Compare commits
	
		
			189 Commits
		
	
	
		
			mesa-24.0.
			...
			mesa_7_7_1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | e33121b2d8 | ||
|  | 415d0326bb | ||
|  | 7e24ce2d9b | ||
|  | 2ae754b7b9 | ||
|  | 501156b36b | ||
|  | 4ff3244457 | ||
|  | 3889556d70 | ||
|  | 6412046f65 | ||
|  | 6e96cea6e2 | ||
|  | 3a3ef3d6c9 | ||
|  | 98aed6dc69 | ||
|  | d3a607f889 | ||
|  | 00e41e007e | ||
|  | 6624845a5d | ||
|  | c9c54180e4 | ||
|  | 93e77b0028 | ||
|  | 0c9e8e6c6e | ||
|  | c50477c255 | ||
|  | 3bf13656d3 | ||
|  | fa4083d38b | ||
|  | d311ded31d | ||
|  | 34f0207161 | ||
|  | 8d3f629a13 | ||
|  | b98ef495d4 | ||
|  | 21c91b410a | ||
|  | a8f3b3f88a | ||
|  | e8a8c5e339 | ||
|  | 7941d31ee6 | ||
|  | 842351dd76 | ||
|  | d74929702f | ||
|  | 1e431f0454 | ||
|  | 4cc8d1d79f | ||
|  | 3d2bc6848a | ||
|  | d5327538e7 | ||
|  | 86ac140937 | ||
|  | b584e780ab | ||
|  | 981e8a2087 | ||
|  | 72d380b363 | ||
|  | cf8af9bcf1 | ||
|  | 7123f3d77a | ||
|  | 2edb1b9534 | ||
|  | 69334d6784 | ||
|  | 61482ddc1c | ||
|  | b0e84e22d5 | ||
|  | c0e8d443fe | ||
|  | b95d4cd680 | ||
|  | 293f4d51b4 | ||
|  | f0e99179bc | ||
|  | 69a94e1452 | ||
|  | bc7e12e5e3 | ||
|  | 7accf8ced6 | ||
|  | 52d83efdbc | ||
|  | 1702db3a35 | ||
|  | fa6eee135e | ||
|  | b5fa760972 | ||
|  | 69cf45cdae | ||
|  | f5ffbe0bc3 | ||
|  | 46d8ca023d | ||
|  | 9bef69782d | ||
|  | b0e5dcb859 | ||
|  | bcd561c667 | ||
|  | c98eced9ae | ||
|  | 13cbb5fff6 | ||
|  | dd8d78c908 | ||
|  | 9d17ad2891 | ||
|  | d437d905e6 | ||
|  | 551c96979e | ||
|  | c1a4f249f1 | ||
|  | 18ff85e91d | ||
|  | 12617c7e30 | ||
|  | 5dbf44953c | ||
|  | a51d638ff3 | ||
|  | 770945cff4 | ||
|  | eaa4066bfc | ||
|  | 46cf606cd3 | ||
|  | a69a7b9688 | ||
|  | eb7590a0d9 | ||
|  | 86870a691c | ||
|  | 7c34c237a2 | ||
|  | 13cd4298fb | ||
|  | 3b724f91c5 | ||
|  | 2077f375c7 | ||
|  | 055265b0a3 | ||
|  | 3094adb3ca | ||
|  | 7c7247ddbf | ||
|  | af2023e31c | ||
|  | 2eedbc94c2 | ||
|  | 672f6bb545 | ||
|  | ab6bcef99a | ||
|  | c5a4cfb03f | ||
|  | df944efdbf | ||
|  | 1ff9cd5079 | ||
|  | 4a2b54cbdb | ||
|  | 6bd6a15ab3 | ||
|  | c1a5c9bb4c | ||
|  | b3c7dc6ff2 | ||
|  | a1025ec041 | ||
|  | 3a4068474c | ||
|  | 1ae976be4a | ||
|  | b685927156 | ||
|  | df0c8d029d | ||
|  | 3477dc4c48 | ||
|  | 0426bccadd | ||
|  | 841333cd21 | ||
|  | e541dceb67 | ||
|  | fea7a70a1a | ||
|  | 426f607aaa | ||
|  | 408f32dc16 | ||
|  | 94028edfc5 | ||
|  | 7fec5f88a5 | ||
|  | 67007670bb | ||
|  | e8865f199d | ||
|  | 2d3262d47d | ||
|  | 3470d821ba | ||
|  | 0371956d66 | ||
|  | 45c4addea7 | ||
|  | 1eba0eb37d | ||
|  | d87fb5e003 | ||
|  | 4be7922a8e | ||
|  | a1cac0732b | ||
|  | fb32e0fcc5 | ||
|  | 9564a6fa13 | ||
|  | 0b9990b2fd | ||
|  | 8ce99c85e7 | ||
|  | a2c402ba53 | ||
|  | 1ceb906c12 | ||
|  | fb1fe8e76f | ||
|  | f8b05566aa | ||
|  | a6148b8eba | ||
|  | 64be837b0b | ||
|  | e070c1d183 | ||
|  | e6ee4b49c4 | ||
|  | e65029e9b3 | ||
|  | 3ca6cb3440 | ||
|  | 34b36277b7 | ||
|  | c8ea0212fe | ||
|  | 7d6cbcdd9a | ||
|  | 9d9c1f17dc | ||
|  | f1afb352da | ||
|  | e4c3abbf55 | ||
|  | 141b5775c0 | ||
|  | c0d5f1d3ad | ||
|  | 70947e531e | ||
|  | 7b92cb45b2 | ||
|  | 43e4b58422 | ||
|  | e0d01c9d7f | ||
|  | b90b3667a1 | ||
|  | 0123a2d042 | ||
|  | 51a2cc5499 | ||
|  | f5145a6ec3 | ||
|  | ddedfe12d4 | ||
|  | cb5447f79c | ||
|  | 9fd3c74724 | ||
|  | 4d1234e222 | ||
|  | 3cba779e16 | ||
|  | 23eda89ec8 | ||
|  | 6e68898b05 | ||
|  | 1befcd5a2a | ||
|  | 12ba355978 | ||
|  | a0907a645f | ||
|  | 1acf7a09e7 | ||
|  | 14dc02a1b2 | ||
|  | 88cf87bd56 | ||
|  | 31b3420688 | ||
|  | 4e95983fa8 | ||
|  | 4e506eac8f | ||
|  | 46167149ce | ||
|  | 96ec4eb755 | ||
|  | e20547042c | ||
|  | 0451d0fd01 | ||
|  | aa8b23e077 | ||
|  | 4eb48a3af7 | ||
|  | 8db8adfd01 | ||
|  | 8e240d7e0e | ||
|  | 40298bf272 | ||
|  | a0518e66b2 | ||
|  | 82c76cd16f | ||
|  | 50e890bc51 | ||
|  | bba9557019 | ||
|  | 2041d3e4b7 | ||
|  | 77b7b3a1ab | ||
|  | 0dab80fbfb | ||
|  | e3257912e0 | ||
|  | 15fe491822 | ||
|  | ac597f5acc | ||
|  | 5cb255f0d7 | ||
|  | 2f28ca0a27 | ||
|  | 0580e488da | ||
|  | 5435f790fd | 
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -182,7 +182,7 @@ ultrix-gcc: | ||||
|  | ||||
| # Rules for making release tarballs | ||||
|  | ||||
| VERSION=7.7.1-devel | ||||
| VERSION=7.7.1-rc2 | ||||
| DIRECTORY = Mesa-$(VERSION) | ||||
| LIB_NAME = MesaLib-$(VERSION) | ||||
| DEMO_NAME = MesaDemos-$(VERSION) | ||||
|   | ||||
| @@ -920,6 +920,11 @@ case $ARCH in | ||||
|  | ||||
|             # make lib | ||||
|             ${LINK} ${OPTS} ${LDFLAGS} -o ${CYGNAME}-${MAJOR}.dll ${OBJECTS} ${DEPS} | ||||
|             # make build fail if link failed | ||||
|             es=$? | ||||
|             if [ "$es" -ne "0" ]; then | ||||
|                 exit $es | ||||
|             fi | ||||
|             # make usual symlinks | ||||
|             ln -s ${LIBNAME}-${MAJOR}.dll.a ${LIBNAME}.dll.a | ||||
|             # finish up | ||||
|   | ||||
							
								
								
									
										19
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -20,6 +20,8 @@ AC_CANONICAL_HOST | ||||
| dnl Versions for external dependencies | ||||
| LIBDRM_REQUIRED=2.4.15 | ||||
| LIBDRM_RADEON_REQUIRED=2.4.17 | ||||
| LIBDRM_XORG_REQUIRED=2.4.17 | ||||
| LIBKMS_XORG_REQUIRED=1.0.0 | ||||
| DRI2PROTO_REQUIRED=1.99.3 | ||||
|  | ||||
| dnl Check for progs | ||||
| @@ -91,6 +93,9 @@ linux*|*-gnu*|gnu*) | ||||
| solaris*) | ||||
|     DEFINES="$DEFINES -DPTHREADS -DSVR4" | ||||
|     ;; | ||||
| cygwin*) | ||||
|     DEFINES="$DEFINES -DPTHREADS" | ||||
|     ;; | ||||
| esac | ||||
|  | ||||
| dnl Add flags for gcc and g++ | ||||
| @@ -1149,7 +1154,7 @@ yes) | ||||
|             GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl" | ||||
|         fi | ||||
|         # Have only tested st/xorg on 1.6.0 servers | ||||
|         PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0], | ||||
|         PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0 libdrm >= $LIBDRM_XORG_REQUIRED libkms >= $LIBKMS_XORG_REQUIRED], | ||||
|             HAVE_XORG="yes"; GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS xorg", | ||||
|             HAVE_XORG="no") | ||||
|         ;; | ||||
| @@ -1166,15 +1171,21 @@ yes) | ||||
|             AC_MSG_ERROR([cannot build egl state tracker without EGL library]) | ||||
|         fi | ||||
|         if test "$tracker" = xorg; then | ||||
| 	    PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], | ||||
|                   HAVE_XEXTPROTO_71="yes"; DEFINES="$DEFINES -DHAVE_XEXTPROTO_71", | ||||
|                   HAVE_XEXTPROTO_71="no") | ||||
|             PKG_CHECK_MODULES([LIBDRM_XORG], [libdrm >= $LIBDRM_XORG_REQUIRED]) | ||||
|             PKG_CHECK_MODULES([LIBKMS_XORG], [libkms >= $LIBKMS_XORG_REQUIRED]) | ||||
|             HAVE_XORG="yes" | ||||
|         fi | ||||
|     done | ||||
|     GALLIUM_STATE_TRACKERS_DIRS="$state_trackers" | ||||
|     ;; | ||||
| esac | ||||
|  | ||||
| if test "x$HAVE_XORG" = xyes; then | ||||
|     PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], | ||||
|         HAVE_XEXTPROTO_71="yes"; DEFINES="$DEFINES -DHAVE_XEXTPROTO_71", | ||||
|         HAVE_XEXTPROTO_71="no") | ||||
| fi | ||||
|  | ||||
| AC_ARG_WITH([xorg-driver-dir], | ||||
|     [AS_HELP_STRING([--with-xorg-driver-dir=DIR], | ||||
|                     [Default xorg driver directory[[default=${libdir}/xorg/modules/drivers]]])], | ||||
|   | ||||
| @@ -26,7 +26,7 @@ more information about the API functions. | ||||
| </p> | ||||
|  | ||||
| <p> | ||||
| There are several examples of OSMesa in the <code>progs/osdemo/</code> | ||||
| There are several examples of OSMesa in the <code>progs/osdemos/</code> | ||||
| directory. | ||||
| </p> | ||||
|  | ||||
|   | ||||
| @@ -30,12 +30,6 @@ tbd | ||||
| </pre> | ||||
|  | ||||
|  | ||||
| <h2>New features</h2> | ||||
| <ul> | ||||
| <li>tbd | ||||
| </ul> | ||||
|  | ||||
|  | ||||
| <h2>Bug fixes</h2> | ||||
| <ul> | ||||
| <li>Assorted fixes to VMware SVGA gallium driver. | ||||
| @@ -43,6 +37,14 @@ tbd | ||||
| <li>Allocate constants more tightly in GL_ARB_vertex/fragment parser. | ||||
| <li>Fixed mipmap generation bug caused by invalid viewport state. | ||||
| <li>Gallium SSE codegen for XPD didn't always work. | ||||
| <li>Fixed Windows build. | ||||
| <li>Fixed broken glMultiDrawElements(). | ||||
| <li>Silence bogus GL errors generated in glxinfo. | ||||
| <li>Fixed several render to texture bugs. | ||||
| <li>Assorted bug fixes in Mesa/Gallium state tracker including | ||||
|     glCopy/DrawPixels() to FBOs. | ||||
| <li>Assorted fixes to Gallium drivers. | ||||
| <li>Fixed broken glPush/PopClientAttrib() for vertex arrays in GLX code. | ||||
| </ul> | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <HTML> | ||||
|  | ||||
| <TITLE>Cocd Repository</TITLE> | ||||
| <TITLE>Code Repository</TITLE> | ||||
|  | ||||
| <link rel="stylesheet" type="text/css" href="mesa.css"></head> | ||||
|  | ||||
|   | ||||
| @@ -171,7 +171,7 @@ print_program_limits(GLenum target) | ||||
|       GLenum token; | ||||
|       const char *name; | ||||
|    }; | ||||
|    static const struct token_name limits[] = { | ||||
|    static const struct token_name common_limits[] = { | ||||
|       { GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_INSTRUCTIONS_ARB" }, | ||||
|       { GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB" }, | ||||
|       { GL_MAX_PROGRAM_TEMPORARIES_ARB, "GL_MAX_PROGRAM_TEMPORARIES_ARB" }, | ||||
| @@ -184,6 +184,9 @@ print_program_limits(GLenum target) | ||||
|       { GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB" }, | ||||
|       { GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB" }, | ||||
|       { GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB" }, | ||||
|       { (GLenum) 0, NULL } | ||||
|    }; | ||||
|    static const struct token_name fragment_limits[] = { | ||||
|       { GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB" }, | ||||
|       { GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB" }, | ||||
|       { GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB" }, | ||||
| @@ -192,8 +195,10 @@ print_program_limits(GLenum target) | ||||
|       { GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB" }, | ||||
|       { (GLenum) 0, NULL } | ||||
|    }; | ||||
|  | ||||
|    PFNGLGETPROGRAMIVARBPROC GetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC) | ||||
|       glXGetProcAddressARB((GLubyte *) "glGetProgramivARB"); | ||||
|  | ||||
|    GLint max[1]; | ||||
|    int i; | ||||
|  | ||||
| @@ -207,10 +212,18 @@ print_program_limits(GLenum target) | ||||
|       return; /* something's wrong */ | ||||
|    } | ||||
|  | ||||
|    for (i = 0; limits[i].token; i++) { | ||||
|       GetProgramivARB_func(target, limits[i].token, max); | ||||
|    for (i = 0; common_limits[i].token; i++) { | ||||
|       GetProgramivARB_func(target, common_limits[i].token, max); | ||||
|       if (glGetError() == GL_NO_ERROR) { | ||||
|          printf("        %s = %d\n", limits[i].name, max[0]); | ||||
|          printf("        %s = %d\n", common_limits[i].name, max[0]); | ||||
|       } | ||||
|    } | ||||
|    if (target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       for (i = 0; fragment_limits[i].token; i++) { | ||||
|          GetProgramivARB_func(target, fragment_limits[i].token, max); | ||||
|          if (glGetError() == GL_NO_ERROR) { | ||||
|             printf("        %s = %d\n", fragment_limits[i].name, max[0]); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| #endif /* GL_ARB_vertex_program / GL_ARB_fragment_program */ | ||||
|   | ||||
| @@ -53,6 +53,7 @@ prefixes = SCons.Util.Split(""" | ||||
|     i486-mingw32msvc- | ||||
|     i586-mingw32msvc- | ||||
|     i686-mingw32msvc- | ||||
|     i686-pc-mingw32- | ||||
| """) | ||||
|  | ||||
| def find(env): | ||||
|   | ||||
| @@ -235,7 +235,9 @@ def generate(env): | ||||
|     # different scons versions building the same source file | ||||
|     env['build'] = build_dir | ||||
|     env.SConsignFile(os.path.join(build_dir, '.sconsign')) | ||||
|     env.CacheDir('build/cache') | ||||
|     if 'SCONS_CACHE_DIR' in os.environ: | ||||
|         print 'scons: Using build cache in %s.' % (os.environ['SCONS_CACHE_DIR'],) | ||||
|         env.CacheDir(os.environ['SCONS_CACHE_DIR']) | ||||
|  | ||||
|     # Parallel build | ||||
|     if env.GetOption('num_jobs') <= 1: | ||||
| @@ -255,8 +257,9 @@ def generate(env): | ||||
|             '_WINDOWS', | ||||
|             #'_UNICODE', | ||||
|             #'UNICODE', | ||||
|             ('_WIN32_WINNT', '0x0501'), # minimum required OS version | ||||
|             ('WINVER', '0x0501'), | ||||
|             # http://msdn.microsoft.com/en-us/library/aa383745.aspx | ||||
|             ('_WIN32_WINNT', '0x0601'), | ||||
|             ('WINVER', '0x0601'), | ||||
|             # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx, | ||||
|             'WIN32_LEAN_AND_MEAN', | ||||
|         ] | ||||
|   | ||||
| @@ -347,7 +347,8 @@ vcache_check_run( struct draw_pt_front_end *frontend, | ||||
|                        draw_count); | ||||
|        | ||||
|    if (max_index == 0xffffffff || | ||||
|        fetch_count > draw_count) { | ||||
|        fetch_count > draw_count || | ||||
|        max_index != (max_index & ~DRAW_PIPE_FLAG_MASK)) { | ||||
|       if (0) debug_printf("fail\n"); | ||||
|       goto fail; | ||||
|    } | ||||
|   | ||||
| @@ -179,7 +179,9 @@ pb_debug_buffer_check(struct pb_debug_buffer *buf) | ||||
| { | ||||
|    uint8_t *map; | ||||
|     | ||||
|    map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_READ); | ||||
|    map = pb_map(buf->buffer, | ||||
|                 PIPE_BUFFER_USAGE_CPU_READ | | ||||
|                 PIPE_BUFFER_USAGE_UNSYNCHRONIZED); | ||||
|    assert(map); | ||||
|    if(map) { | ||||
|       boolean underflow, overflow; | ||||
|   | ||||
| @@ -133,8 +133,7 @@ static const union tgsi_exec_channel ZeroVec = | ||||
|    { { 0.0, 0.0, 0.0, 0.0 } }; | ||||
|  | ||||
|  | ||||
| #ifdef DEBUG | ||||
| static void | ||||
| static INLINE void | ||||
| check_inf_or_nan(const union tgsi_exec_channel *chan) | ||||
| { | ||||
|    assert(!util_is_inf_or_nan(chan->f[0])); | ||||
| @@ -142,7 +141,6 @@ check_inf_or_nan(const union tgsi_exec_channel *chan) | ||||
|    assert(!util_is_inf_or_nan(chan->f[2])); | ||||
|    assert(!util_is_inf_or_nan(chan->f[3])); | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef DEBUG | ||||
| @@ -338,7 +336,9 @@ tgsi_exec_machine_bind_shader( | ||||
|             /* XXX we only handle SOA dependencies properly for MOV/SWZ | ||||
|              * at this time! | ||||
|              */ | ||||
|             if (opcode != TGSI_OPCODE_MOV) { | ||||
|             if (opcode != TGSI_OPCODE_MOV && | ||||
|                 opcode != TGSI_OPCODE_MUL && | ||||
|                 opcode != TGSI_OPCODE_CMP) { | ||||
|                debug_printf("Warning: SOA dependency in instruction" | ||||
|                             " is not handled:\n"); | ||||
|                tgsi_dump_instruction(&parse.FullToken.FullInstruction, | ||||
| @@ -1424,9 +1424,9 @@ store_dest( | ||||
|    int offset = 0;  /* indirection offset */ | ||||
|    int index; | ||||
|  | ||||
| #ifdef DEBUG | ||||
|    check_inf_or_nan(chan); | ||||
| #endif | ||||
|    if (0) { | ||||
|       check_inf_or_nan(chan); | ||||
|    } | ||||
|  | ||||
|    /* There is an extra source register that indirectly subscripts | ||||
|     * a register file. The direct index now becomes an offset | ||||
| @@ -1854,7 +1854,8 @@ exec_instruction( | ||||
|    int *pc ) | ||||
| { | ||||
|    uint chan_index; | ||||
|    union tgsi_exec_channel r[10]; | ||||
|    union tgsi_exec_channel r[3 * NUM_CHANNELS]; | ||||
|    union tgsi_exec_channel d[8]; | ||||
|  | ||||
|    (*pc)++; | ||||
|  | ||||
| @@ -1981,14 +1982,27 @@ exec_instruction( | ||||
|       break; | ||||
|  | ||||
|    case TGSI_OPCODE_MUL: | ||||
|       FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) | ||||
|       { | ||||
|          FETCH(&r[0], 0, chan_index); | ||||
|          FETCH(&r[1], 1, chan_index); | ||||
|       if (inst->Flags & SOA_DEPENDENCY_FLAG) { | ||||
|          FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) | ||||
|          { | ||||
|             FETCH(&r[chan_index], 0, chan_index); | ||||
|             FETCH(&r[chan_index + NUM_CHANNELS], 1, chan_index); | ||||
|          } | ||||
|          FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) | ||||
|          { | ||||
|             micro_mul( &r[chan_index], &r[chan_index], &r[chan_index + NUM_CHANNELS] ); | ||||
|             STORE(&r[chan_index], 0, chan_index); | ||||
|          } | ||||
|       } else { | ||||
|          FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) | ||||
|          { | ||||
|             FETCH(&r[0], 0, chan_index); | ||||
|             FETCH(&r[1], 1, chan_index); | ||||
|  | ||||
|          micro_mul( &r[0], &r[0], &r[1] ); | ||||
|             micro_mul( &r[0], &r[0], &r[1] ); | ||||
|  | ||||
|          STORE(&r[0], 0, chan_index); | ||||
|             STORE(&r[0], 0, chan_index); | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
| @@ -2255,11 +2269,7 @@ exec_instruction( | ||||
|       FETCH(&r[4], 1, CHAN_Y); | ||||
|  | ||||
|       micro_mul( &r[5], &r[3], &r[4] ); | ||||
|       micro_sub( &r[2], &r[2], &r[5] ); | ||||
|  | ||||
|       if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) { | ||||
|          STORE( &r[2], 0, CHAN_X ); | ||||
|       } | ||||
|       micro_sub(&d[CHAN_X], &r[2], &r[5]); | ||||
|  | ||||
|       FETCH(&r[2], 1, CHAN_X); | ||||
|  | ||||
| @@ -2268,26 +2278,27 @@ exec_instruction( | ||||
|       FETCH(&r[5], 0, CHAN_X); | ||||
|  | ||||
|       micro_mul( &r[1], &r[1], &r[5] ); | ||||
|       micro_sub( &r[3], &r[3], &r[1] ); | ||||
|  | ||||
|       if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) { | ||||
|          STORE( &r[3], 0, CHAN_Y ); | ||||
|       } | ||||
|       micro_sub(&d[CHAN_Y], &r[3], &r[1]); | ||||
|  | ||||
|       micro_mul( &r[5], &r[5], &r[4] ); | ||||
|       micro_mul( &r[0], &r[0], &r[2] ); | ||||
|       micro_sub( &r[5], &r[5], &r[0] ); | ||||
|       micro_sub(&d[CHAN_Z], &r[5], &r[0]); | ||||
|  | ||||
|       if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) { | ||||
|          STORE( &r[5], 0, CHAN_Z ); | ||||
|       if (IS_CHANNEL_ENABLED(*inst, CHAN_X)) { | ||||
|          STORE(&d[CHAN_X], 0, CHAN_X); | ||||
|       } | ||||
|       if (IS_CHANNEL_ENABLED(*inst, CHAN_Y)) { | ||||
|          STORE(&d[CHAN_Y], 0, CHAN_Y); | ||||
|       } | ||||
|       if (IS_CHANNEL_ENABLED(*inst, CHAN_Z)) { | ||||
|          STORE(&d[CHAN_Z], 0, CHAN_Z); | ||||
|       } | ||||
|  | ||||
|       if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) { | ||||
|          STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W ); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case TGSI_OPCODE_ABS: | ||||
|    case TGSI_OPCODE_ABS: | ||||
|        FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | ||||
|           FETCH(&r[0], 0, chan_index); | ||||
|  | ||||
| @@ -2667,14 +2678,28 @@ exec_instruction( | ||||
|       break; | ||||
|  | ||||
|    case TGSI_OPCODE_CMP: | ||||
|       FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | ||||
|          FETCH(&r[0], 0, chan_index); | ||||
|          FETCH(&r[1], 1, chan_index); | ||||
|          FETCH(&r[2], 2, chan_index); | ||||
|       if (inst->Flags & SOA_DEPENDENCY_FLAG) { | ||||
|          FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | ||||
|             FETCH(&r[chan_index], 0, chan_index); | ||||
|             FETCH(&r[chan_index + NUM_CHANNELS], 1, chan_index); | ||||
|             FETCH(&r[chan_index + 2 * NUM_CHANNELS], 2, chan_index); | ||||
|          } | ||||
|          FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | ||||
|             micro_lt( &r[chan_index], &r[chan_index], | ||||
|                       &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[chan_index + NUM_CHANNELS], | ||||
|                       &r[chan_index + 2*NUM_CHANNELS] ); | ||||
|             STORE(&r[chan_index], 0, chan_index); | ||||
|          } | ||||
|       } else { | ||||
|          FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | ||||
|             FETCH(&r[0], 0, chan_index); | ||||
|             FETCH(&r[1], 1, chan_index); | ||||
|             FETCH(&r[2], 2, chan_index); | ||||
|  | ||||
|          micro_lt( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[1], &r[2] ); | ||||
|             micro_lt( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[1], &r[2] ); | ||||
|  | ||||
|          STORE(&r[0], 0, chan_index); | ||||
|             STORE(&r[0], 0, chan_index); | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|   | ||||
| @@ -216,6 +216,9 @@ iter_instruction( | ||||
|          inst->FullDstRegisters[i].DstRegister.Index, | ||||
|          "destination", | ||||
|          FALSE ); | ||||
|       if (!inst->FullDstRegisters[i].DstRegister.WriteMask) { | ||||
|          report_error(ctx, "Destination register has empty writemask"); | ||||
|       } | ||||
|    } | ||||
|    for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { | ||||
|       check_register_usage( | ||||
|   | ||||
| @@ -644,6 +644,57 @@ void debug_dump_image(const char *prefix, | ||||
|    } | ||||
|        | ||||
|    EngUnmapFile(iFile); | ||||
| #elif defined(PIPE_OS_UNIX) | ||||
|    /* write a ppm file */ | ||||
|    char filename[256]; | ||||
|    FILE *f; | ||||
|  | ||||
|    util_snprintf(filename, sizeof(filename), "%s.ppm", prefix); | ||||
|  | ||||
|    f = fopen(filename, "w"); | ||||
|    if (f) { | ||||
|       int i, x, y; | ||||
|       int r, g, b; | ||||
|       const uint8_t *ptr = (uint8_t *) data; | ||||
|  | ||||
|       /* XXX this is a hack */ | ||||
|       switch (format) { | ||||
|       case PIPE_FORMAT_B8G8R8A8_UNORM: | ||||
|          r = 2; | ||||
|          g = 1; | ||||
|          b = 0; | ||||
|          break; | ||||
|       case PIPE_FORMAT_A8R8G8B8_UNORM: | ||||
|          b = 0; | ||||
|          g = 1; | ||||
|          r = 2; | ||||
|          break; | ||||
|       default: | ||||
|          r = 0; | ||||
|          g = 1; | ||||
|          b = 2; | ||||
|       } | ||||
|  | ||||
|       fprintf(f, "P6\n"); | ||||
|       fprintf(f, "# ppm-file created by osdemo.c\n"); | ||||
|       fprintf(f, "%i %i\n", width, height); | ||||
|       fprintf(f, "255\n"); | ||||
|       fclose(f); | ||||
|  | ||||
|       f = fopen(filename, "ab");  /* reopen in binary append mode */ | ||||
|       for (y = 0; y < height; y++) { | ||||
|          for (x = 0; x < width; x++) { | ||||
|             i = y * stride + x * cpp; | ||||
|             fputc(ptr[i + r], f); /* write red */ | ||||
|             fputc(ptr[i + g], f); /* write green */ | ||||
|             fputc(ptr[i + b], f); /* write blue */ | ||||
|          } | ||||
|       } | ||||
|       fclose(f); | ||||
|    } | ||||
|    else { | ||||
|       fprintf(stderr, "Can't open %s for writing\n", filename); | ||||
|    } | ||||
| #endif | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -628,7 +628,8 @@ lp_build_abs(struct lp_build_context *bld, | ||||
|    if(type.floating) { | ||||
|       /* Mask out the sign bit */ | ||||
|       LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); | ||||
|       LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long)1 << type.width) - 1); | ||||
|       unsigned long absMask = ~(1 << (type.width - 1)); | ||||
|       LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask)); | ||||
|       a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); | ||||
|       a = LLVMBuildAnd(bld->builder, a, mask, ""); | ||||
|       a = LLVMBuildBitCast(bld->builder, a, vec_type, ""); | ||||
| @@ -1082,7 +1083,7 @@ lp_build_log(struct lp_build_context *bld, | ||||
|              LLVMValueRef x) | ||||
| { | ||||
|    /* log(2) */ | ||||
|    LLVMValueRef log2 = lp_build_const_scalar(bld->type, 1.4426950408889634); | ||||
|    LLVMValueRef log2 = lp_build_const_scalar(bld->type, 0.69314718055994529); | ||||
|  | ||||
|    return lp_build_mul(bld, log2, lp_build_exp2(bld, x)); | ||||
| } | ||||
| @@ -1094,7 +1095,7 @@ lp_build_log(struct lp_build_context *bld, | ||||
|  | ||||
| /** | ||||
|  * Generate polynomial. | ||||
|  * Ex:  x^2 * coeffs[0] + x * coeffs[1] + coeffs[2]. | ||||
|  * Ex:  coeffs[0] + x * coeffs[1] + x^2 * coeffs[2]. | ||||
|  */ | ||||
| static LLVMValueRef | ||||
| lp_build_polynomial(struct lp_build_context *bld, | ||||
| @@ -1284,13 +1285,13 @@ lp_build_log2_approx(struct lp_build_context *bld, | ||||
|       /* mant = (float) mantissa(x) */ | ||||
|       mant = LLVMBuildAnd(bld->builder, i, mantmask, ""); | ||||
|       mant = LLVMBuildOr(bld->builder, mant, one, ""); | ||||
|       mant = LLVMBuildSIToFP(bld->builder, mant, vec_type, ""); | ||||
|       mant = LLVMBuildBitCast(bld->builder, mant, vec_type, ""); | ||||
|  | ||||
|       logmant = lp_build_polynomial(bld, mant, lp_build_log2_polynomial, | ||||
|                                     Elements(lp_build_log2_polynomial)); | ||||
|  | ||||
|       /* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/ | ||||
|       logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildMul(bld->builder, mant, bld->one, ""), ""); | ||||
|       logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildSub(bld->builder, mant, bld->one, ""), ""); | ||||
|  | ||||
|       res = LLVMBuildAdd(bld->builder, logmant, logexp, ""); | ||||
|    } | ||||
|   | ||||
| @@ -766,7 +766,7 @@ emit_instruction( | ||||
|       FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { | ||||
|          src0 = emit_fetch( bld, inst, 0, chan_index ); | ||||
|          tmp0 = lp_build_floor(&bld->base, src0); | ||||
|          tmp0 = lp_build_sub(&bld->base, tmp0, src0); | ||||
|          tmp0 = lp_build_sub(&bld->base, src0, tmp0); | ||||
|          dst0[chan_index] = tmp0; | ||||
|       } | ||||
|       break; | ||||
|   | ||||
							
								
								
									
										71
									
								
								src/gallium/drivers/llvmpipe/lp_debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/gallium/drivers/llvmpipe/lp_debug.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #ifndef LP_DEBUG_H | ||||
| #define LP_DEBUG_H | ||||
|  | ||||
| #include "pipe/p_compiler.h" | ||||
| #include "util/u_debug.h" | ||||
|  | ||||
| extern void | ||||
| st_print_current(void); | ||||
|  | ||||
|  | ||||
| #define DEBUG_PIPE      0x1 | ||||
| #define DEBUG_TGSI      0x2 | ||||
| #define DEBUG_TEX       0x4 | ||||
| #define DEBUG_ASM       0x8 | ||||
| #define DEBUG_SETUP     0x10 | ||||
| #define DEBUG_RAST      0x20 | ||||
| #define DEBUG_QUERY     0x40 | ||||
| #define DEBUG_SCREEN    0x80 | ||||
| #define DEBUG_JIT       0x100 | ||||
|  | ||||
| #ifdef DEBUG | ||||
| extern int LP_DEBUG; | ||||
| #else | ||||
| #define LP_DEBUG 0 | ||||
| #endif | ||||
|  | ||||
| void st_debug_init( void ); | ||||
|  | ||||
| static INLINE void | ||||
| LP_DBG( unsigned flag, const char *fmt, ... ) | ||||
| { | ||||
|     if (LP_DEBUG & flag) | ||||
|     { | ||||
|         va_list args; | ||||
|  | ||||
|         va_start( args, fmt ); | ||||
|         debug_vprintf( fmt, args ); | ||||
|         va_end( args ); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif /* LP_DEBUG_H */ | ||||
| @@ -101,7 +101,7 @@ llvmpipe_draw_range_elements(struct pipe_context *pipe, | ||||
|    draw_arrays(draw, mode, start, count); | ||||
|  | ||||
|    /* | ||||
|     * unmap vertex/index buffers - will cause draw module to flush | ||||
|     * unmap vertex/index buffers | ||||
|     */ | ||||
|    for (i = 0; i < lp->num_vertex_buffers; i++) { | ||||
|       draw_set_mapped_vertex_buffer(draw, i, NULL); | ||||
| @@ -110,6 +110,12 @@ llvmpipe_draw_range_elements(struct pipe_context *pipe, | ||||
|       draw_set_mapped_element_buffer(draw, 0, NULL); | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * TODO: Flush only when a user vertex/index buffer is present | ||||
|     * (or even better, modify draw module to do this | ||||
|     * internally when this condition is seen?) | ||||
|     */ | ||||
|    draw_flush(draw); | ||||
|  | ||||
|    /* Note: leave drawing surfaces mapped */ | ||||
|  | ||||
|   | ||||
| @@ -166,7 +166,7 @@ lp_jit_screen_init(struct llvmpipe_screen *screen) | ||||
|    if (LLVMCreateJITCompiler(&screen->engine, screen->provider, 1, &error)) { | ||||
|       _debug_printf("%s\n", error); | ||||
|       LLVMDisposeMessage(error); | ||||
|       abort(); | ||||
|       assert(0); | ||||
|    } | ||||
|  | ||||
|    screen->target = LLVMGetExecutionEngineTargetData(screen->engine); | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
|  | ||||
|  | ||||
| #include "util/u_memory.h" | ||||
| #include "util/u_format.h" | ||||
| #include "pipe/p_defines.h" | ||||
| #include "pipe/p_screen.h" | ||||
|  | ||||
| @@ -35,6 +36,24 @@ | ||||
| #include "lp_winsys.h" | ||||
| #include "lp_jit.h" | ||||
| #include "lp_screen.h" | ||||
| #include "lp_debug.h" | ||||
|  | ||||
| #ifdef DEBUG | ||||
| int LP_DEBUG = 0; | ||||
|  | ||||
| static const struct debug_named_value lp_debug_flags[] = { | ||||
|    { "pipe",   DEBUG_PIPE }, | ||||
|    { "tgsi",   DEBUG_TGSI }, | ||||
|    { "tex",    DEBUG_TEX }, | ||||
|    { "asm",    DEBUG_ASM }, | ||||
|    { "setup",  DEBUG_SETUP }, | ||||
|    { "rast",   DEBUG_RAST }, | ||||
|    { "query",  DEBUG_QUERY }, | ||||
|    { "screen", DEBUG_SCREEN }, | ||||
|    { "jit",    DEBUG_JIT }, | ||||
|    {NULL, 0} | ||||
| }; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| static const char * | ||||
| @@ -131,17 +150,17 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, | ||||
| { | ||||
|    struct llvmpipe_screen *screen = llvmpipe_screen(_screen); | ||||
|    struct llvmpipe_winsys *winsys = screen->winsys; | ||||
|    const struct util_format_description *format_desc; | ||||
|  | ||||
|    format_desc = util_format_description(format); | ||||
|    if(!format_desc) | ||||
|       return FALSE; | ||||
|  | ||||
|    assert(target == PIPE_TEXTURE_1D || | ||||
|           target == PIPE_TEXTURE_2D || | ||||
|           target == PIPE_TEXTURE_3D || | ||||
|           target == PIPE_TEXTURE_CUBE); | ||||
|  | ||||
|    if(format == PIPE_FORMAT_Z16_UNORM) | ||||
|       return FALSE; | ||||
|    if(format == PIPE_FORMAT_S8_UNORM) | ||||
|       return FALSE; | ||||
|  | ||||
|    switch(format) { | ||||
|    case PIPE_FORMAT_DXT1_RGB: | ||||
|    case PIPE_FORMAT_DXT1_RGBA: | ||||
| @@ -152,8 +171,51 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) | ||||
|       return winsys->is_displaytarget_format_supported(winsys, format); | ||||
|    if(tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { | ||||
|       if(format_desc->block.width != 1 || | ||||
|          format_desc->block.height != 1) | ||||
|          return FALSE; | ||||
|  | ||||
|       if(format_desc->layout != UTIL_FORMAT_LAYOUT_SCALAR && | ||||
|          format_desc->layout != UTIL_FORMAT_LAYOUT_ARITH && | ||||
|          format_desc->layout != UTIL_FORMAT_LAYOUT_ARRAY) | ||||
|          return FALSE; | ||||
|  | ||||
|       if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB && | ||||
|          format_desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) | ||||
|          return FALSE; | ||||
|    } | ||||
|  | ||||
|    if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { | ||||
|       if(!winsys->is_displaytarget_format_supported(winsys, format)) | ||||
|          return FALSE; | ||||
|    } | ||||
|  | ||||
|    if(tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { | ||||
|       if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) | ||||
|          return FALSE; | ||||
|  | ||||
|       /* FIXME: Temporary restriction. See lp_state_fs.c. */ | ||||
|       if(format_desc->block.bits != 32) | ||||
|          return FALSE; | ||||
|    } | ||||
|  | ||||
|    /* FIXME: Temporary restrictions. See lp_bld_sample_soa.c */ | ||||
|    if(tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) { | ||||
|       if(format_desc->block.width != 1 || | ||||
|          format_desc->block.height != 1) | ||||
|          return FALSE; | ||||
|  | ||||
|       if(format_desc->layout != UTIL_FORMAT_LAYOUT_SCALAR && | ||||
|          format_desc->layout != UTIL_FORMAT_LAYOUT_ARITH && | ||||
|          format_desc->layout != UTIL_FORMAT_LAYOUT_ARRAY) | ||||
|          return FALSE; | ||||
|  | ||||
|       if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB && | ||||
|          format_desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB && | ||||
|          format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) | ||||
|          return FALSE; | ||||
|    } | ||||
|  | ||||
|    return TRUE; | ||||
| } | ||||
| @@ -213,6 +275,10 @@ llvmpipe_create_screen(struct llvmpipe_winsys *winsys) | ||||
| { | ||||
|    struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen); | ||||
|  | ||||
| #ifdef DEBUG | ||||
|    LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 ); | ||||
| #endif | ||||
|  | ||||
|    if (!screen) | ||||
|       return NULL; | ||||
|  | ||||
|   | ||||
| @@ -34,6 +34,7 @@ | ||||
| #include "util/u_memory.h" | ||||
| #include "util/u_math.h" | ||||
| #include "util/u_debug_dump.h" | ||||
| #include "draw/draw_context.h" | ||||
| #include "lp_screen.h" | ||||
| #include "lp_context.h" | ||||
| #include "lp_state.h" | ||||
| @@ -51,6 +52,11 @@ void llvmpipe_bind_blend_state( struct pipe_context *pipe, | ||||
| { | ||||
|    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); | ||||
|  | ||||
|    if (llvmpipe->blend == blend) | ||||
|       return; | ||||
|  | ||||
|    draw_flush(llvmpipe->draw); | ||||
|  | ||||
|    llvmpipe->blend = blend; | ||||
|  | ||||
|    llvmpipe->dirty |= LP_NEW_BLEND; | ||||
| @@ -69,6 +75,11 @@ void llvmpipe_set_blend_color( struct pipe_context *pipe, | ||||
|    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); | ||||
|    unsigned i, j; | ||||
|  | ||||
|    if(memcmp(&llvmpipe->blend_color, blend_color, sizeof *blend_color) == 0) | ||||
|       return; | ||||
|  | ||||
|    draw_flush(llvmpipe->draw); | ||||
|  | ||||
|    memcpy(&llvmpipe->blend_color, blend_color, sizeof *blend_color); | ||||
|  | ||||
|    if(!llvmpipe->jit_context.blend_color) | ||||
| @@ -99,7 +110,12 @@ llvmpipe_bind_depth_stencil_state(struct pipe_context *pipe, | ||||
| { | ||||
|    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); | ||||
|  | ||||
|    llvmpipe->depth_stencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil; | ||||
|    if (llvmpipe->depth_stencil == depth_stencil) | ||||
|       return; | ||||
|  | ||||
|    draw_flush(llvmpipe->draw); | ||||
|  | ||||
|    llvmpipe->depth_stencil = depth_stencil; | ||||
|  | ||||
|    if(llvmpipe->depth_stencil) | ||||
|       llvmpipe->jit_context.alpha_ref_value = llvmpipe->depth_stencil->alpha.ref_value; | ||||
|   | ||||
| @@ -85,6 +85,7 @@ | ||||
| #include "lp_buffer.h" | ||||
| #include "lp_state.h" | ||||
| #include "lp_tex_sample.h" | ||||
| #include "lp_debug.h" | ||||
|  | ||||
|  | ||||
| static const unsigned char quad_offset_x[4] = {0, 1, 0, 1}; | ||||
| @@ -146,6 +147,20 @@ generate_depth(LLVMBuilderRef builder, | ||||
|    format_desc = util_format_description(key->zsbuf_format); | ||||
|    assert(format_desc); | ||||
|  | ||||
|    /* | ||||
|     * Depths are expected to be between 0 and 1, even if they are stored in | ||||
|     * floats. Setting these bits here will ensure that the lp_build_conv() call | ||||
|     * below won't try to unnecessarily clamp the incoming values. | ||||
|     */ | ||||
|    if(src_type.floating) { | ||||
|       src_type.sign = FALSE; | ||||
|       src_type.norm = TRUE; | ||||
|    } | ||||
|    else { | ||||
|       assert(!src_type.sign); | ||||
|       assert(src_type.norm); | ||||
|    } | ||||
|  | ||||
|    /* Pick the depth type. */ | ||||
|    dst_type = lp_depth_type(format_desc, src_type.width*src_type.length); | ||||
|  | ||||
| @@ -153,14 +168,11 @@ generate_depth(LLVMBuilderRef builder, | ||||
|    assert(dst_type.width == src_type.width); | ||||
|    assert(dst_type.length == src_type.length); | ||||
|  | ||||
| #if 1 | ||||
|    src = lp_build_clamped_float_to_unsigned_norm(builder, | ||||
|                                                  src_type, | ||||
|                                                  dst_type.width, | ||||
|                                                  src); | ||||
| #else | ||||
|    lp_build_conv(builder, src_type, dst_type, &src, 1, &src, 1); | ||||
| #endif | ||||
|  | ||||
|    dst_ptr = LLVMBuildBitCast(builder, | ||||
|                               dst_ptr, | ||||
|                               LLVMPointerType(lp_build_vec_type(dst_type), 0), ""); | ||||
|  | ||||
|    lp_build_depth_test(builder, | ||||
|                        &key->depth, | ||||
| @@ -395,59 +407,58 @@ generate_fragment(struct llvmpipe_context *lp, | ||||
|    unsigned i; | ||||
|    unsigned chan; | ||||
|  | ||||
| #ifdef DEBUG | ||||
|    tgsi_dump(shader->base.tokens, 0); | ||||
|    if(key->depth.enabled) { | ||||
|       debug_printf("depth.format = %s\n", pf_name(key->zsbuf_format)); | ||||
|       debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE)); | ||||
|       debug_printf("depth.writemask = %u\n", key->depth.writemask); | ||||
|    } | ||||
|    if(key->alpha.enabled) { | ||||
|       debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE)); | ||||
|       debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); | ||||
|    } | ||||
|    if(key->blend.logicop_enable) { | ||||
|       debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); | ||||
|    } | ||||
|    else if(key->blend.blend_enable) { | ||||
|       debug_printf("blend.rgb_func = %s\n",   debug_dump_blend_func  (key->blend.rgb_func, TRUE)); | ||||
|       debug_printf("rgb_src_factor = %s\n",   debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE)); | ||||
|       debug_printf("rgb_dst_factor = %s\n",   debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE)); | ||||
|       debug_printf("alpha_func = %s\n",       debug_dump_blend_func  (key->blend.alpha_func, TRUE)); | ||||
|       debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE)); | ||||
|       debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, TRUE)); | ||||
|    } | ||||
|    debug_printf("blend.colormask = 0x%x\n", key->blend.colormask); | ||||
|    for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) { | ||||
|       if(key->sampler[i].format) { | ||||
|          debug_printf("sampler[%u] = \n", i); | ||||
|          debug_printf("  .format = %s\n", | ||||
|                       pf_name(key->sampler[i].format)); | ||||
|          debug_printf("  .target = %s\n", | ||||
|                       debug_dump_tex_target(key->sampler[i].target, TRUE)); | ||||
|          debug_printf("  .pot = %u %u %u\n", | ||||
|                       key->sampler[i].pot_width, | ||||
|                       key->sampler[i].pot_height, | ||||
|                       key->sampler[i].pot_depth); | ||||
|          debug_printf("  .wrap = %s %s %s\n", | ||||
|                       debug_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), | ||||
|                       debug_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), | ||||
|                       debug_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); | ||||
|          debug_printf("  .min_img_filter = %s\n", | ||||
|                       debug_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); | ||||
|          debug_printf("  .min_mip_filter = %s\n", | ||||
|                       debug_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); | ||||
|          debug_printf("  .mag_img_filter = %s\n", | ||||
|                       debug_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); | ||||
|          if(key->sampler[i].compare_mode) | ||||
|             debug_printf("  .compare_mode = %s\n", debug_dump_func(key->sampler[i].compare_func, TRUE)); | ||||
|          debug_printf("  .normalized_coords = %u\n", key->sampler[i].normalized_coords); | ||||
|          debug_printf("  .prefilter = %u\n", key->sampler[i].prefilter); | ||||
|    if (LP_DEBUG & DEBUG_JIT) { | ||||
|       tgsi_dump(shader->base.tokens, 0); | ||||
|       if(key->depth.enabled) { | ||||
|          debug_printf("depth.format = %s\n", pf_name(key->zsbuf_format)); | ||||
|          debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE)); | ||||
|          debug_printf("depth.writemask = %u\n", key->depth.writemask); | ||||
|       } | ||||
|       if(key->alpha.enabled) { | ||||
|          debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE)); | ||||
|          debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); | ||||
|       } | ||||
|       if(key->blend.logicop_enable) { | ||||
|          debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); | ||||
|       } | ||||
|       else if(key->blend.blend_enable) { | ||||
|          debug_printf("blend.rgb_func = %s\n",   debug_dump_blend_func  (key->blend.rgb_func, TRUE)); | ||||
|          debug_printf("rgb_src_factor = %s\n",   debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE)); | ||||
|          debug_printf("rgb_dst_factor = %s\n",   debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE)); | ||||
|          debug_printf("alpha_func = %s\n",       debug_dump_blend_func  (key->blend.alpha_func, TRUE)); | ||||
|          debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE)); | ||||
|          debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, TRUE)); | ||||
|       } | ||||
|       debug_printf("blend.colormask = 0x%x\n", key->blend.colormask); | ||||
|       for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) { | ||||
|          if(key->sampler[i].format) { | ||||
|             debug_printf("sampler[%u] = \n", i); | ||||
|             debug_printf("  .format = %s\n", | ||||
|                          pf_name(key->sampler[i].format)); | ||||
|             debug_printf("  .target = %s\n", | ||||
|                          debug_dump_tex_target(key->sampler[i].target, TRUE)); | ||||
|             debug_printf("  .pot = %u %u %u\n", | ||||
|                          key->sampler[i].pot_width, | ||||
|                          key->sampler[i].pot_height, | ||||
|                          key->sampler[i].pot_depth); | ||||
|             debug_printf("  .wrap = %s %s %s\n", | ||||
|                          debug_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), | ||||
|                          debug_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), | ||||
|                          debug_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); | ||||
|             debug_printf("  .min_img_filter = %s\n", | ||||
|                          debug_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); | ||||
|             debug_printf("  .min_mip_filter = %s\n", | ||||
|                          debug_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); | ||||
|             debug_printf("  .mag_img_filter = %s\n", | ||||
|                          debug_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); | ||||
|             if(key->sampler[i].compare_mode) | ||||
|                debug_printf("  .compare_mode = %s\n", debug_dump_func(key->sampler[i].compare_func, TRUE)); | ||||
|             debug_printf("  .normalized_coords = %u\n", key->sampler[i].normalized_coords); | ||||
|             debug_printf("  .prefilter = %u\n", key->sampler[i].prefilter); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|    variant = CALLOC_STRUCT(lp_fragment_shader_variant); | ||||
|    if(!variant) | ||||
|       return NULL; | ||||
| @@ -586,8 +597,8 @@ generate_fragment(struct llvmpipe_context *lp, | ||||
|    } | ||||
|  | ||||
|    lp_build_conv_mask(builder, fs_type, blend_type, | ||||
|                                fs_mask, num_fs, | ||||
|                                &blend_mask, 1); | ||||
|                       fs_mask, num_fs, | ||||
|                       &blend_mask, 1); | ||||
|  | ||||
|    /* | ||||
|     * Blending. | ||||
| @@ -609,23 +620,24 @@ generate_fragment(struct llvmpipe_context *lp, | ||||
|     * Translate the LLVM IR into machine code. | ||||
|     */ | ||||
|  | ||||
| #ifdef DEBUG | ||||
|    if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) { | ||||
|       LLVMDumpValue(variant->function); | ||||
|       abort(); | ||||
|       assert(0); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    LLVMRunFunctionPassManager(screen->pass, variant->function); | ||||
|  | ||||
| #ifdef DEBUG | ||||
|    LLVMDumpValue(variant->function); | ||||
|    debug_printf("\n"); | ||||
| #endif | ||||
|    if (LP_DEBUG & DEBUG_JIT) { | ||||
|       LLVMDumpValue(variant->function); | ||||
|       debug_printf("\n"); | ||||
|    } | ||||
|  | ||||
|    variant->jit_function = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, variant->function); | ||||
|  | ||||
| #ifdef DEBUG | ||||
|    lp_disassemble(variant->jit_function); | ||||
| #endif | ||||
|    if (LP_DEBUG & DEBUG_ASM) | ||||
|       lp_disassemble(variant->jit_function); | ||||
|  | ||||
|    variant->next = shader->variants; | ||||
|    shader->variants = variant; | ||||
| @@ -659,7 +671,12 @@ llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs) | ||||
| { | ||||
|    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); | ||||
|  | ||||
|    llvmpipe->fs = (struct lp_fragment_shader *) fs; | ||||
|    if (llvmpipe->fs == fs) | ||||
|       return; | ||||
|  | ||||
|    draw_flush(llvmpipe->draw); | ||||
|  | ||||
|    llvmpipe->fs = fs; | ||||
|  | ||||
|    llvmpipe->dirty |= LP_NEW_FS; | ||||
| } | ||||
| @@ -710,8 +727,7 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe, | ||||
|    assert(shader < PIPE_SHADER_TYPES); | ||||
|    assert(index == 0); | ||||
|  | ||||
|    if(shader == PIPE_SHADER_VERTEX) | ||||
|       draw_flush(llvmpipe->draw); | ||||
|    draw_flush(llvmpipe->draw); | ||||
|  | ||||
|    /* note: reference counting */ | ||||
|    pipe_buffer_reference(&llvmpipe->constants[shader].buffer, buffer); | ||||
|   | ||||
| @@ -41,14 +41,17 @@ llvmpipe_create_rasterizer_state(struct pipe_context *pipe, | ||||
| } | ||||
|  | ||||
| void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, | ||||
|                                     void *setup) | ||||
|                                     void *rasterizer) | ||||
| { | ||||
|    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); | ||||
|  | ||||
|    /* pass-through to draw module */ | ||||
|    draw_set_rasterizer_state(llvmpipe->draw, setup); | ||||
|    if (llvmpipe->rasterizer == rasterizer) | ||||
|       return; | ||||
|  | ||||
|    llvmpipe->rasterizer = (struct pipe_rasterizer_state *)setup; | ||||
|    /* pass-through to draw module */ | ||||
|    draw_set_rasterizer_state(llvmpipe->draw, rasterizer); | ||||
|  | ||||
|    llvmpipe->rasterizer = rasterizer; | ||||
|  | ||||
|    llvmpipe->dirty |= LP_NEW_RASTERIZER; | ||||
| } | ||||
|   | ||||
| @@ -48,6 +48,8 @@ llvmpipe_set_framebuffer_state(struct pipe_context *pipe, | ||||
|    struct llvmpipe_context *lp = llvmpipe_context(pipe); | ||||
|    uint i; | ||||
|  | ||||
|    draw_flush(lp->draw); | ||||
|  | ||||
|    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { | ||||
|       /* check if changing cbuf */ | ||||
|       if (lp->framebuffer.cbufs[i] != fb->cbufs[i]) { | ||||
|   | ||||
| @@ -70,14 +70,18 @@ fail: | ||||
|  | ||||
|  | ||||
| void | ||||
| llvmpipe_bind_vs_state(struct pipe_context *pipe, void *vs) | ||||
| llvmpipe_bind_vs_state(struct pipe_context *pipe, void *_vs) | ||||
| { | ||||
|    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); | ||||
|    const struct lp_vertex_shader *vs = (const struct lp_vertex_shader *)_vs; | ||||
|  | ||||
|    llvmpipe->vs = (const struct lp_vertex_shader *)vs; | ||||
|    if (llvmpipe->vs == vs) | ||||
|       return; | ||||
|  | ||||
|    draw_bind_vertex_shader(llvmpipe->draw, | ||||
|                            (llvmpipe->vs ? llvmpipe->vs->draw_data : NULL)); | ||||
|    draw_bind_vertex_shader(llvmpipe->draw,  | ||||
|                            vs ? vs->draw_data : NULL); | ||||
|  | ||||
|    llvmpipe->vs = vs; | ||||
|  | ||||
|    llvmpipe->dirty |= LP_NEW_VS; | ||||
| } | ||||
| @@ -92,5 +96,6 @@ llvmpipe_delete_vs_state(struct pipe_context *pipe, void *vs) | ||||
|       (struct lp_vertex_shader *)vs; | ||||
|  | ||||
|    draw_delete_vertex_shader(llvmpipe->draw, state->draw_data); | ||||
|    FREE( (void *)state->shader.tokens ); | ||||
|    FREE( state ); | ||||
| } | ||||
|   | ||||
| @@ -714,9 +714,14 @@ depth_test_quads_fallback(struct quad_stage *qs, | ||||
|       qs->next->run(qs->next, quads, nr); | ||||
| } | ||||
|  | ||||
| /* XXX: this function assumes setup function actually emits linear | ||||
|  * spans of quads.  It seems a lot more natural to do (early) | ||||
|  * depth-testing on spans rather than quads. | ||||
|  | ||||
| /** | ||||
|  * Special-case Z testing for 16-bit Zbuffer, PIPE_FUNC_LESS and | ||||
|  * Z buffer writes enabled. | ||||
|  * | ||||
|  * NOTE: there's no guarantee that the quads are sequentially side by | ||||
|  * side.  The fragment shader may have culled some quads, etc.  Sliver | ||||
|  * triangles may generate non-sequential quads. | ||||
|  */ | ||||
| static void | ||||
| depth_interp_z16_less_write(struct quad_stage *qs,  | ||||
| @@ -733,25 +738,33 @@ depth_interp_z16_less_write(struct quad_stage *qs, | ||||
|    const float z0 = quads[0]->posCoef->a0[2] + dzdx * fx + dzdy * fy; | ||||
|    struct softpipe_cached_tile *tile; | ||||
|    ushort (*depth16)[TILE_SIZE]; | ||||
|    ushort idepth[4], depth_step; | ||||
|    ushort init_idepth[4], idepth[4], depth_step; | ||||
|    const float scale = 65535.0; | ||||
|  | ||||
|    idepth[0] = (ushort)((z0) * scale); | ||||
|    idepth[1] = (ushort)((z0 + dzdx) * scale); | ||||
|    idepth[2] = (ushort)((z0 + dzdy) * scale); | ||||
|    idepth[3] = (ushort)((z0 + dzdx + dzdy) * scale); | ||||
|    /* compute scaled depth of the four pixels in first quad */ | ||||
|    init_idepth[0] = (ushort)((z0) * scale); | ||||
|    init_idepth[1] = (ushort)((z0 + dzdx) * scale); | ||||
|    init_idepth[2] = (ushort)((z0 + dzdy) * scale); | ||||
|    init_idepth[3] = (ushort)((z0 + dzdx + dzdy) * scale); | ||||
|  | ||||
|    depth_step = (ushort)(dzdx * 2 * scale); | ||||
|    depth_step = (ushort)(dzdx * scale); | ||||
|  | ||||
|    tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, ix, iy); | ||||
|  | ||||
|    depth16 = (ushort (*)[TILE_SIZE]) | ||||
|       &tile->data.depth16[iy % TILE_SIZE][ix % TILE_SIZE]; | ||||
|  | ||||
|    for (i = 0; i < nr; i++) { | ||||
|       unsigned outmask = quads[i]->inout.mask; | ||||
|       const unsigned outmask = quads[i]->inout.mask; | ||||
|       const int dx = quads[i]->input.x0 - ix; | ||||
|       unsigned mask = 0; | ||||
|        | ||||
|  | ||||
|       /* compute depth for this quad */ | ||||
|       idepth[0] = init_idepth[0] + dx * depth_step; | ||||
|       idepth[1] = init_idepth[1] + dx * depth_step; | ||||
|       idepth[2] = init_idepth[2] + dx * depth_step; | ||||
|       idepth[3] = init_idepth[3] + dx * depth_step; | ||||
|  | ||||
|       depth16 = (ushort (*)[TILE_SIZE]) | ||||
|          &tile->data.depth16[iy % TILE_SIZE][(ix + dx)% TILE_SIZE]; | ||||
|  | ||||
|       if ((outmask & 1) && idepth[0] < depth16[0][0]) { | ||||
|          depth16[0][0] = idepth[0]; | ||||
|          mask |= (1 << 0); | ||||
| @@ -772,13 +785,6 @@ depth_interp_z16_less_write(struct quad_stage *qs, | ||||
|          mask |= (1 << 3); | ||||
|       } | ||||
|  | ||||
|       idepth[0] += depth_step; | ||||
|       idepth[1] += depth_step; | ||||
|       idepth[2] += depth_step; | ||||
|       idepth[3] += depth_step; | ||||
|  | ||||
|       depth16 = (ushort (*)[TILE_SIZE]) &depth16[0][2]; | ||||
|  | ||||
|       quads[i]->inout.mask = mask; | ||||
|       if (quads[i]->inout.mask) | ||||
|          quads[pass++] = quads[i]; | ||||
| @@ -790,6 +796,14 @@ depth_interp_z16_less_write(struct quad_stage *qs, | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Special-case Z testing for 16-bit Zbuffer, PIPE_FUNC_LEQUAL and | ||||
|  * Z buffer writes enabled. | ||||
|  * | ||||
|  * NOTE: there's no guarantee that the quads are sequentially side by | ||||
|  * side.  The fragment shader may have culled some quads, etc.  Sliver | ||||
|  * triangles may generate non-sequential quads. | ||||
|  */ | ||||
| static void | ||||
| depth_interp_z16_lequal_write(struct quad_stage *qs,  | ||||
|                             struct quad_header *quads[], | ||||
| @@ -805,25 +819,33 @@ depth_interp_z16_lequal_write(struct quad_stage *qs, | ||||
|    const float z0 = quads[0]->posCoef->a0[2] + dzdx * fx + dzdy * fy; | ||||
|    struct softpipe_cached_tile *tile; | ||||
|    ushort (*depth16)[TILE_SIZE]; | ||||
|    ushort idepth[4], depth_step; | ||||
|    ushort init_idepth[4], idepth[4], depth_step; | ||||
|    const float scale = 65535.0; | ||||
|  | ||||
|    idepth[0] = (ushort)((z0) * scale); | ||||
|    idepth[1] = (ushort)((z0 + dzdx) * scale); | ||||
|    idepth[2] = (ushort)((z0 + dzdy) * scale); | ||||
|    idepth[3] = (ushort)((z0 + dzdx + dzdy) * scale); | ||||
|    /* compute scaled depth of the four pixels in first quad */ | ||||
|    init_idepth[0] = (ushort)((z0) * scale); | ||||
|    init_idepth[1] = (ushort)((z0 + dzdx) * scale); | ||||
|    init_idepth[2] = (ushort)((z0 + dzdy) * scale); | ||||
|    init_idepth[3] = (ushort)((z0 + dzdx + dzdy) * scale); | ||||
|  | ||||
|    depth_step = (ushort)(dzdx * 2 * scale); | ||||
|    depth_step = (ushort)(dzdx * scale); | ||||
|  | ||||
|    tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, ix, iy); | ||||
|  | ||||
|    depth16 = (ushort (*)[TILE_SIZE]) | ||||
|       &tile->data.depth16[iy % TILE_SIZE][ix % TILE_SIZE]; | ||||
|  | ||||
|    for (i = 0; i < nr; i++) { | ||||
|       unsigned outmask = quads[i]->inout.mask; | ||||
|       const unsigned outmask = quads[i]->inout.mask; | ||||
|       const int dx = quads[i]->input.x0 - ix; | ||||
|       unsigned mask = 0; | ||||
|        | ||||
|       /* compute depth for this quad */ | ||||
|       idepth[0] = init_idepth[0] + dx * depth_step; | ||||
|       idepth[1] = init_idepth[1] + dx * depth_step; | ||||
|       idepth[2] = init_idepth[2] + dx * depth_step; | ||||
|       idepth[3] = init_idepth[3] + dx * depth_step; | ||||
|  | ||||
|       depth16 = (ushort (*)[TILE_SIZE]) | ||||
|          &tile->data.depth16[iy % TILE_SIZE][(ix + dx)% TILE_SIZE]; | ||||
|  | ||||
|       if ((outmask & 1) && idepth[0] <= depth16[0][0]) { | ||||
|          depth16[0][0] = idepth[0]; | ||||
|          mask |= (1 << 0); | ||||
| @@ -844,11 +866,6 @@ depth_interp_z16_lequal_write(struct quad_stage *qs, | ||||
|          mask |= (1 << 3); | ||||
|       } | ||||
|  | ||||
|       idepth[0] += depth_step; | ||||
|       idepth[1] += depth_step; | ||||
|       idepth[2] += depth_step; | ||||
|       idepth[3] += depth_step; | ||||
|  | ||||
|       depth16 = (ushort (*)[TILE_SIZE]) &depth16[0][2]; | ||||
|  | ||||
|       quads[i]->inout.mask = mask; | ||||
|   | ||||
| @@ -805,7 +805,6 @@ line_persp_coeff(const struct setup_context *setup, | ||||
|                  struct tgsi_interp_coef *coef, | ||||
|                  uint vertSlot, uint i) | ||||
| { | ||||
|    /* XXX double-check/verify this arithmetic */ | ||||
|    const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3]; | ||||
|    const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3]; | ||||
|    const float da = a1 - a0; | ||||
| @@ -813,7 +812,7 @@ line_persp_coeff(const struct setup_context *setup, | ||||
|    const float dady = da * setup->emaj.dy * setup->oneoverarea; | ||||
|    coef->dadx[i] = dadx; | ||||
|    coef->dady[i] = dady; | ||||
|    coef->a0[i] = (setup->vmin[vertSlot][i] - | ||||
|    coef->a0[i] = (a0 - | ||||
|                   (dadx * (setup->vmin[0][0] - setup->pixel_offset) + | ||||
|                    dady * (setup->vmin[0][1] - setup->pixel_offset))); | ||||
| } | ||||
|   | ||||
| @@ -29,6 +29,7 @@ | ||||
|  */ | ||||
|  | ||||
| #include "util/u_memory.h" | ||||
| #include "draw/draw_context.h" | ||||
| #include "sp_context.h" | ||||
| #include "sp_state.h" | ||||
|  | ||||
| @@ -45,6 +46,8 @@ void softpipe_bind_blend_state( struct pipe_context *pipe, | ||||
| { | ||||
|    struct softpipe_context *softpipe = softpipe_context(pipe); | ||||
|  | ||||
|    draw_flush(softpipe->draw); | ||||
|  | ||||
|    softpipe->blend = (struct pipe_blend_state *)blend; | ||||
|  | ||||
|    softpipe->dirty |= SP_NEW_BLEND; | ||||
| @@ -62,6 +65,8 @@ void softpipe_set_blend_color( struct pipe_context *pipe, | ||||
| { | ||||
|    struct softpipe_context *softpipe = softpipe_context(pipe); | ||||
|  | ||||
|    draw_flush(softpipe->draw); | ||||
|  | ||||
|    softpipe->blend_color = *blend_color; | ||||
|  | ||||
|    softpipe->dirty |= SP_NEW_BLEND; | ||||
|   | ||||
| @@ -69,7 +69,14 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) | ||||
| { | ||||
|    struct softpipe_context *softpipe = softpipe_context(pipe); | ||||
|  | ||||
|    softpipe->fs = (struct sp_fragment_shader *) fs; | ||||
|    draw_flush(softpipe->draw); | ||||
|  | ||||
|    if (softpipe->fs == fs) | ||||
|       return; | ||||
|  | ||||
|    draw_flush(softpipe->draw); | ||||
|  | ||||
|    softpipe->fs = fs; | ||||
|  | ||||
|    softpipe->dirty |= SP_NEW_FS; | ||||
| } | ||||
| @@ -159,6 +166,8 @@ softpipe_set_constant_buffer(struct pipe_context *pipe, | ||||
|    assert(shader < PIPE_SHADER_TYPES); | ||||
|    assert(index == 0); | ||||
|  | ||||
|    draw_flush(softpipe->draw); | ||||
|  | ||||
|    /* note: reference counting */ | ||||
|    pipe_buffer_reference(&softpipe->constants[shader].buffer, | ||||
| 			 buf ? buf->buffer : NULL); | ||||
|   | ||||
| @@ -41,14 +41,17 @@ softpipe_create_rasterizer_state(struct pipe_context *pipe, | ||||
| } | ||||
|  | ||||
| void softpipe_bind_rasterizer_state(struct pipe_context *pipe, | ||||
|                                     void *setup) | ||||
|                                     void *rasterizer) | ||||
| { | ||||
|    struct softpipe_context *softpipe = softpipe_context(pipe); | ||||
|  | ||||
|    /* pass-through to draw module */ | ||||
|    draw_set_rasterizer_state(softpipe->draw, setup); | ||||
|    if (softpipe->rasterizer == rasterizer) | ||||
|       return; | ||||
|  | ||||
|    softpipe->rasterizer = (struct pipe_rasterizer_state *)setup; | ||||
|    /* pass-through to draw module */ | ||||
|    draw_set_rasterizer_state(softpipe->draw, rasterizer); | ||||
|  | ||||
|    softpipe->rasterizer = rasterizer; | ||||
|  | ||||
|    softpipe->dirty |= SP_NEW_RASTERIZER; | ||||
| } | ||||
|   | ||||
| @@ -48,6 +48,8 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe, | ||||
|    struct softpipe_context *sp = softpipe_context(pipe); | ||||
|    uint i; | ||||
|  | ||||
|    draw_flush(sp->draw); | ||||
|  | ||||
|    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { | ||||
|       /* check if changing cbuf */ | ||||
|       if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) { | ||||
|   | ||||
| @@ -1306,6 +1306,11 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Compute nearest mipmap level from texcoords. | ||||
|  * Then sample the texture level for four elements of a quad. | ||||
|  * \param c0  the LOD bias factors, or absolute LODs (depending on control) | ||||
|  */ | ||||
| static void | ||||
| mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, | ||||
|                    const float s[QUAD_SIZE], | ||||
| @@ -1500,8 +1505,8 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Compute which cube face is referenced by each texcoord and put that | ||||
|  * info into the sampler faces[] array.  Then sample the cube faces | ||||
|  * Use 3D texcoords to choose a cube face, then sample the 2D cube faces. | ||||
|  * Put face info into the sampler faces[] array. | ||||
|  */ | ||||
| static void | ||||
| sample_cube(struct tgsi_sampler *tgsi_sampler, | ||||
| @@ -1514,11 +1519,12 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, | ||||
|    struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); | ||||
|    unsigned j; | ||||
|    float ssss[4], tttt[4]; | ||||
|    unsigned face; | ||||
|  | ||||
|    /* | ||||
|      major axis | ||||
|      direction     target                             sc     tc    ma | ||||
|      ----------    -------------------------------    ---    ---   --- | ||||
|      direction    target                             sc     tc    ma | ||||
|      ----------   -------------------------------    ---    ---   --- | ||||
|      +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx | ||||
|      -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx | ||||
|      +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry | ||||
| @@ -1526,56 +1532,93 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, | ||||
|      +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz | ||||
|      -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz | ||||
|    */ | ||||
|    for (j = 0; j < QUAD_SIZE; j++) { | ||||
|       float rx = s[j]; | ||||
|       float ry = t[j]; | ||||
|       float rz = p[j]; | ||||
|  | ||||
|    /* First choose the cube face. | ||||
|     * Use the same cube face for all four pixels in the quad. | ||||
|     * | ||||
|     * This isn't ideal, but if we want to use a different cube face | ||||
|     * per pixel in the quad, we'd have to also compute the per-face | ||||
|     * LOD here too.  That's because the four post-face-selection | ||||
|     * texcoords are no longer related to each other (they're | ||||
|     * per-face!)  so we can't use subtraction to compute the partial | ||||
|     * deriviates to compute the LOD.  Doing so (near cube edges | ||||
|     * anyway) gives us pretty much random values. | ||||
|     */ | ||||
|    { | ||||
|       /* use the average of the four pixel's texcoords to choose the face */ | ||||
|       const float rx = 0.25 * (s[0] + s[1] + s[2] + s[3]); | ||||
|       const float ry = 0.25 * (t[0] + t[1] + t[2] + t[3]); | ||||
|       const float rz = 0.25 * (p[0] + p[1] + p[2] + p[3]); | ||||
|       const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); | ||||
|       unsigned face; | ||||
|       float sc, tc, ma; | ||||
|  | ||||
|       if (arx >= ary && arx >= arz) { | ||||
|          if (rx >= 0.0F) { | ||||
|             face = PIPE_TEX_FACE_POS_X; | ||||
|             sc = -rz; | ||||
|             tc = -ry; | ||||
|             ma = arx; | ||||
|          } | ||||
|          else { | ||||
|             face = PIPE_TEX_FACE_NEG_X; | ||||
|             sc = rz; | ||||
|             tc = -ry; | ||||
|             ma = arx; | ||||
|          } | ||||
|       } | ||||
|       else if (ary >= arx && ary >= arz) { | ||||
|          if (ry >= 0.0F) { | ||||
|             face = PIPE_TEX_FACE_POS_Y; | ||||
|             sc = rx; | ||||
|             tc = rz; | ||||
|             ma = ary; | ||||
|          } | ||||
|          else { | ||||
|             face = PIPE_TEX_FACE_NEG_Y; | ||||
|             sc = rx; | ||||
|             tc = -rz; | ||||
|             ma = ary; | ||||
|          } | ||||
|       } | ||||
|       else { | ||||
|          if (rz > 0.0F) { | ||||
|             face = PIPE_TEX_FACE_POS_Z; | ||||
|             sc = rx; | ||||
|             tc = -ry; | ||||
|             ma = arz; | ||||
|          } | ||||
|          else { | ||||
|             face = PIPE_TEX_FACE_NEG_Z; | ||||
|             sc = -rx; | ||||
|             tc = -ry; | ||||
|             ma = arz; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Now compute the 2D _face_ texture coords from the | ||||
|     * 3D _cube_ texture coords. | ||||
|     */ | ||||
|    for (j = 0; j < QUAD_SIZE; j++) { | ||||
|       const float rx = s[j], ry = t[j], rz = p[j]; | ||||
|       const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); | ||||
|       float sc, tc, ma; | ||||
|  | ||||
|       switch (face) { | ||||
|       case PIPE_TEX_FACE_POS_X: | ||||
|          sc = -rz; | ||||
|          tc = -ry; | ||||
|          ma = arx; | ||||
|          break; | ||||
|       case PIPE_TEX_FACE_NEG_X: | ||||
|          sc = rz; | ||||
|          tc = -ry; | ||||
|          ma = arx; | ||||
|          break; | ||||
|       case PIPE_TEX_FACE_POS_Y: | ||||
|          sc = rx; | ||||
|          tc = rz; | ||||
|          ma = ary; | ||||
|          break; | ||||
|       case PIPE_TEX_FACE_NEG_Y: | ||||
|          sc = rx; | ||||
|          tc = -rz; | ||||
|          ma = ary; | ||||
|          break; | ||||
|       case PIPE_TEX_FACE_POS_Z: | ||||
|          sc = rx; | ||||
|          tc = -ry; | ||||
|          ma = arz; | ||||
|          break; | ||||
|       case PIPE_TEX_FACE_NEG_Z: | ||||
|          sc = -rx; | ||||
|          tc = -ry; | ||||
|          ma = arz; | ||||
|          break; | ||||
|       default: | ||||
|          assert(0 && "bad cube face"); | ||||
|       } | ||||
|  | ||||
|       { | ||||
| 	 const float ima = 1.0 / ma; | ||||
|   | ||||
| @@ -297,13 +297,14 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) | ||||
|                               x, y, TILE_SIZE, TILE_SIZE, | ||||
|                               tc->tile.data.color32, 0/*STRIDE*/); | ||||
|  | ||||
|             /* do this? */ | ||||
|             clear_clear_flag(tc->clear_flags, addr); | ||||
|  | ||||
|             numCleared++; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* reset all clear flags to zero */ | ||||
|    memset(tc->clear_flags, 0, sizeof(tc->clear_flags)); | ||||
|  | ||||
| #if 0 | ||||
|    debug_printf("num cleared: %u\n", numCleared); | ||||
| #endif | ||||
|   | ||||
| @@ -478,7 +478,8 @@ SVGA3D_BufferDMA(struct svga_winsys_context *swc, | ||||
|                  struct svga_winsys_surface *host, | ||||
|                  SVGA3dTransferType transfer,      // IN | ||||
|                  uint32 size,                      // IN | ||||
|                  uint32 offset,                    // IN | ||||
|                  uint32 guest_offset,              // IN | ||||
|                  uint32 host_offset,               // IN | ||||
|                  SVGA3dSurfaceDMAFlags flags)      // IN | ||||
| { | ||||
|    SVGA3dCmdSurfaceDMA *cmd; | ||||
| @@ -517,19 +518,19 @@ SVGA3D_BufferDMA(struct svga_winsys_context *swc, | ||||
|    cmd->transfer = transfer; | ||||
|  | ||||
|    box = (SVGA3dCopyBox *)&cmd[1]; | ||||
|    box->x = offset; | ||||
|    box->x = host_offset; | ||||
|    box->y = 0; | ||||
|    box->z = 0; | ||||
|    box->w = size; | ||||
|    box->h = 1; | ||||
|    box->d = 1; | ||||
|    box->srcx = offset; | ||||
|    box->srcx = guest_offset; | ||||
|    box->srcy = 0; | ||||
|    box->srcz = 0; | ||||
|     | ||||
|    pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box); | ||||
|    pSuffix->suffixSize = sizeof *pSuffix; | ||||
|    pSuffix->maximumOffset = offset + size; | ||||
|    pSuffix->maximumOffset = guest_offset + size; | ||||
|    pSuffix->flags = flags; | ||||
|  | ||||
|    swc->commit(swc); | ||||
|   | ||||
| @@ -111,7 +111,8 @@ SVGA3D_BufferDMA(struct svga_winsys_context *swc, | ||||
|                  struct svga_winsys_surface *host, | ||||
|                  SVGA3dTransferType transfer, | ||||
|                  uint32 size, | ||||
|                  uint32 offset, | ||||
|                  uint32 guest_offset, | ||||
|                  uint32 host_offset, | ||||
|                  SVGA3dSurfaceDMAFlags flags); | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -215,7 +215,6 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen ) | ||||
|    svga->state.hw_draw.num_views = 0; | ||||
|  | ||||
|    svga->dirty = ~0; | ||||
|    svga->state.white_fs_id = SVGA3D_INVALID_ID; | ||||
|  | ||||
|    LIST_INITHEAD(&svga->dirty_buffers); | ||||
|  | ||||
| @@ -285,3 +284,8 @@ void svga_hwtnl_flush_retry( struct svga_context *svga ) | ||||
|    assert(ret == 0); | ||||
| } | ||||
|  | ||||
| struct svga_winsys_context * | ||||
| svga_winsys_context( struct pipe_context *pipe ) | ||||
| { | ||||
|    return svga_context( pipe )->swc; | ||||
| } | ||||
|   | ||||
| @@ -139,6 +139,7 @@ struct svga_rasterizer_state { | ||||
|    unsigned multisampleantialias:1; | ||||
|    unsigned antialiasedlineenable:1; | ||||
|    unsigned lastpixel:1; | ||||
|    unsigned pointspriteenable:1; | ||||
|  | ||||
|    unsigned linepattern; | ||||
|  | ||||
| @@ -329,10 +330,6 @@ struct svga_context | ||||
|  | ||||
|       unsigned texture_timestamp; | ||||
|  | ||||
|       /* Internally generated shaders: | ||||
|        */ | ||||
|       unsigned white_fs_id; | ||||
|  | ||||
|       /*  | ||||
|        */ | ||||
|       struct svga_sw_state          sw; | ||||
|   | ||||
| @@ -253,7 +253,9 @@ enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl, | ||||
|          assert(index_bias >= 0); | ||||
|          assert(min_index <= max_index); | ||||
|          assert(offset + index_bias*stride < size); | ||||
|          assert(offset + (index_bias + min_index)*stride < size); | ||||
|          if (min_index != ~0) { | ||||
|             assert(offset + (index_bias + min_index) * stride < size); | ||||
|          } | ||||
|  | ||||
|          switch (hwtnl->cmd.vdecl[i].identity.type) { | ||||
|          case SVGA3D_DECLTYPE_FLOAT1: | ||||
| @@ -314,7 +316,9 @@ enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl, | ||||
|          } | ||||
|  | ||||
|          assert(!stride || width <= stride); | ||||
|          assert(offset + (index_bias + max_index)*stride + width <= size); | ||||
|          if (max_index != ~0) { | ||||
|             assert(offset + (index_bias + max_index) * stride + width <= size); | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       assert(range->indexWidth == range->indexArray.stride); | ||||
|   | ||||
| @@ -92,6 +92,7 @@ svga_create_blend_state(struct pipe_context *pipe, | ||||
|       if (templ->logicop_enable) { | ||||
|          switch (templ->logicop_func) { | ||||
|          case PIPE_LOGICOP_XOR: | ||||
|          case PIPE_LOGICOP_INVERT: | ||||
|             blend->need_white_fragments = TRUE; | ||||
|             blend->rt[i].blend_enable = TRUE; | ||||
|             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE; | ||||
| @@ -125,12 +126,6 @@ svga_create_blend_state(struct pipe_context *pipe, | ||||
|             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE; | ||||
|             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM; | ||||
|             break; | ||||
|          case PIPE_LOGICOP_INVERT: | ||||
|             blend->rt[i].blend_enable = TRUE; | ||||
|             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR; | ||||
|             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO; | ||||
|             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD; | ||||
|             break; | ||||
|          case PIPE_LOGICOP_AND: | ||||
|             /* Approximate with minimum - works for the 0 & anything case: */ | ||||
|             blend->rt[i].blend_enable = TRUE; | ||||
| @@ -228,7 +223,7 @@ static void svga_set_blend_color( struct pipe_context *pipe, | ||||
|  | ||||
|    svga->curr.blend_color = *blend_color; | ||||
|  | ||||
|    svga->dirty |= SVGA_NEW_BLEND; | ||||
|    svga->dirty |= SVGA_NEW_BLEND_COLOR; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -218,9 +218,6 @@ svga_draw_range_elements( struct pipe_context *pipe, | ||||
|    if (SVGA_DEBUG & DEBUG_FLUSH) { | ||||
|       static unsigned id; | ||||
|       debug_printf("%s %d\n", __FUNCTION__, id++); | ||||
|       if (id > 1300) | ||||
|          util_time_sleep( 2000 ); | ||||
|  | ||||
|       svga_hwtnl_flush_retry( svga ); | ||||
|       svga_context_flush(svga, NULL); | ||||
|    } | ||||
|   | ||||
| @@ -70,7 +70,6 @@ svga_create_rasterizer_state(struct pipe_context *pipe, | ||||
|    /* light_twoside          - XXX: need fragment shader varient */ | ||||
|    /* poly_smooth            - XXX: no fallback available */ | ||||
|    /* poly_stipple_enable    - draw module */ | ||||
|    /* point_sprite           - ? */ | ||||
|    /* point_size_per_vertex  - ? */ | ||||
|    /* sprite_coord_mode      - ??? */ | ||||
|    /* bypass_vs_viewport_and_clip        - handled by viewport setup */ | ||||
| @@ -86,6 +85,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, | ||||
|    rast->multisampleantialias = templ->multisample; | ||||
|    rast->antialiasedlineenable = templ->line_smooth; | ||||
|    rast->lastpixel = templ->line_last_pixel; | ||||
|    rast->pointspriteenable = templ->point_sprite; | ||||
|    rast->pointsize = templ->point_size; | ||||
|    rast->pointsize_min = templ->point_size_min; | ||||
|    rast->pointsize_max = templ->point_size_max; | ||||
|   | ||||
| @@ -27,7 +27,6 @@ | ||||
| #include "pipe/p_defines.h" | ||||
| #include "util/u_math.h" | ||||
| #include "util/u_memory.h" | ||||
| #include "util/u_pack_color.h" | ||||
| #include "tgsi/tgsi_parse.h" | ||||
|  | ||||
| #include "svga_context.h" | ||||
| @@ -112,14 +111,12 @@ svga_create_sampler_state(struct pipe_context *pipe, | ||||
|    cso->compare_func = sampler->compare_func; | ||||
|  | ||||
|    { | ||||
|       ubyte r = float_to_ubyte(sampler->border_color[0]); | ||||
|       ubyte g = float_to_ubyte(sampler->border_color[1]); | ||||
|       ubyte b = float_to_ubyte(sampler->border_color[2]); | ||||
|       ubyte a = float_to_ubyte(sampler->border_color[3]); | ||||
|       uint32 r = float_to_ubyte(sampler->border_color[0]); | ||||
|       uint32 g = float_to_ubyte(sampler->border_color[1]); | ||||
|       uint32 b = float_to_ubyte(sampler->border_color[2]); | ||||
|       uint32 a = float_to_ubyte(sampler->border_color[3]); | ||||
|  | ||||
|       util_pack_color_ub( r, g, b, a, | ||||
|                           PIPE_FORMAT_B8G8R8A8_UNORM, | ||||
|                           &cso->bordercolor ); | ||||
|       cso->bordercolor = (a << 24) | (r << 16) | (g << 8) | b; | ||||
|    } | ||||
|  | ||||
|    /* No SVGA3D support for: | ||||
|   | ||||
| @@ -50,7 +50,7 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe, | ||||
|    /* Adjust refcounts */ | ||||
|    for (i = 0; i < count; i++) { | ||||
|       pipe_buffer_reference(&svga->curr.vb[i].buffer, buffers[i].buffer); | ||||
|       if (svga_buffer(buffers[i].buffer)->user) | ||||
|       if (svga_buffer_is_user_buffer(buffers[i].buffer)) | ||||
|          any_user_buffer = TRUE; | ||||
|    } | ||||
|  | ||||
|   | ||||
| @@ -104,7 +104,9 @@ svga_get_paramf(struct pipe_screen *screen, int param) | ||||
|       return 80.0; | ||||
|  | ||||
|    case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: | ||||
|       return 4.0; | ||||
|       if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY, &result)) | ||||
|          return 4.0; | ||||
|       return result.u; | ||||
|  | ||||
|    case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: | ||||
|       return 16.0; | ||||
| @@ -131,12 +133,33 @@ svga_get_paramf(struct pipe_screen *screen, int param) | ||||
|       return 1; | ||||
|    case PIPE_CAP_TEXTURE_SHADOW_MAP: | ||||
|       return 1; | ||||
|  | ||||
|    case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: | ||||
|       return SVGA_MAX_TEXTURE_LEVELS; | ||||
|       { | ||||
|          unsigned levels = SVGA_MAX_TEXTURE_LEVELS; | ||||
|          if (sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH, &result)) | ||||
|             levels = MIN2(util_logbase2(result.u) + 1, levels); | ||||
|          else | ||||
|             levels = 12 /* 2048x2048 */; | ||||
|          if (sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT, &result)) | ||||
|             levels = MIN2(util_logbase2(result.u) + 1, levels); | ||||
|          else | ||||
|             levels = 12 /* 2048x2048 */; | ||||
|          return levels; | ||||
|       } | ||||
|  | ||||
|    case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: | ||||
|       return 8;  /* max 128x128x128 */ | ||||
|       if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VOLUME_EXTENT, &result)) | ||||
|          return 8;  /* max 128x128x128 */ | ||||
|       return MIN2(util_logbase2(result.u) + 1, SVGA_MAX_TEXTURE_LEVELS); | ||||
|  | ||||
|    case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: | ||||
|       return SVGA_MAX_TEXTURE_LEVELS; | ||||
|       /* | ||||
|        * No mechanism to query the host, and at least limited to 2048x2048 on | ||||
|        * certain hardware. | ||||
|        */ | ||||
|       return MIN2(screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS), | ||||
|                   12.0 /* 2048x2048 */); | ||||
|  | ||||
|    case PIPE_CAP_TEXTURE_MIRROR_REPEAT: /* req. for GL 1.4 */ | ||||
|       return 1; | ||||
|   | ||||
| @@ -83,7 +83,7 @@ svga_buffer_create_host_surface(struct svga_screen *ss, | ||||
|        * as svga_screen_surface_create might have passed a recycled host | ||||
|        * buffer. | ||||
|        */ | ||||
|       sbuf->hw.flags.discard = TRUE; | ||||
|       sbuf->dma.flags.discard = TRUE; | ||||
|  | ||||
|       SVGA_DBG(DEBUG_DMA, "   --> got sid %p sz %d (buffer)\n", sbuf->handle, sbuf->base.size); | ||||
|    } | ||||
| @@ -109,10 +109,10 @@ svga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf) | ||||
|    struct svga_winsys_screen *sws = ss->sws; | ||||
|  | ||||
|    assert(!sbuf->map.count); | ||||
|    assert(sbuf->hw.buf); | ||||
|    if(sbuf->hw.buf) { | ||||
|       sws->buffer_destroy(sws, sbuf->hw.buf); | ||||
|       sbuf->hw.buf = NULL; | ||||
|    assert(sbuf->hwbuf); | ||||
|    if(sbuf->hwbuf) { | ||||
|       sws->buffer_destroy(sws, sbuf->hwbuf); | ||||
|       sbuf->hwbuf = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
| @@ -151,16 +151,18 @@ static INLINE enum pipe_error | ||||
| svga_buffer_create_hw_storage(struct svga_screen *ss, | ||||
|                               struct svga_buffer *sbuf) | ||||
| { | ||||
|    if(!sbuf->hw.buf) { | ||||
|    assert(!sbuf->user); | ||||
|  | ||||
|    if(!sbuf->hwbuf) { | ||||
|       unsigned alignment = sbuf->base.alignment; | ||||
|       unsigned usage = 0; | ||||
|       unsigned size = sbuf->base.size; | ||||
|        | ||||
|       sbuf->hw.buf = svga_winsys_buffer_create(ss, alignment, usage, size); | ||||
|       if(!sbuf->hw.buf) | ||||
|       sbuf->hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size); | ||||
|       if(!sbuf->hwbuf) | ||||
|          return PIPE_ERROR_OUT_OF_MEMORY; | ||||
|        | ||||
|       assert(!sbuf->needs_flush); | ||||
|       assert(!sbuf->dma.pending); | ||||
|    } | ||||
|     | ||||
|    return PIPE_OK; | ||||
| @@ -175,12 +177,11 @@ svga_buffer_upload_command(struct svga_context *svga, | ||||
|                            struct svga_buffer *sbuf) | ||||
| { | ||||
|    struct svga_winsys_context *swc = svga->swc; | ||||
|    struct svga_winsys_buffer *guest = sbuf->hw.buf; | ||||
|    struct svga_winsys_buffer *guest = sbuf->hwbuf; | ||||
|    struct svga_winsys_surface *host = sbuf->handle; | ||||
|    SVGA3dTransferType transfer = SVGA3D_WRITE_HOST_VRAM; | ||||
|    SVGA3dSurfaceDMAFlags flags = sbuf->hw.flags; | ||||
|    SVGA3dCmdSurfaceDMA *cmd; | ||||
|    uint32 numBoxes = sbuf->hw.num_ranges; | ||||
|    uint32 numBoxes = sbuf->map.num_ranges; | ||||
|    SVGA3dCopyBox *boxes; | ||||
|    SVGA3dCmdSurfaceDMASuffix *pSuffix; | ||||
|    unsigned region_flags; | ||||
| @@ -218,8 +219,8 @@ svga_buffer_upload_command(struct svga_context *svga, | ||||
|  | ||||
|    cmd->transfer = transfer; | ||||
|  | ||||
|    sbuf->hw.boxes = (SVGA3dCopyBox *)&cmd[1]; | ||||
|    sbuf->hw.svga = svga; | ||||
|    sbuf->dma.boxes = (SVGA3dCopyBox *)&cmd[1]; | ||||
|    sbuf->dma.svga = svga; | ||||
|  | ||||
|    /* Increment reference count */ | ||||
|    dummy = NULL; | ||||
| @@ -228,9 +229,11 @@ svga_buffer_upload_command(struct svga_context *svga, | ||||
|    pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes); | ||||
|    pSuffix->suffixSize = sizeof *pSuffix; | ||||
|    pSuffix->maximumOffset = sbuf->base.size; | ||||
|    pSuffix->flags = flags; | ||||
|    pSuffix->flags = sbuf->dma.flags; | ||||
|  | ||||
|    swc->commit(swc); | ||||
|    SVGA_FIFOCommitAll(swc); | ||||
|  | ||||
|    sbuf->dma.flags.discard = FALSE; | ||||
|  | ||||
|    return PIPE_OK; | ||||
| } | ||||
| @@ -248,10 +251,10 @@ svga_buffer_upload_flush(struct svga_context *svga, | ||||
|    unsigned i; | ||||
|  | ||||
|    assert(sbuf->handle);  | ||||
|    assert(sbuf->hw.buf); | ||||
|    assert(sbuf->hw.num_ranges); | ||||
|    assert(sbuf->hw.svga == svga); | ||||
|    assert(sbuf->hw.boxes); | ||||
|    assert(sbuf->hwbuf); | ||||
|    assert(sbuf->map.num_ranges); | ||||
|    assert(sbuf->dma.svga == svga); | ||||
|    assert(sbuf->dma.boxes); | ||||
|     | ||||
|    /* | ||||
|     * Patch the DMA command with the final copy box. | ||||
| @@ -259,36 +262,33 @@ svga_buffer_upload_flush(struct svga_context *svga, | ||||
|  | ||||
|    SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle); | ||||
|  | ||||
|    boxes = sbuf->hw.boxes; | ||||
|    for(i = 0; i < sbuf->hw.num_ranges; ++i) { | ||||
|    boxes = sbuf->dma.boxes; | ||||
|    for(i = 0; i < sbuf->map.num_ranges; ++i) { | ||||
|       SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n", | ||||
|                sbuf->hw.ranges[i].start, sbuf->hw.ranges[i].end); | ||||
|                sbuf->map.ranges[i].start, sbuf->map.ranges[i].end); | ||||
|  | ||||
|       boxes[i].x = sbuf->hw.ranges[i].start; | ||||
|       boxes[i].x = sbuf->map.ranges[i].start; | ||||
|       boxes[i].y = 0; | ||||
|       boxes[i].z = 0; | ||||
|       boxes[i].w = sbuf->hw.ranges[i].end - sbuf->hw.ranges[i].start; | ||||
|       boxes[i].w = sbuf->map.ranges[i].end - sbuf->map.ranges[i].start; | ||||
|       boxes[i].h = 1; | ||||
|       boxes[i].d = 1; | ||||
|       boxes[i].srcx = sbuf->hw.ranges[i].start; | ||||
|       boxes[i].srcx = sbuf->map.ranges[i].start; | ||||
|       boxes[i].srcy = 0; | ||||
|       boxes[i].srcz = 0; | ||||
|    } | ||||
|  | ||||
|    sbuf->hw.num_ranges = 0; | ||||
|    memset(&sbuf->hw.flags, 0, sizeof sbuf->hw.flags); | ||||
|    sbuf->map.num_ranges = 0; | ||||
|  | ||||
|    assert(sbuf->head.prev && sbuf->head.next); | ||||
|    LIST_DEL(&sbuf->head); | ||||
| #ifdef DEBUG | ||||
|    sbuf->head.next = sbuf->head.prev = NULL;  | ||||
| #endif | ||||
|    sbuf->needs_flush = FALSE; | ||||
|    sbuf->dma.pending = FALSE; | ||||
|  | ||||
|    sbuf->hw.svga = NULL; | ||||
|    sbuf->hw.boxes = NULL; | ||||
|  | ||||
|    sbuf->host_written = TRUE; | ||||
|    sbuf->dma.svga = NULL; | ||||
|    sbuf->dma.boxes = NULL; | ||||
|  | ||||
|    /* Decrement reference count */ | ||||
|    pipe_buffer_reference((struct pipe_buffer **)&sbuf, NULL); | ||||
| @@ -296,7 +296,7 @@ svga_buffer_upload_flush(struct svga_context *svga, | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Queue a DMA upload of a range of this buffer to the host. | ||||
|  * Note a dirty range. | ||||
|  * | ||||
|  * This function only notes the range down. It doesn't actually emit a DMA | ||||
|  * upload command. That only happens when a context tries to refer to this | ||||
| @@ -305,15 +305,24 @@ svga_buffer_upload_flush(struct svga_context *svga, | ||||
|  * We try to lump as many contiguous DMA transfers together as possible. | ||||
|  */ | ||||
| static void | ||||
| svga_buffer_upload_queue(struct svga_buffer *sbuf, | ||||
|                          unsigned start, | ||||
|                          unsigned end) | ||||
| svga_buffer_add_range(struct svga_buffer *sbuf, | ||||
|                       unsigned start, | ||||
|                       unsigned end) | ||||
| { | ||||
|    unsigned i; | ||||
|    unsigned nearest_range; | ||||
|    unsigned nearest_dist; | ||||
|  | ||||
|    assert(sbuf->hw.buf); | ||||
|    assert(end > start); | ||||
|     | ||||
|    if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) { | ||||
|       nearest_range = sbuf->map.num_ranges; | ||||
|       nearest_dist = ~0; | ||||
|    } else { | ||||
|       nearest_range = SVGA_BUFFER_MAX_RANGES - 1; | ||||
|       nearest_dist = 0; | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * Try to grow one of the ranges. | ||||
|     * | ||||
| @@ -324,12 +333,34 @@ svga_buffer_upload_queue(struct svga_buffer *sbuf, | ||||
|     * buffer should be flushed. | ||||
|     */ | ||||
|  | ||||
|    for(i = 0; i < sbuf->hw.num_ranges; ++i) { | ||||
|       if(start <= sbuf->hw.ranges[i].end && sbuf->hw.ranges[i].start <= end) { | ||||
|          sbuf->hw.ranges[i].start = MIN2(sbuf->hw.ranges[i].start, start); | ||||
|          sbuf->hw.ranges[i].end   = MAX2(sbuf->hw.ranges[i].end,    end); | ||||
|    for(i = 0; i < sbuf->map.num_ranges; ++i) { | ||||
|       int left_dist; | ||||
|       int right_dist; | ||||
|       int dist; | ||||
|  | ||||
|       left_dist = start - sbuf->map.ranges[i].end; | ||||
|       right_dist = sbuf->map.ranges[i].start - end; | ||||
|       dist = MAX2(left_dist, right_dist); | ||||
|  | ||||
|       if (dist <= 0) { | ||||
|          /* | ||||
|           * Ranges are contiguous or overlapping -- extend this one and return. | ||||
|           */ | ||||
|  | ||||
|          sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start); | ||||
|          sbuf->map.ranges[i].end   = MAX2(sbuf->map.ranges[i].end,   end); | ||||
|          return; | ||||
|       } | ||||
|       else { | ||||
|          /* | ||||
|           * Discontiguous ranges -- keep track of the nearest range. | ||||
|           */ | ||||
|  | ||||
|          if (dist < nearest_dist) { | ||||
|             nearest_range = i; | ||||
|             nearest_dist = dist; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* | ||||
| @@ -337,20 +368,34 @@ svga_buffer_upload_queue(struct svga_buffer *sbuf, | ||||
|     * pending DMA upload and start clean. | ||||
|     */ | ||||
|  | ||||
|    if(sbuf->needs_flush) | ||||
|       svga_buffer_upload_flush(sbuf->hw.svga, sbuf); | ||||
|    if(sbuf->dma.pending) | ||||
|       svga_buffer_upload_flush(sbuf->dma.svga, sbuf); | ||||
|  | ||||
|    assert(!sbuf->needs_flush); | ||||
|    assert(!sbuf->hw.svga); | ||||
|    assert(!sbuf->hw.boxes); | ||||
|    assert(!sbuf->dma.pending); | ||||
|    assert(!sbuf->dma.svga); | ||||
|    assert(!sbuf->dma.boxes); | ||||
|  | ||||
|    /* | ||||
|     * Add a new range. | ||||
|     */ | ||||
|    if (sbuf->map.num_ranges < SVGA_BUFFER_MAX_RANGES) { | ||||
|       /* | ||||
|        * Add a new range. | ||||
|        */ | ||||
|  | ||||
|    sbuf->hw.ranges[sbuf->hw.num_ranges].start = start; | ||||
|    sbuf->hw.ranges[sbuf->hw.num_ranges].end = end; | ||||
|    ++sbuf->hw.num_ranges; | ||||
|       sbuf->map.ranges[sbuf->map.num_ranges].start = start; | ||||
|       sbuf->map.ranges[sbuf->map.num_ranges].end = end; | ||||
|       ++sbuf->map.num_ranges; | ||||
|    } else { | ||||
|       /* | ||||
|        * Everything else failed, so just extend the nearest range. | ||||
|        * | ||||
|        * It is OK to do this because we always keep a local copy of the | ||||
|        * host buffer data, for SW TNL, and the host never modifies the buffer. | ||||
|        */ | ||||
|  | ||||
|       assert(nearest_range < SVGA_BUFFER_MAX_RANGES); | ||||
|       assert(nearest_range < sbuf->map.num_ranges); | ||||
|       sbuf->map.ranges[nearest_range].start = MIN2(sbuf->map.ranges[nearest_range].start, start); | ||||
|       sbuf->map.ranges[nearest_range].end   = MAX2(sbuf->map.ranges[nearest_range].end,   end); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -365,55 +410,30 @@ svga_buffer_map_range( struct pipe_screen *screen, | ||||
|    struct svga_buffer *sbuf = svga_buffer( buf ); | ||||
|    void *map; | ||||
|  | ||||
|    if(sbuf->swbuf) { | ||||
|    if (!sbuf->swbuf && !sbuf->hwbuf) { | ||||
|       if (svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) { | ||||
|          /* | ||||
|           * We can't create a hardware buffer big enough, so create a malloc | ||||
|           * buffer instead. | ||||
|           */ | ||||
|  | ||||
|          debug_printf("%s: failed to allocate %u KB of DMA, splitting DMA transfers\n", | ||||
|                       __FUNCTION__, | ||||
|                       (sbuf->base.size + 1023)/1024); | ||||
|  | ||||
|          sbuf->swbuf = align_malloc(sbuf->base.size, sbuf->base.alignment); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (sbuf->swbuf) { | ||||
|       /* User/malloc buffer */ | ||||
|       map = sbuf->swbuf; | ||||
|    } | ||||
|    else if (sbuf->hwbuf) { | ||||
|       map = sws->buffer_map(sws, sbuf->hwbuf, usage); | ||||
|    } | ||||
|    else { | ||||
|       if(!sbuf->hw.buf) { | ||||
|          if(svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) | ||||
|             return NULL; | ||||
|           | ||||
|          /* Populate the hardware storage if the host surface pre-existed */ | ||||
|          if(sbuf->host_written) { | ||||
|             SVGA3dSurfaceDMAFlags flags; | ||||
|             enum pipe_error ret; | ||||
|             struct pipe_fence_handle *fence = NULL; | ||||
|              | ||||
|             assert(sbuf->handle); | ||||
|  | ||||
|             SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "dma from sid %p (buffer), bytes %u - %u\n",  | ||||
|                      sbuf->handle, 0, sbuf->base.size); | ||||
|  | ||||
|             memset(&flags, 0, sizeof flags); | ||||
|              | ||||
|             ret = SVGA3D_BufferDMA(ss->swc, | ||||
|                                    sbuf->hw.buf, | ||||
|                                    sbuf->handle, | ||||
|                                    SVGA3D_READ_HOST_VRAM, | ||||
|                                    sbuf->base.size, | ||||
|                                    0, | ||||
|                                    flags); | ||||
|             if(ret != PIPE_OK) { | ||||
|                ss->swc->flush(ss->swc, NULL); | ||||
|                 | ||||
|                ret = SVGA3D_BufferDMA(ss->swc, | ||||
|                                       sbuf->hw.buf, | ||||
|                                       sbuf->handle, | ||||
|                                       SVGA3D_READ_HOST_VRAM, | ||||
|                                       sbuf->base.size, | ||||
|                                       0, | ||||
|                                       flags); | ||||
|                assert(ret == PIPE_OK); | ||||
|             } | ||||
|              | ||||
|             ss->swc->flush(ss->swc, &fence); | ||||
|             sws->fence_finish(sws, fence, 0); | ||||
|             sws->fence_reference(sws, &fence, NULL); | ||||
|          } | ||||
|       } | ||||
|           | ||||
|       map = sws->buffer_map(sws, sbuf->hw.buf, usage); | ||||
|       map = NULL; | ||||
|    } | ||||
|  | ||||
|    if(map) { | ||||
| @@ -446,8 +466,7 @@ svga_buffer_flush_mapped_range( struct pipe_screen *screen, | ||||
|    assert(sbuf->map.writing); | ||||
|    if(sbuf->map.writing) { | ||||
|       assert(sbuf->map.flush_explicit); | ||||
|       if(sbuf->hw.buf) | ||||
|          svga_buffer_upload_queue(sbuf, offset, offset + length); | ||||
|       svga_buffer_add_range(sbuf, offset, offset + length); | ||||
|    } | ||||
|    pipe_mutex_unlock(ss->swc_mutex); | ||||
| } | ||||
| @@ -466,16 +485,15 @@ svga_buffer_unmap( struct pipe_screen *screen, | ||||
|    if(sbuf->map.count) | ||||
|       --sbuf->map.count; | ||||
|  | ||||
|    if(sbuf->hw.buf) | ||||
|       sws->buffer_unmap(sws, sbuf->hw.buf); | ||||
|    if(sbuf->hwbuf) | ||||
|       sws->buffer_unmap(sws, sbuf->hwbuf); | ||||
|  | ||||
|    if(sbuf->map.writing) { | ||||
|       if(!sbuf->map.flush_explicit) { | ||||
|          /* No mapped range was flushed -- flush the whole buffer */ | ||||
|          SVGA_DBG(DEBUG_DMA, "flushing the whole buffer\n"); | ||||
|     | ||||
|          if(sbuf->hw.buf) | ||||
|             svga_buffer_upload_queue(sbuf, 0, sbuf->base.size); | ||||
|          svga_buffer_add_range(sbuf, 0, sbuf->base.size); | ||||
|       } | ||||
|        | ||||
|       sbuf->map.writing = FALSE; | ||||
| @@ -493,12 +511,15 @@ svga_buffer_destroy( struct pipe_buffer *buf ) | ||||
|  | ||||
|    assert(!p_atomic_read(&buf->reference.count)); | ||||
|     | ||||
|    assert(!sbuf->needs_flush); | ||||
|    assert(!sbuf->dma.pending); | ||||
|  | ||||
|    if(sbuf->handle) | ||||
|       svga_buffer_destroy_host_surface(ss, sbuf); | ||||
|     | ||||
|    if(sbuf->hw.buf) | ||||
|    if(sbuf->uploaded.buffer) | ||||
|       pipe_buffer_reference(&sbuf->uploaded.buffer, NULL); | ||||
|  | ||||
|    if(sbuf->hwbuf) | ||||
|       svga_buffer_destroy_hw_storage(ss, sbuf); | ||||
|     | ||||
|    if(sbuf->swbuf && !sbuf->user) | ||||
| @@ -595,13 +616,14 @@ svga_screen_init_buffer_functions(struct pipe_screen *screen) | ||||
| } | ||||
|  | ||||
|  | ||||
| /**  | ||||
|  * Copy the contents of the user buffer / malloc buffer to a hardware buffer. | ||||
| /** | ||||
|  * Copy the contents of the malloc buffer to a hardware buffer. | ||||
|  */ | ||||
| static INLINE enum pipe_error | ||||
| svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf) | ||||
| { | ||||
|    if(!sbuf->hw.buf) { | ||||
|    assert(!sbuf->user); | ||||
|    if(!sbuf->hwbuf) { | ||||
|       enum pipe_error ret; | ||||
|       void *map; | ||||
|        | ||||
| @@ -610,20 +632,20 @@ svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf) | ||||
|          return PIPE_ERROR; | ||||
|        | ||||
|       ret = svga_buffer_create_hw_storage(ss, sbuf); | ||||
|       assert(ret == PIPE_OK); | ||||
|       if(ret != PIPE_OK) | ||||
|          return ret; | ||||
|  | ||||
|       pipe_mutex_lock(ss->swc_mutex); | ||||
|       map = ss->sws->buffer_map(ss->sws, sbuf->hw.buf, PIPE_BUFFER_USAGE_CPU_WRITE); | ||||
|       map = ss->sws->buffer_map(ss->sws, sbuf->hwbuf, PIPE_BUFFER_USAGE_CPU_WRITE); | ||||
|       assert(map); | ||||
|       if(!map) { | ||||
| 	 pipe_mutex_unlock(ss->swc_mutex); | ||||
|          return PIPE_ERROR_OUT_OF_MEMORY; | ||||
|          svga_buffer_destroy_hw_storage(ss, sbuf); | ||||
|          return PIPE_ERROR; | ||||
|       } | ||||
|  | ||||
|       memcpy(map, sbuf->swbuf, sbuf->base.size); | ||||
|       ss->sws->buffer_unmap(ss->sws, sbuf->hw.buf); | ||||
|       ss->sws->buffer_unmap(ss->sws, sbuf->hwbuf); | ||||
|  | ||||
|       /* This user/malloc buffer is now indistinguishable from a gpu buffer */ | ||||
|       assert(!sbuf->map.count); | ||||
| @@ -635,10 +657,89 @@ svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf) | ||||
|          sbuf->swbuf = NULL; | ||||
|       } | ||||
|        | ||||
|       svga_buffer_upload_queue(sbuf, 0, sbuf->base.size); | ||||
|       pipe_mutex_unlock(ss->swc_mutex); | ||||
|    } | ||||
|     | ||||
|    pipe_mutex_unlock(ss->swc_mutex); | ||||
|    return PIPE_OK; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Upload the buffer to the host in a piecewise fashion. | ||||
|  * | ||||
|  * Used when the buffer is too big to fit in the GMR aperture. | ||||
|  */ | ||||
| static INLINE enum pipe_error | ||||
| svga_buffer_upload_piecewise(struct svga_screen *ss, | ||||
|                              struct svga_context *svga, | ||||
|                              struct svga_buffer *sbuf) | ||||
| { | ||||
|    struct svga_winsys_screen *sws = ss->sws; | ||||
|    const unsigned alignment = sizeof(void *); | ||||
|    const unsigned usage = 0; | ||||
|    unsigned i; | ||||
|  | ||||
|    assert(sbuf->map.num_ranges); | ||||
|    assert(!sbuf->dma.pending); | ||||
|  | ||||
|    SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle); | ||||
|  | ||||
|    for (i = 0; i < sbuf->map.num_ranges; ++i) { | ||||
|       struct svga_buffer_range *range = &sbuf->map.ranges[i]; | ||||
|       unsigned offset = range->start; | ||||
|       unsigned size = range->end - range->start; | ||||
|  | ||||
|       while (offset < range->end) { | ||||
|          struct svga_winsys_buffer *hwbuf; | ||||
|          uint8_t *map; | ||||
|          enum pipe_error ret; | ||||
|  | ||||
|          if (offset + size > range->end) | ||||
|             size = range->end - offset; | ||||
|  | ||||
|          hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size); | ||||
|          while (!hwbuf) { | ||||
|             size /= 2; | ||||
|             if (!size) | ||||
|                return PIPE_ERROR_OUT_OF_MEMORY; | ||||
|             hwbuf = svga_winsys_buffer_create(ss, alignment, usage, size); | ||||
|          } | ||||
|  | ||||
|          SVGA_DBG(DEBUG_DMA, "  bytes %u - %u\n", | ||||
|                   offset, offset + size); | ||||
|  | ||||
|          map = sws->buffer_map(sws, hwbuf, | ||||
|                                PIPE_BUFFER_USAGE_CPU_WRITE | | ||||
|                                PIPE_BUFFER_USAGE_DISCARD); | ||||
|          assert(map); | ||||
|          if (map) { | ||||
|             memcpy(map, sbuf->swbuf, size); | ||||
|             sws->buffer_unmap(sws, hwbuf); | ||||
|          } | ||||
|  | ||||
|          ret = SVGA3D_BufferDMA(svga->swc, | ||||
|                                 hwbuf, sbuf->handle, | ||||
|                                 SVGA3D_WRITE_HOST_VRAM, | ||||
|                                 size, 0, offset, sbuf->dma.flags); | ||||
|          if(ret != PIPE_OK) { | ||||
|             svga_context_flush(svga, NULL); | ||||
|             ret =  SVGA3D_BufferDMA(svga->swc, | ||||
|                                     hwbuf, sbuf->handle, | ||||
|                                     SVGA3D_WRITE_HOST_VRAM, | ||||
|                                     size, 0, offset, sbuf->dma.flags); | ||||
|             assert(ret == PIPE_OK); | ||||
|          } | ||||
|  | ||||
|          sbuf->dma.flags.discard = FALSE; | ||||
|  | ||||
|          sws->buffer_destroy(sws, hwbuf); | ||||
|  | ||||
|          offset += size; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    sbuf->map.num_ranges = 0; | ||||
|  | ||||
|    return PIPE_OK; | ||||
| } | ||||
|  | ||||
| @@ -658,34 +759,74 @@ svga_buffer_handle(struct svga_context *svga, | ||||
|    sbuf = svga_buffer(buf); | ||||
|     | ||||
|    assert(!sbuf->map.count); | ||||
|    assert(!sbuf->user); | ||||
|     | ||||
|    if(!sbuf->handle) { | ||||
|       ret = svga_buffer_create_host_surface(ss, sbuf); | ||||
|       if(ret != PIPE_OK) | ||||
| 	 return NULL; | ||||
|  | ||||
|       ret = svga_buffer_update_hw(ss, sbuf); | ||||
|       if(ret != PIPE_OK) | ||||
| 	 return NULL; | ||||
|    } | ||||
|  | ||||
|    if(!sbuf->needs_flush && sbuf->hw.num_ranges) { | ||||
|       /* Queue the buffer for flushing */ | ||||
|       ret = svga_buffer_upload_command(svga, sbuf); | ||||
|       if(ret != PIPE_OK) | ||||
|          /* XXX: Should probably have a richer return value */ | ||||
|          return NULL; | ||||
|    assert(sbuf->handle); | ||||
|  | ||||
|       assert(sbuf->hw.svga == svga); | ||||
|    if (sbuf->map.num_ranges) { | ||||
|       if (!sbuf->dma.pending) { | ||||
|          /* | ||||
|           * No pending DMA upload yet, so insert a DMA upload command now. | ||||
|           */ | ||||
|  | ||||
|       sbuf->needs_flush = TRUE; | ||||
|       assert(!sbuf->head.prev && !sbuf->head.next); | ||||
|       LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers); | ||||
|          /* | ||||
|           * Migrate the data from swbuf -> hwbuf if necessary. | ||||
|           */ | ||||
|          ret = svga_buffer_update_hw(ss, sbuf); | ||||
|          if (ret == PIPE_OK) { | ||||
|             /* | ||||
|              * Queue a dma command. | ||||
|              */ | ||||
|  | ||||
|             ret = svga_buffer_upload_command(svga, sbuf); | ||||
|             if (ret == PIPE_ERROR_OUT_OF_MEMORY) { | ||||
|                svga_context_flush(svga, NULL); | ||||
|                ret = svga_buffer_upload_command(svga, sbuf); | ||||
|                assert(ret == PIPE_OK); | ||||
|             } | ||||
|             if (ret == PIPE_OK) { | ||||
|                sbuf->dma.pending = TRUE; | ||||
|                assert(!sbuf->head.prev && !sbuf->head.next); | ||||
|                LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers); | ||||
|             } | ||||
|          } | ||||
|          else if (ret == PIPE_ERROR_OUT_OF_MEMORY) { | ||||
|             /* | ||||
|              * The buffer is too big to fit in the GMR aperture, so break it in | ||||
|              * smaller pieces. | ||||
|              */ | ||||
|             ret = svga_buffer_upload_piecewise(ss, svga, sbuf); | ||||
|          } | ||||
|  | ||||
|          if (ret != PIPE_OK) { | ||||
|             /* | ||||
|              * Something unexpected happened above. There is very little that | ||||
|              * we can do other than proceeding while ignoring the dirty ranges. | ||||
|              */ | ||||
|             assert(0); | ||||
|             sbuf->map.num_ranges = 0; | ||||
|          } | ||||
|       } | ||||
|       else { | ||||
|          /* | ||||
|           * There a pending dma already. Make sure it is from this context. | ||||
|           */ | ||||
|          assert(sbuf->dma.svga == svga); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    assert(!sbuf->map.num_ranges || sbuf->dma.pending); | ||||
|  | ||||
|    return sbuf->handle; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct pipe_buffer * | ||||
| svga_screen_buffer_wrap_surface(struct pipe_screen *screen, | ||||
| 				enum SVGA3dSurfaceFormat format, | ||||
| @@ -738,7 +879,7 @@ svga_context_flush_buffers(struct svga_context *svga) | ||||
|       sbuf = LIST_ENTRY(struct svga_buffer, curr, head); | ||||
|  | ||||
|       assert(p_atomic_read(&sbuf->base.reference.count) != 0); | ||||
|       assert(sbuf->needs_flush); | ||||
|       assert(sbuf->dma.pending); | ||||
|        | ||||
|       svga_buffer_upload_flush(svga, sbuf); | ||||
|  | ||||
|   | ||||
| @@ -56,35 +56,6 @@ struct svga_buffer_range | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Describe a | ||||
|  * | ||||
|  * This holds the information to emit a SVGA3dCmdSurfaceDMA. | ||||
|  */ | ||||
| struct svga_buffer_upload | ||||
| { | ||||
|    /** | ||||
|     * Guest memory region. | ||||
|     */ | ||||
|    struct svga_winsys_buffer *buf; | ||||
|  | ||||
|    struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES]; | ||||
|    unsigned num_ranges; | ||||
|  | ||||
|    SVGA3dSurfaceDMAFlags flags; | ||||
|  | ||||
|    /** | ||||
|     * Pointer to the DMA copy box *inside* the command buffer. | ||||
|     */ | ||||
|    SVGA3dCopyBox *boxes; | ||||
|  | ||||
|    /** | ||||
|     * Context that has the pending DMA to this buffer. | ||||
|     */ | ||||
|    struct svga_context *svga; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * SVGA pipe buffer. | ||||
|  */ | ||||
| @@ -110,14 +81,6 @@ struct svga_buffer | ||||
|     */ | ||||
|    boolean user; | ||||
|     | ||||
|    /** | ||||
|     * DMA'ble memory. | ||||
|     *  | ||||
|     * A piece of GMR memory. It is created when mapping the buffer, and will be | ||||
|     * used to upload/download vertex data from the host. | ||||
|     */ | ||||
|    struct svga_buffer_upload hw; | ||||
|  | ||||
|    /** | ||||
|     * Creation key for the host surface handle. | ||||
|     *  | ||||
| @@ -134,19 +97,94 @@ struct svga_buffer | ||||
|     * trying to bind | ||||
|     */ | ||||
|    struct svga_winsys_surface *handle; | ||||
|     | ||||
|    /** | ||||
|     * Whether the host has been ever written. | ||||
|     */ | ||||
|    boolean host_written; | ||||
|  | ||||
|    /** | ||||
|     * Information about ongoing and past map operations. | ||||
|     */ | ||||
|    struct { | ||||
|       /** | ||||
|        * Number of concurrent mappings. | ||||
|        * | ||||
|        * XXX: It is impossible to guarantee concurrent maps work in all | ||||
|        * circumstances -- pipe_buffers really need transfer objects too. | ||||
|        */ | ||||
|       unsigned count; | ||||
|  | ||||
|       /** | ||||
|        * Whether this buffer is currently mapped for writing. | ||||
|        */ | ||||
|       boolean writing; | ||||
|  | ||||
|       /** | ||||
|        * Whether the application will tell us explicity which ranges it touched | ||||
|        * or not. | ||||
|        */ | ||||
|       boolean flush_explicit; | ||||
|  | ||||
|       /** | ||||
|        * Dirty ranges. | ||||
|        * | ||||
|        * Ranges that were touched by the application and need to be uploaded to | ||||
|        * the host. | ||||
|        * | ||||
|        * This information will be copied into dma.boxes, when emiting the | ||||
|        * SVGA3dCmdSurfaceDMA command. | ||||
|        */ | ||||
|       struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES]; | ||||
|       unsigned num_ranges; | ||||
|    } map; | ||||
|     | ||||
|    boolean needs_flush; | ||||
|  | ||||
|    /** | ||||
|     * Information about uploaded version of user buffers. | ||||
|     */ | ||||
|    struct { | ||||
|       struct pipe_buffer *buffer; | ||||
|  | ||||
|       /** | ||||
|        * We combine multiple user buffers into the same hardware buffer. This | ||||
|        * is the relative offset within that buffer. | ||||
|        */ | ||||
|       unsigned offset; | ||||
|    } uploaded; | ||||
|  | ||||
|    /** | ||||
|     * DMA'ble memory. | ||||
|     * | ||||
|     * A piece of GMR memory, with the same size of the buffer. It is created | ||||
|     * when mapping the buffer, and will be used to upload vertex data to the | ||||
|     * host. | ||||
|     */ | ||||
|    struct svga_winsys_buffer *hwbuf; | ||||
|  | ||||
|    /** | ||||
|     * Information about pending DMA uploads. | ||||
|     * | ||||
|     */ | ||||
|    struct { | ||||
|       /** | ||||
|        * Whether this buffer has an unfinished DMA upload command. | ||||
|        * | ||||
|        * If not set then the rest of the information is null. | ||||
|        */ | ||||
|       boolean pending; | ||||
|  | ||||
|       SVGA3dSurfaceDMAFlags flags; | ||||
|  | ||||
|       /** | ||||
|        * Pointer to the DMA copy box *inside* the command buffer. | ||||
|        */ | ||||
|       SVGA3dCopyBox *boxes; | ||||
|  | ||||
|       /** | ||||
|        * Context that has the pending DMA to this buffer. | ||||
|        */ | ||||
|       struct svga_context *svga; | ||||
|    } dma; | ||||
|  | ||||
|    /** | ||||
|     * Linked list head, used to gather all buffers with pending dma uploads on | ||||
|     * a context. It is only valid if the dma.pending is set above. | ||||
|     */ | ||||
|    struct list_head head; | ||||
| }; | ||||
|  | ||||
| @@ -176,6 +214,16 @@ svga_buffer_is_user_buffer( struct pipe_buffer *buffer ) | ||||
| void | ||||
| svga_screen_init_buffer_functions(struct pipe_screen *screen); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Get the host surface handle for this buffer. | ||||
|  * | ||||
|  * This will ensure the host surface is updated, issuing DMAs as needed. | ||||
|  * | ||||
|  * NOTE: This may insert new commands in the context, so it *must* be called | ||||
|  * before reserving command buffer space. And, in order to insert commands | ||||
|  * it may need to call svga_context_flush(). | ||||
|  */ | ||||
| struct svga_winsys_surface * | ||||
| svga_buffer_handle(struct svga_context *svga, | ||||
|                    struct pipe_buffer *buf); | ||||
|   | ||||
| @@ -203,7 +203,7 @@ svga_transfer_dma(struct svga_transfer *st, | ||||
|       if(transfer == SVGA3D_READ_HOST_VRAM) { | ||||
|          svga_screen_flush(screen, &fence); | ||||
|          sws->fence_finish(sws, fence, 0); | ||||
|          //sws->fence_reference(sws, &fence, NULL); | ||||
|          sws->fence_reference(sws, &fence, NULL); | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
| @@ -232,7 +232,7 @@ svga_transfer_dma(struct svga_transfer *st, | ||||
|             if(y) { | ||||
|                svga_screen_flush(screen, &fence); | ||||
|                sws->fence_finish(sws, fence, 0); | ||||
|                //sws->fence_reference(sws, &fence, NULL); | ||||
|                sws->fence_reference(sws, &fence, NULL); | ||||
|             } | ||||
|  | ||||
|             hw = sws->buffer_map(sws, st->hwbuf, PIPE_BUFFER_USAGE_CPU_WRITE); | ||||
|   | ||||
| @@ -38,7 +38,7 @@ struct svga_winsys_surface; | ||||
| enum SVGA3dSurfaceFormat; | ||||
|  | ||||
|  | ||||
| #define SVGA_MAX_TEXTURE_LEVELS 12 /* 2048x2048 */ | ||||
| #define SVGA_MAX_TEXTURE_LEVELS 16 | ||||
|  | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -103,70 +103,6 @@ fail: | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
| /* The blend workaround for simulating logicop xor behaviour requires | ||||
|  * that the incoming fragment color be white.  This change achieves | ||||
|  * that by hooking up a hard-wired fragment shader that just emits | ||||
|  * color 1,1,1,1 | ||||
|  *    | ||||
|  * This is a slightly incomplete solution as it assumes that the | ||||
|  * actual bound shader has no other effects beyond generating a | ||||
|  * fragment color.  In particular shaders containing TEXKIL and/or | ||||
|  * depth-write will not have the correct behaviour, nor will those | ||||
|  * expecting to use alphatest. | ||||
|  *    | ||||
|  * These are avoidable issues, but they are not much worse than the | ||||
|  * unavoidable ones associated with this technique, so it's not clear | ||||
|  * how much effort should be expended trying to resolve them - the | ||||
|  * ultimate result will still not be correct in most cases. | ||||
|  * | ||||
|  * Shader below was generated with: | ||||
|  *   SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt | ||||
|  */ | ||||
| static int emit_white_fs( struct svga_context *svga ) | ||||
| { | ||||
|    int ret = PIPE_ERROR; | ||||
|  | ||||
|    /* ps_3_0 | ||||
|     * def c0, 1.000000, 0.000000, 0.000000, 1.000000 | ||||
|     * mov oC0, c0.x | ||||
|     * end | ||||
|     */ | ||||
|    static const unsigned white_tokens[] = { | ||||
|       0xffff0300, | ||||
|       0x05000051, | ||||
|       0xa00f0000, | ||||
|       0x3f800000, | ||||
|       0x00000000, | ||||
|       0x00000000, | ||||
|       0x3f800000, | ||||
|       0x02000001, | ||||
|       0x800f0800, | ||||
|       0xa0000000, | ||||
|       0x0000ffff, | ||||
|    }; | ||||
|  | ||||
|    assert(SVGA3D_INVALID_ID == UTIL_BITMASK_INVALID_INDEX); | ||||
|    svga->state.white_fs_id = util_bitmask_add(svga->fs_bm); | ||||
|    if(svga->state.white_fs_id == SVGA3D_INVALID_ID) | ||||
|       goto no_fs_id; | ||||
|  | ||||
|    ret = SVGA3D_DefineShader(svga->swc,  | ||||
|                              svga->state.white_fs_id, | ||||
|                              SVGA3D_SHADERTYPE_PS, | ||||
|                              white_tokens,  | ||||
|                              sizeof(white_tokens)); | ||||
|    if (ret) | ||||
|       goto no_definition; | ||||
|  | ||||
|    return 0; | ||||
|  | ||||
| no_definition: | ||||
|    util_bitmask_clear(svga->fs_bm, svga->state.white_fs_id); | ||||
|    svga->state.white_fs_id = SVGA3D_INVALID_ID; | ||||
| no_fs_id: | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* SVGA_NEW_TEXTURE_BINDING | ||||
|  * SVGA_NEW_RAST | ||||
| @@ -194,6 +130,23 @@ static int make_fs_key( const struct svga_context *svga, | ||||
|                        PIPE_WINDING_CW); | ||||
|    } | ||||
|  | ||||
|    /* The blend workaround for simulating logicop xor behaviour | ||||
|     * requires that the incoming fragment color be white.  This change | ||||
|     * achieves that by creating a varient of the current fragment | ||||
|     * shader that overrides all output colors with 1,1,1,1 | ||||
|     *    | ||||
|     * This will work for most shaders, including those containing | ||||
|     * TEXKIL and/or depth-write.  However, it will break on the | ||||
|     * combination of xor-logicop plus alphatest. | ||||
|     * | ||||
|     * Ultimately, we could implement alphatest in the shader using | ||||
|     * texkil prior to overriding the outgoing fragment color. | ||||
|     *    | ||||
|     * SVGA_NEW_BLEND | ||||
|     */ | ||||
|    if (svga->curr.blend->need_white_fragments) { | ||||
|       key->white_fragments = 1; | ||||
|    } | ||||
|     | ||||
|    /* XXX: want to limit this to the textures that the shader actually | ||||
|     * refers to. | ||||
| @@ -233,40 +186,29 @@ static int emit_hw_fs( struct svga_context *svga, | ||||
|    unsigned id = SVGA3D_INVALID_ID; | ||||
|    int ret = 0; | ||||
|  | ||||
|    /* SVGA_NEW_BLEND | ||||
|     */ | ||||
|    if (svga->curr.blend->need_white_fragments) { | ||||
|       if (svga->state.white_fs_id == SVGA3D_INVALID_ID) { | ||||
|          ret = emit_white_fs( svga ); | ||||
|          if (ret) | ||||
|             return ret; | ||||
|       } | ||||
|       id = svga->state.white_fs_id; | ||||
|    } | ||||
|    else { | ||||
|       struct svga_fragment_shader *fs = svga->curr.fs; | ||||
|       struct svga_fs_compile_key key; | ||||
|    struct svga_fragment_shader *fs = svga->curr.fs; | ||||
|    struct svga_fs_compile_key key; | ||||
|  | ||||
|       /* SVGA_NEW_TEXTURE_BINDING | ||||
|        * SVGA_NEW_RAST | ||||
|        * SVGA_NEW_NEED_SWTNL | ||||
|        * SVGA_NEW_SAMPLER | ||||
|        */ | ||||
|       ret = make_fs_key( svga, &key ); | ||||
|    /* SVGA_NEW_BLEND | ||||
|     * SVGA_NEW_TEXTURE_BINDING | ||||
|     * SVGA_NEW_RAST | ||||
|     * SVGA_NEW_NEED_SWTNL | ||||
|     * SVGA_NEW_SAMPLER | ||||
|     */ | ||||
|    ret = make_fs_key( svga, &key ); | ||||
|    if (ret) | ||||
|       return ret; | ||||
|  | ||||
|    result = search_fs_key( fs, &key ); | ||||
|    if (!result) { | ||||
|       ret = compile_fs( svga, fs, &key, &result ); | ||||
|       if (ret) | ||||
|          return ret; | ||||
|  | ||||
|       result = search_fs_key( fs, &key ); | ||||
|       if (!result) { | ||||
|          ret = compile_fs( svga, fs, &key, &result ); | ||||
|          if (ret) | ||||
|             return ret; | ||||
|       } | ||||
|  | ||||
|       assert (result); | ||||
|       id = result->id; | ||||
|    } | ||||
|  | ||||
|    assert (result); | ||||
|    id = result->id; | ||||
|  | ||||
|    assert(id != SVGA3D_INVALID_ID); | ||||
|  | ||||
|    if (result != svga->state.hw_draw.fs) { | ||||
|   | ||||
| @@ -101,6 +101,19 @@ static int emit_rss( struct svga_context *svga, | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (dirty & SVGA_NEW_BLEND_COLOR) { | ||||
|       uint32 color; | ||||
|       uint32 r = float_to_ubyte(svga->curr.blend_color.color[0]); | ||||
|       uint32 g = float_to_ubyte(svga->curr.blend_color.color[1]); | ||||
|       uint32 b = float_to_ubyte(svga->curr.blend_color.color[2]); | ||||
|       uint32 a = float_to_ubyte(svga->curr.blend_color.color[3]); | ||||
|  | ||||
|       color = (a << 24) | (r << 16) | (g << 8) | b; | ||||
|  | ||||
|       EMIT_RS( svga, color, BLENDCOLOR, fail ); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (dirty & (SVGA_NEW_DEPTH_STENCIL | SVGA_NEW_RAST)) { | ||||
|       const struct svga_depth_stencil_state *curr = svga->curr.depth;  | ||||
|       const struct svga_rasterizer_state *rast = svga->curr.rast;  | ||||
| @@ -179,18 +192,28 @@ static int emit_rss( struct svga_context *svga, | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (dirty & SVGA_NEW_RAST) | ||||
|    if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE)) | ||||
|    { | ||||
|       const struct svga_rasterizer_state *curr = svga->curr.rast;  | ||||
|       unsigned cullmode = curr->cullmode; | ||||
|  | ||||
|       /* Shademode: still need to rearrange index list to move | ||||
|        * flat-shading PV first vertex. | ||||
|        */ | ||||
|       EMIT_RS( svga, curr->shademode, SHADEMODE, fail ); | ||||
|       EMIT_RS( svga, curr->cullmode, CULLMODE, fail ); | ||||
|  | ||||
|       /* Don't do culling while the software pipeline is active.  It | ||||
|        * does it for us, and additionally introduces potentially | ||||
|        * back-facing triangles. | ||||
|        */ | ||||
|       if (svga->state.sw.need_pipeline) | ||||
|          cullmode = SVGA3D_FACE_NONE; | ||||
|  | ||||
|       EMIT_RS( svga, cullmode, CULLMODE, fail ); | ||||
|       EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail ); | ||||
|       EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail ); | ||||
|       EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail ); | ||||
|       EMIT_RS( svga, curr->pointspriteenable, POINTSPRITEENABLE, fail ); | ||||
|       EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail ); | ||||
|       EMIT_RS_FLOAT( svga, curr->pointsize, POINTSIZE, fail ); | ||||
|       EMIT_RS_FLOAT( svga, curr->pointsize_min, POINTSIZEMIN, fail ); | ||||
| @@ -230,13 +253,10 @@ static int emit_rss( struct svga_context *svga, | ||||
|       memcpy( rs, | ||||
|               queue.rs, | ||||
|               queue.rs_count * sizeof queue.rs[0]); | ||||
|        | ||||
|  | ||||
|       SVGA_FIFOCommitAll( svga->swc ); | ||||
|    } | ||||
|  | ||||
|    /* Also blend color: | ||||
|     */ | ||||
|  | ||||
|    return 0; | ||||
|  | ||||
| fail: | ||||
| @@ -256,6 +276,7 @@ struct svga_tracked_state svga_hw_rss = | ||||
|    "hw rss state", | ||||
|  | ||||
|    (SVGA_NEW_BLEND | | ||||
|     SVGA_NEW_BLEND_COLOR | | ||||
|     SVGA_NEW_DEPTH_STENCIL | | ||||
|     SVGA_NEW_RAST | | ||||
|     SVGA_NEW_FRAME_BUFFER | | ||||
|   | ||||
| @@ -54,33 +54,30 @@ upload_user_buffers( struct svga_context *svga ) | ||||
|    { | ||||
|       if (svga_buffer_is_user_buffer(svga->curr.vb[i].buffer)) | ||||
|       { | ||||
|          struct pipe_buffer *upload_buffer = NULL; | ||||
|          unsigned offset = /*svga->curr.vb[i].buffer_offset*/ 0; | ||||
|          unsigned size = svga->curr.vb[i].buffer->size /*- offset*/; | ||||
|          unsigned upload_offset; | ||||
|          struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer); | ||||
|  | ||||
|          ret = u_upload_buffer( svga->upload_vb, | ||||
|                                 offset, | ||||
|                                 size, | ||||
|                                 svga->curr.vb[i].buffer, | ||||
|                                 &upload_offset, | ||||
|                                 &upload_buffer ); | ||||
|          if (ret) | ||||
|             return ret; | ||||
|          if (!buffer->uploaded.buffer) { | ||||
|             ret = u_upload_buffer( svga->upload_vb, | ||||
|                                    0, | ||||
|                                    buffer->base.size, | ||||
|                                    &buffer->base, | ||||
|                                    &buffer->uploaded.offset, | ||||
|                                    &buffer->uploaded.buffer ); | ||||
|             if (ret) | ||||
|                return ret; | ||||
|  | ||||
|          if (0) | ||||
|             debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sz %d\n",  | ||||
|                          __FUNCTION__,  | ||||
|                          i, | ||||
|                          svga->curr.vb[i].buffer, | ||||
|                          upload_buffer, upload_offset, size); | ||||
|             if (0) | ||||
|                debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sz %d\n", | ||||
|                             __FUNCTION__, | ||||
|                             i, | ||||
|                             buffer, | ||||
|                             buffer->uploaded.buffer, | ||||
|                             buffer->uploaded.offset, | ||||
|                             buffer->base.size); | ||||
|          } | ||||
|  | ||||
|          /* Make sure we release the old buffer and end up with the | ||||
|           * correct refcount on the uploaded buffer. | ||||
|           */ | ||||
|          pipe_buffer_reference( &svga->curr.vb[i].buffer, NULL ); | ||||
|          svga->curr.vb[i].buffer = upload_buffer; | ||||
|          svga->curr.vb[i].buffer_offset = upload_offset; | ||||
|          pipe_buffer_reference( &svga->curr.vb[i].buffer, buffer->uploaded.buffer ); | ||||
|          svga->curr.vb[i].buffer_offset = buffer->uploaded.offset; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|   | ||||
| @@ -49,6 +49,7 @@ struct svga_fs_compile_key | ||||
| { | ||||
|    boolean light_twoside:1; | ||||
|    boolean front_cw:1; | ||||
|    boolean white_fragments:1; | ||||
|    ubyte num_textures; | ||||
|    ubyte num_unnormalized_coords; | ||||
|    struct { | ||||
|   | ||||
| @@ -194,8 +194,19 @@ static boolean ps30_output( struct svga_shader_emitter *emit, | ||||
|  | ||||
|    switch (semantic.SemanticName) { | ||||
|    case TGSI_SEMANTIC_COLOR: | ||||
|       emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT,  | ||||
|                                             semantic.SemanticIndex ); | ||||
|       if (emit->unit == PIPE_SHADER_FRAGMENT && | ||||
|           emit->key.fkey.white_fragments) { | ||||
|  | ||||
|          emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, | ||||
|                                                emit->nr_hw_temp++ ); | ||||
|          emit->temp_col[idx] = emit->output_map[idx]; | ||||
|          emit->true_col[idx] = dst_register( SVGA3DREG_COLOROUT,  | ||||
|                                               semantic.SemanticIndex ); | ||||
|       } | ||||
|       else { | ||||
|          emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT,  | ||||
|                                                semantic.SemanticIndex ); | ||||
|       } | ||||
|       break; | ||||
|    case TGSI_SEMANTIC_POSITION: | ||||
|       emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, | ||||
|   | ||||
| @@ -79,6 +79,8 @@ struct svga_shader_emitter | ||||
|  | ||||
|    int ps30_input_count; | ||||
|  | ||||
|    int dynamic_branching_level; | ||||
|  | ||||
|    boolean in_main_func; | ||||
|  | ||||
|    boolean created_zero_immediate; | ||||
| @@ -136,6 +138,7 @@ static INLINE boolean emit_dst( struct svga_shader_emitter *emit, | ||||
|                          SVGA3dShaderDestToken dest ) | ||||
| { | ||||
|    assert(dest.reserved0); | ||||
|    assert(dest.mask); | ||||
|    return svga_shader_emit_dword( emit, dest.value ); | ||||
| } | ||||
|  | ||||
| @@ -199,6 +202,23 @@ static INLINE boolean emit_op3( struct svga_shader_emitter *emit, | ||||
| } | ||||
|  | ||||
|  | ||||
| static INLINE boolean emit_op4( struct svga_shader_emitter *emit, | ||||
|                                 SVGA3dShaderInstToken inst, | ||||
|                                 SVGA3dShaderDestToken dest, | ||||
|                                 struct src_register src0, | ||||
|                                 struct src_register src1, | ||||
|                                 struct src_register src2, | ||||
|                                 struct src_register src3) | ||||
| { | ||||
|    return (emit_instruction( emit, inst ) && | ||||
|            emit_dst( emit, dest ) && | ||||
|            emit_src( emit, src0 ) && | ||||
|            emit_src( emit, src1 ) && | ||||
|            emit_src( emit, src2 ) && | ||||
|            emit_src( emit, src3 )); | ||||
| } | ||||
|  | ||||
|  | ||||
| #define TRANSLATE_SWIZZLE(x,y,z,w)  ((x) | ((y) << 2) | ((z) << 4) | ((w) << 6)) | ||||
| #define SWIZZLE_XYZW  \ | ||||
|  TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_W) | ||||
| @@ -248,6 +268,7 @@ static INLINE SVGA3dShaderDestToken | ||||
| writemask( SVGA3dShaderDestToken dest, | ||||
|            unsigned mask ) | ||||
| { | ||||
|    assert(dest.mask & mask); | ||||
|    dest.mask &= mask; | ||||
|    return dest; | ||||
| } | ||||
|   | ||||
| @@ -46,8 +46,6 @@ translate_opcode( | ||||
|    case TGSI_OPCODE_ABS:        return SVGA3DOP_ABS; | ||||
|    case TGSI_OPCODE_ADD:        return SVGA3DOP_ADD; | ||||
|    case TGSI_OPCODE_BREAKC:     return SVGA3DOP_BREAKC; | ||||
|    case TGSI_OPCODE_DDX:        return SVGA3DOP_DSX; | ||||
|    case TGSI_OPCODE_DDY:        return SVGA3DOP_DSY; | ||||
|    case TGSI_OPCODE_DP2A:       return SVGA3DOP_DP2ADD; | ||||
|    case TGSI_OPCODE_DP3:        return SVGA3DOP_DP3; | ||||
|    case TGSI_OPCODE_DP4:        return SVGA3DOP_DP4; | ||||
| @@ -114,6 +112,7 @@ translate_dst_register( struct svga_shader_emitter *emit, | ||||
|    } | ||||
|  | ||||
|    dest.mask = reg->DstRegister.WriteMask; | ||||
|    assert(dest.mask); | ||||
|  | ||||
|    if (insn->Instruction.Saturate)  | ||||
|       dest.dstMod = SVGA3DDSTMOD_SATURATE; | ||||
| @@ -415,6 +414,88 @@ static boolean submit_op3( struct svga_shader_emitter *emit, | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* SVGA shaders may not refer to >1 constant register in a single | ||||
|  * instruction.  This function checks for that usage and inserts a | ||||
|  * move to temporary if detected. | ||||
|  */ | ||||
| static boolean submit_op4( struct svga_shader_emitter *emit, | ||||
|                            SVGA3dShaderInstToken inst, | ||||
|                            SVGA3dShaderDestToken dest, | ||||
|                            struct src_register src0, | ||||
|                            struct src_register src1, | ||||
|                            struct src_register src2, | ||||
|                            struct src_register src3) | ||||
| { | ||||
|    SVGA3dShaderDestToken temp0; | ||||
|    SVGA3dShaderDestToken temp3; | ||||
|    boolean need_temp0 = FALSE; | ||||
|    boolean need_temp3 = FALSE; | ||||
|    SVGA3dShaderRegType type0, type1, type2, type3; | ||||
|  | ||||
|    temp0.value = 0; | ||||
|    temp3.value = 0; | ||||
|    type0 = SVGA3dShaderGetRegType( src0.base.value ); | ||||
|    type1 = SVGA3dShaderGetRegType( src1.base.value ); | ||||
|    type2 = SVGA3dShaderGetRegType( src2.base.value ); | ||||
|    type3 = SVGA3dShaderGetRegType( src2.base.value ); | ||||
|  | ||||
|    /* Make life a little easier - this is only used by the TXD | ||||
|     * instruction which is guaranteed not to have a constant/input reg | ||||
|     * in one slot at least: | ||||
|     */ | ||||
|    assert(type1 == SVGA3DREG_SAMPLER); | ||||
|  | ||||
|    if (type0 == SVGA3DREG_CONST && | ||||
|        ((type3 == SVGA3DREG_CONST && src0.base.num != src3.base.num) || | ||||
|         (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num))) | ||||
|       need_temp0 = TRUE; | ||||
|  | ||||
|    if (type3 == SVGA3DREG_CONST && | ||||
|        (type2 == SVGA3DREG_CONST && src3.base.num != src2.base.num)) | ||||
|       need_temp3 = TRUE; | ||||
|  | ||||
|    if (type0 == SVGA3DREG_INPUT && | ||||
|        ((type3 == SVGA3DREG_INPUT && src0.base.num != src3.base.num) || | ||||
|         (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num))) | ||||
|       need_temp0 = TRUE; | ||||
|  | ||||
|    if (type3 == SVGA3DREG_INPUT && | ||||
|        (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num)) | ||||
|       need_temp3 = TRUE; | ||||
|  | ||||
|    if (need_temp0) | ||||
|    { | ||||
|       temp0 = get_temp( emit ); | ||||
|   | ||||
|       if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 )) | ||||
|          return FALSE; | ||||
|           | ||||
|       src0 = src( temp0 ); | ||||
|    } | ||||
|  | ||||
|    if (need_temp3) | ||||
|    { | ||||
|       temp3 = get_temp( emit ); | ||||
|  | ||||
|       if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp3, src3 )) | ||||
|          return FALSE; | ||||
|  | ||||
|       src3 = src( temp3 ); | ||||
|    } | ||||
|  | ||||
|    if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 )) | ||||
|       return FALSE; | ||||
|  | ||||
|    if (need_temp3) | ||||
|       release_temp( emit, temp3 ); | ||||
|    if (need_temp0) | ||||
|       release_temp( emit, temp0 ); | ||||
|    return TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static boolean emit_def_const( struct svga_shader_emitter *emit, | ||||
|                                SVGA3dShaderConstType type, | ||||
|                                unsigned idx, | ||||
| @@ -660,6 +741,8 @@ static boolean emit_if(struct svga_shader_emitter *emit, | ||||
|    if_token.control = SVGA3DOPCOMPC_NE; | ||||
|    zero = scalar(zero, TGSI_SWIZZLE_X); | ||||
|  | ||||
|    emit->dynamic_branching_level++; | ||||
|  | ||||
|    return (emit_instruction( emit, if_token ) && | ||||
|            emit_src( emit, src ) && | ||||
|            emit_src( emit, zero ) ); | ||||
| @@ -668,6 +751,8 @@ static boolean emit_if(struct svga_shader_emitter *emit, | ||||
| static boolean emit_endif(struct svga_shader_emitter *emit, | ||||
|                        const struct tgsi_full_instruction *insn) | ||||
| { | ||||
|    emit->dynamic_branching_level--; | ||||
|  | ||||
|    return (emit_instruction( emit, | ||||
|                              inst_token( SVGA3DOP_ENDIF ))); | ||||
| } | ||||
| @@ -1011,10 +1096,10 @@ static boolean emit_kilp(struct svga_shader_emitter *emit, | ||||
| { | ||||
|    SVGA3dShaderInstToken inst; | ||||
|    SVGA3dShaderDestToken temp; | ||||
|    struct src_register one = get_zero_immediate( emit ); | ||||
|    struct src_register one = scalar( get_zero_immediate( emit ), | ||||
|                                      TGSI_SWIZZLE_W ); | ||||
|  | ||||
|    inst = inst_token( SVGA3DOP_TEXKILL ); | ||||
|    one = scalar( one, TGSI_SWIZZLE_W ); | ||||
|  | ||||
|    /* texkill doesn't allow negation on the operand so lets move | ||||
|     * negation of {1} to a temp register */ | ||||
| @@ -1169,41 +1254,79 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, | ||||
|                          SVGA3dShaderDestToken dst ) | ||||
| { | ||||
|    SVGA3dShaderInstToken inst; | ||||
|    struct src_register src0; | ||||
|    struct src_register src1; | ||||
|  | ||||
|    struct src_register texcoord; | ||||
|    struct src_register sampler; | ||||
|    SVGA3dShaderDestToken tmp; | ||||
|     | ||||
|    inst.value = 0; | ||||
|    inst.op = SVGA3DOP_TEX; | ||||
|  | ||||
|    switch (insn->Instruction.Opcode) { | ||||
|    case TGSI_OPCODE_TEX: | ||||
|       inst.op = SVGA3DOP_TEX; | ||||
|       break; | ||||
|    case TGSI_OPCODE_TXP: | ||||
|       inst.op = SVGA3DOP_TEX; | ||||
|       inst.control = SVGA3DOPCONT_PROJECT; | ||||
|       break; | ||||
|    case TGSI_OPCODE_TXB: | ||||
|       inst.op = SVGA3DOP_TEX; | ||||
|       inst.control = SVGA3DOPCONT_BIAS; | ||||
|       break; | ||||
|    case TGSI_OPCODE_TXL: | ||||
|       inst.op = SVGA3DOP_TEXLDL; | ||||
|       break; | ||||
|    default: | ||||
|       assert(0); | ||||
|       return FALSE; | ||||
|    } | ||||
|  | ||||
|    src0 = translate_src_register( emit, &insn->FullSrcRegisters[0] ); | ||||
|    src1 = translate_src_register( emit, &insn->FullSrcRegisters[1] ); | ||||
|    texcoord = translate_src_register( emit, &insn->FullSrcRegisters[0] ); | ||||
|    sampler = translate_src_register( emit, &insn->FullSrcRegisters[1] ); | ||||
|  | ||||
|    if (emit->key.fkey.tex[src1.base.num].unnormalized) { | ||||
|       struct src_register wh = get_tex_dimensions( emit, src1.base.num ); | ||||
|       SVGA3dShaderDestToken tmp = get_temp( emit ); | ||||
|    if (emit->key.fkey.tex[sampler.base.num].unnormalized || | ||||
|        emit->dynamic_branching_level > 0) | ||||
|       tmp = get_temp( emit ); | ||||
|  | ||||
|    /* Can't do mipmapping inside dynamic branch constructs.  Force LOD | ||||
|     * zero in that case. | ||||
|     */ | ||||
|    if (emit->dynamic_branching_level > 0 && | ||||
|        inst.op == SVGA3DOP_TEX && | ||||
|        SVGA3dShaderGetRegType(texcoord.base.value) == SVGA3DREG_TEMP) { | ||||
|       struct src_register zero = get_zero_immediate( emit ); | ||||
|  | ||||
|       /* MOV  tmp, texcoord */ | ||||
|       if (!submit_op1( emit, | ||||
|                        inst_token( SVGA3DOP_MOV ), | ||||
|                        tmp, | ||||
|                        texcoord )) | ||||
|          return FALSE; | ||||
|  | ||||
|       /* MOV  tmp.w, zero */ | ||||
|       if (!submit_op1( emit,  | ||||
|                        inst_token( SVGA3DOP_MOV ), | ||||
|                        writemask( tmp, TGSI_WRITEMASK_W ),  | ||||
|                        scalar( zero, TGSI_SWIZZLE_X ))) | ||||
|          return FALSE; | ||||
|        | ||||
|       texcoord = src( tmp ); | ||||
|       inst.op = SVGA3DOP_TEXLDL; | ||||
|    } | ||||
|  | ||||
|    /* Explicit normalization of texcoords: | ||||
|     */ | ||||
|    if (emit->key.fkey.tex[sampler.base.num].unnormalized) { | ||||
|       struct src_register wh = get_tex_dimensions( emit, sampler.base.num ); | ||||
|  | ||||
|       /* MUL  tmp, SRC0, WH */ | ||||
|       if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), | ||||
|                        tmp, src0, wh )) | ||||
|                        tmp, texcoord, wh )) | ||||
|          return FALSE; | ||||
|       src0 = src( tmp ); | ||||
|  | ||||
|       texcoord = src( tmp ); | ||||
|    } | ||||
|  | ||||
|    return submit_op2( emit, inst, dst, src0, src1 ); | ||||
|    return submit_op2( emit, inst, dst, texcoord, sampler ); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1211,31 +1334,33 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, | ||||
|  | ||||
| /* Translate texture instructions to SVGA3D representation. | ||||
|  */ | ||||
| static boolean emit_tex3(struct svga_shader_emitter *emit, | ||||
| static boolean emit_tex4(struct svga_shader_emitter *emit, | ||||
|                          const struct tgsi_full_instruction *insn, | ||||
|                          SVGA3dShaderDestToken dst ) | ||||
| { | ||||
|    SVGA3dShaderInstToken inst; | ||||
|    struct src_register src0; | ||||
|    struct src_register src1; | ||||
|    struct src_register src2; | ||||
|    struct src_register texcoord; | ||||
|    struct src_register ddx; | ||||
|    struct src_register ddy; | ||||
|    struct src_register sampler; | ||||
|  | ||||
|    texcoord = translate_src_register( emit, &insn->FullSrcRegisters[0] ); | ||||
|    ddx      = translate_src_register( emit, &insn->FullSrcRegisters[1] ); | ||||
|    ddy      = translate_src_register( emit, &insn->FullSrcRegisters[2] ); | ||||
|    sampler  = translate_src_register( emit, &insn->FullSrcRegisters[3] ); | ||||
|  | ||||
|    inst.value = 0; | ||||
|  | ||||
|    switch (insn->Instruction.Opcode) { | ||||
|    case TGSI_OPCODE_TXD:  | ||||
|       inst.op = SVGA3DOP_TEXLDD; | ||||
|       break; | ||||
|    case TGSI_OPCODE_TXL: | ||||
|       inst.op = SVGA3DOP_TEXLDL; | ||||
|       inst.op = SVGA3DOP_TEXLDD; /* 4 args! */ | ||||
|       break; | ||||
|    default: | ||||
|       assert(0); | ||||
|       return FALSE; | ||||
|    } | ||||
|  | ||||
|    src0 = translate_src_register( emit, &insn->FullSrcRegisters[0] ); | ||||
|    src1 = translate_src_register( emit, &insn->FullSrcRegisters[1] ); | ||||
|    src2 = translate_src_register( emit, &insn->FullSrcRegisters[2] ); | ||||
|  | ||||
|    return submit_op3( emit, inst, dst, src0, src1, src2 ); | ||||
|    return submit_op4( emit, inst, dst, texcoord, sampler, ddx, ddy ); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1271,12 +1396,12 @@ static boolean emit_tex(struct svga_shader_emitter *emit, | ||||
|    case TGSI_OPCODE_TEX: | ||||
|    case TGSI_OPCODE_TXB: | ||||
|    case TGSI_OPCODE_TXP: | ||||
|    case TGSI_OPCODE_TXL: | ||||
|       if (!emit_tex2( emit, insn, tex_result )) | ||||
|          return FALSE; | ||||
|       break; | ||||
|    case TGSI_OPCODE_TXL: | ||||
|    case TGSI_OPCODE_TXD: | ||||
|       if (!emit_tex3( emit, insn, tex_result )) | ||||
|       if (!emit_tex4( emit, insn, tex_result )) | ||||
|          return FALSE; | ||||
|       break; | ||||
|    default: | ||||
| @@ -1285,34 +1410,42 @@ static boolean emit_tex(struct svga_shader_emitter *emit, | ||||
|  | ||||
|  | ||||
|    if (compare) { | ||||
|       SVGA3dShaderDestToken src0_zdivw = get_temp( emit ); | ||||
|       struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y); | ||||
|       struct src_register one = | ||||
|          scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W ); | ||||
|       if (dst.mask & TGSI_WRITEMASK_XYZ) { | ||||
|          SVGA3dShaderDestToken src0_zdivw = get_temp( emit ); | ||||
|          struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y); | ||||
|  | ||||
|       /* Divide texcoord R by Q */ | ||||
|       if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ), | ||||
|                        src0_zdivw, | ||||
|                        scalar(src0, TGSI_SWIZZLE_W) )) | ||||
|          return FALSE; | ||||
|          /* Divide texcoord R by Q */ | ||||
|          if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ), | ||||
|                           writemask(src0_zdivw, TGSI_WRITEMASK_X), | ||||
|                           scalar(src0, TGSI_SWIZZLE_W) )) | ||||
|             return FALSE; | ||||
|  | ||||
|       if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), | ||||
|                        src0_zdivw, | ||||
|                        scalar(src0, TGSI_SWIZZLE_Z), | ||||
|                        src(src0_zdivw) )) | ||||
|          return FALSE; | ||||
|          if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), | ||||
|                           writemask(src0_zdivw, TGSI_WRITEMASK_X), | ||||
|                           scalar(src0, TGSI_SWIZZLE_Z), | ||||
|                           scalar(src(src0_zdivw), TGSI_SWIZZLE_X) )) | ||||
|             return FALSE; | ||||
|  | ||||
|       if (!emit_select( | ||||
|              emit, | ||||
|              emit->key.fkey.tex[src1.base.num].compare_func, | ||||
|              dst, | ||||
|              src(src0_zdivw), | ||||
|              tex_src_x)) | ||||
|          return FALSE; | ||||
|          if (!emit_select( | ||||
|                 emit, | ||||
|                 emit->key.fkey.tex[src1.base.num].compare_func, | ||||
|                 writemask( dst, TGSI_WRITEMASK_XYZ ), | ||||
|                 scalar(src(src0_zdivw), TGSI_SWIZZLE_X), | ||||
|                 tex_src_x)) | ||||
|             return FALSE; | ||||
|       } | ||||
|  | ||||
|       return submit_op1( emit, inst_token( SVGA3DOP_MOV ), | ||||
|                          writemask( dst, TGSI_WRITEMASK_W), | ||||
|                          one ); | ||||
|       if (dst.mask & TGSI_WRITEMASK_W) { | ||||
|          struct src_register one = | ||||
|             scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W ); | ||||
|  | ||||
|         if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), | ||||
|                          writemask( dst, TGSI_WRITEMASK_W ), | ||||
|                          one )) | ||||
|            return FALSE; | ||||
|       } | ||||
|  | ||||
|       return TRUE; | ||||
|    } | ||||
|    else if (!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW)  | ||||
|    { | ||||
| @@ -1330,6 +1463,8 @@ static boolean emit_bgnloop2( struct svga_shader_emitter *emit, | ||||
|    struct src_register loop_reg = src_register( SVGA3DREG_LOOP, 0 ); | ||||
|    struct src_register const_int = get_loop_const( emit ); | ||||
|  | ||||
|    emit->dynamic_branching_level++; | ||||
|  | ||||
|    return (emit_instruction( emit, inst ) && | ||||
|            emit_src( emit, loop_reg ) && | ||||
|            emit_src( emit, const_int ) ); | ||||
| @@ -1339,6 +1474,9 @@ static boolean emit_endloop2( struct svga_shader_emitter *emit, | ||||
|                               const struct tgsi_full_instruction *insn ) | ||||
| { | ||||
|    SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_ENDLOOP ); | ||||
|  | ||||
|    emit->dynamic_branching_level--; | ||||
|  | ||||
|    return emit_instruction( emit, inst ); | ||||
| } | ||||
|  | ||||
| @@ -1398,6 +1536,46 @@ static boolean emit_simple_instruction(struct svga_shader_emitter *emit, | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static boolean emit_deriv(struct svga_shader_emitter *emit, | ||||
|                           const struct tgsi_full_instruction *insn ) | ||||
| { | ||||
|    if (emit->dynamic_branching_level > 0 && | ||||
|        insn->FullSrcRegisters[0].SrcRegister.File == TGSI_FILE_TEMPORARY)  | ||||
|    { | ||||
|       struct src_register zero = get_zero_immediate( emit ); | ||||
|       SVGA3dShaderDestToken dst =  | ||||
|          translate_dst_register( emit, insn, 0 ); | ||||
|  | ||||
|       /* Deriv opcodes not valid inside dynamic branching, workaround | ||||
|        * by zeroing out the destination. | ||||
|        */ | ||||
|       if (!submit_op1(emit,  | ||||
|                       inst_token( SVGA3DOP_MOV ),  | ||||
|                       dst, | ||||
|                       scalar(zero, TGSI_SWIZZLE_X))) | ||||
|          return FALSE; | ||||
|        | ||||
|       return TRUE; | ||||
|    } | ||||
|    else { | ||||
|       unsigned opcode; | ||||
|  | ||||
|       switch (insn->Instruction.Opcode) { | ||||
|       case TGSI_OPCODE_DDX: | ||||
|          opcode = SVGA3DOP_DSX; | ||||
|          break; | ||||
|       case TGSI_OPCODE_DDY: | ||||
|          opcode = SVGA3DOP_DSY; | ||||
|          break; | ||||
|       default: | ||||
|          return FALSE; | ||||
|       } | ||||
|  | ||||
|       return emit_simple_instruction( emit, opcode, insn ); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static boolean emit_arl(struct svga_shader_emitter *emit, | ||||
|                         const struct tgsi_full_instruction *insn) | ||||
| { | ||||
| @@ -1655,13 +1833,13 @@ static boolean emit_exp(struct svga_shader_emitter *emit, | ||||
|     */ | ||||
|    if (dst.mask & TGSI_WRITEMASK_X) { | ||||
|       if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), | ||||
|                        writemask( dst, dst.mask & TGSI_WRITEMASK_X ), | ||||
|                        writemask( dst, TGSI_WRITEMASK_X ), | ||||
|                        src0, | ||||
|                        scalar( negate( src( fraction ) ), TGSI_SWIZZLE_Y ) ) ) | ||||
|          return FALSE; | ||||
|  | ||||
|       if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ), | ||||
|                        writemask( dst, dst.mask & TGSI_WRITEMASK_X ), | ||||
|                        writemask( dst, TGSI_WRITEMASK_X ), | ||||
|                        scalar( src( dst ), TGSI_SWIZZLE_X ) ) ) | ||||
|          return FALSE; | ||||
|  | ||||
| @@ -1673,7 +1851,7 @@ static boolean emit_exp(struct svga_shader_emitter *emit, | ||||
|     */ | ||||
|    if (dst.mask & TGSI_WRITEMASK_Z) { | ||||
|       if (!submit_op1( emit, inst_token( SVGA3DOP_EXPP ), | ||||
|                        writemask( dst, dst.mask & TGSI_WRITEMASK_Z ), | ||||
|                        writemask( dst, TGSI_WRITEMASK_Z ), | ||||
|                        src0 ) ) | ||||
|          return FALSE; | ||||
|    } | ||||
| @@ -2002,6 +2180,10 @@ static boolean svga_emit_instruction( struct svga_shader_emitter *emit, | ||||
|    case TGSI_OPCODE_TXD: | ||||
|       return emit_tex( emit, insn ); | ||||
|  | ||||
|    case TGSI_OPCODE_DDX: | ||||
|    case TGSI_OPCODE_DDY: | ||||
|       return emit_deriv( emit, insn ); | ||||
|  | ||||
|    case TGSI_OPCODE_BGNSUB: | ||||
|       return emit_bgnsub( emit, position, insn ); | ||||
|  | ||||
| @@ -2254,11 +2436,28 @@ static boolean emit_ps_postamble( struct svga_shader_emitter *emit ) | ||||
|    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { | ||||
|       if (SVGA3dShaderGetRegType(emit->true_col[i].value) != 0) { | ||||
|  | ||||
|          if (!submit_op1( emit, | ||||
|                           inst_token(SVGA3DOP_MOV), | ||||
|                           emit->true_col[i], | ||||
|                           src(emit->temp_col[i]) )) | ||||
|             return FALSE; | ||||
|          /* Potentially override output colors with white for XOR | ||||
|           * logicop workaround. | ||||
|           */ | ||||
|          if (emit->unit == PIPE_SHADER_FRAGMENT && | ||||
|              emit->key.fkey.white_fragments) { | ||||
|  | ||||
|             struct src_register one = scalar( get_zero_immediate( emit ), | ||||
|                                               TGSI_SWIZZLE_W ); | ||||
|  | ||||
|             if (!submit_op1( emit, | ||||
|                              inst_token(SVGA3DOP_MOV), | ||||
|                              emit->true_col[i], | ||||
|                              one )) | ||||
|                return FALSE; | ||||
|          } | ||||
|          else { | ||||
|             if (!submit_op1( emit, | ||||
|                              inst_token(SVGA3DOP_MOV), | ||||
|                              emit->true_col[i], | ||||
|                              src(emit->temp_col[i]) )) | ||||
|                return FALSE; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
| @@ -2467,6 +2666,9 @@ needs_to_create_zero( struct svga_shader_emitter *emit ) | ||||
|       if (emit->key.fkey.light_twoside) | ||||
|          return TRUE; | ||||
|  | ||||
|       if (emit->key.fkey.white_fragments) | ||||
|          return TRUE; | ||||
|  | ||||
|       if (emit->emit_frontface) | ||||
|          return TRUE; | ||||
|  | ||||
| @@ -2476,6 +2678,10 @@ needs_to_create_zero( struct svga_shader_emitter *emit ) | ||||
|    } | ||||
|  | ||||
|    if (emit->info.opcode_count[TGSI_OPCODE_IF] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_BGNFOR] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_DDX] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_DDY] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_SGE] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_SGT] >= 1 || | ||||
|        emit->info.opcode_count[TGSI_OPCODE_SLE] >= 1 || | ||||
| @@ -2702,6 +2908,8 @@ boolean svga_shader_emit_instructions( struct svga_shader_emitter *emit, | ||||
|          goto done; | ||||
|    } | ||||
|  | ||||
|    assert(emit->dynamic_branching_level == 0); | ||||
|  | ||||
|    /* Need to terminate the whole shader: | ||||
|     */ | ||||
|    ret = emit_instruction( emit, inst_token( SVGA3DOP_END ) ); | ||||
|   | ||||
| @@ -281,6 +281,9 @@ svga_screen_create(struct svga_winsys_screen *sws); | ||||
| struct svga_winsys_screen * | ||||
| svga_winsys_screen(struct pipe_screen *screen); | ||||
|  | ||||
| struct svga_winsys_context * | ||||
| svga_winsys_context(struct pipe_context *context); | ||||
|  | ||||
| struct pipe_buffer * | ||||
| svga_screen_buffer_wrap_surface(struct pipe_screen *screen, | ||||
| 				enum SVGA3dSurfaceFormat format, | ||||
|   | ||||
| @@ -132,14 +132,22 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv) | ||||
|    boolean have_depth = FALSE; | ||||
|    int i, count; | ||||
|  | ||||
|    buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable, | ||||
| 						     &dri_drawable->w, | ||||
| 						     &dri_drawable->h, | ||||
| 						     drawable->attachments, | ||||
| 						     drawable-> | ||||
| 						     num_attachments, &count, | ||||
| 						     dri_drawable-> | ||||
| 						     loaderPrivate); | ||||
|    if ((dri_screen->dri2.loader | ||||
|         && (dri_screen->dri2.loader->base.version > 2) | ||||
|         && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) | ||||
|       buffers = (*dri_screen->dri2.loader->getBuffersWithFormat) | ||||
|                 (dri_drawable, &dri_drawable->w, &dri_drawable->h, | ||||
|                  drawable->attachments, drawable->num_attachments, | ||||
|                  &count, dri_drawable->loaderPrivate); | ||||
|    else | ||||
|       buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable, | ||||
|                                                         &dri_drawable->w, | ||||
|                                                         &dri_drawable->h, | ||||
|                                                         drawable->attachments, | ||||
|                                                         drawable-> | ||||
|                                                         num_attachments, &count, | ||||
|                                                         dri_drawable-> | ||||
|                                                         loaderPrivate); | ||||
|  | ||||
|    if (buffers == NULL) { | ||||
|       return; | ||||
| @@ -346,12 +354,12 @@ dri_create_buffer(__DRIscreenPrivate * sPriv, | ||||
|    case 24: | ||||
|       if (visual->stencilBits == 0) { | ||||
| 	 drawable->depth_stencil_format = (screen->d_depth_bits_last) ? | ||||
| 	    PIPE_FORMAT_X8Z24_UNORM: | ||||
| 	    PIPE_FORMAT_Z24X8_UNORM; | ||||
|                                           PIPE_FORMAT_X8Z24_UNORM: | ||||
|                                           PIPE_FORMAT_Z24X8_UNORM; | ||||
|       } else { | ||||
| 	 drawable->depth_stencil_format = (screen->sd_depth_bits_last) ? | ||||
| 	    PIPE_FORMAT_S8Z24_UNORM: | ||||
| 	    PIPE_FORMAT_Z24S8_UNORM; | ||||
|                                           PIPE_FORMAT_S8Z24_UNORM: | ||||
|                                           PIPE_FORMAT_Z24S8_UNORM; | ||||
|       } | ||||
|       break; | ||||
|    case 32: | ||||
| @@ -375,23 +383,49 @@ dri_create_buffer(__DRIscreenPrivate * sPriv, | ||||
|    /* setup dri2 buffers information */ | ||||
|    /* TODO incase of double buffer visual, delay fake creation */ | ||||
|    i = 0; | ||||
|    drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; | ||||
|    if (!screen->auto_fake_front) | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; | ||||
|    if (visual->doubleBufferMode) | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; | ||||
|    if (visual->depthBits && visual->stencilBits) | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; | ||||
|    else if (visual->depthBits) | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_DEPTH; | ||||
|    else if (visual->stencilBits) | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_STENCIL; | ||||
|    drawable->num_attachments = i; | ||||
|    if (sPriv->dri2.loader | ||||
|        && (sPriv->dri2.loader->base.version > 2) | ||||
|        && (sPriv->dri2.loader->getBuffersWithFormat != NULL)) { | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; | ||||
|       drawable->attachments[i++] = visual->rgbBits; | ||||
|       if (!screen->auto_fake_front)  { | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; | ||||
|          drawable->attachments[i++] = visual->rgbBits; | ||||
|       } | ||||
|       if (visual->doubleBufferMode) { | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; | ||||
|          drawable->attachments[i++] = visual->rgbBits; | ||||
|       } | ||||
|       if (visual->depthBits && visual->stencilBits) { | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; | ||||
|          drawable->attachments[i++] = visual->depthBits + visual->stencilBits; | ||||
|       } else if (visual->depthBits) { | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_DEPTH; | ||||
|          drawable->attachments[i++] = visual->depthBits; | ||||
|       } else if (visual->stencilBits) { | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_STENCIL; | ||||
|          drawable->attachments[i++] = visual->stencilBits; | ||||
|       } | ||||
|       drawable->num_attachments = i / 2; | ||||
|    } else { | ||||
|       drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; | ||||
|       if (!screen->auto_fake_front) | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; | ||||
|       if (visual->doubleBufferMode) | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; | ||||
|       if (visual->depthBits && visual->stencilBits) | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; | ||||
|       else if (visual->depthBits) | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_DEPTH; | ||||
|       else if (visual->stencilBits) | ||||
|          drawable->attachments[i++] = __DRI_BUFFER_STENCIL; | ||||
|       drawable->num_attachments = i; | ||||
|    } | ||||
|  | ||||
|    drawable->desired_fences = 2; | ||||
|  | ||||
|    return GL_TRUE; | ||||
|  fail: | ||||
| fail: | ||||
|    FREE(drawable); | ||||
|    return GL_FALSE; | ||||
| } | ||||
|   | ||||
| @@ -80,6 +80,9 @@ dri_fill_in_modes(struct dri_screen *screen, | ||||
| 		  unsigned pixel_bits) | ||||
| { | ||||
|    __DRIconfig **configs = NULL; | ||||
|    __DRIconfig **configs_r5g6b5 = NULL; | ||||
|    __DRIconfig **configs_a8r8g8b8 = NULL; | ||||
|    __DRIconfig **configs_x8r8g8b8 = NULL; | ||||
|    unsigned num_modes; | ||||
|    uint8_t depth_bits_array[5]; | ||||
|    uint8_t stencil_bits_array[5]; | ||||
| @@ -99,12 +102,6 @@ dri_fill_in_modes(struct dri_screen *screen, | ||||
|    stencil_bits_array[0] = 0; | ||||
|    depth_buffer_factor = 1; | ||||
|  | ||||
|    pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, | ||||
| 					  PIPE_TEXTURE_2D, | ||||
| 					  PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); | ||||
|    pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, | ||||
| 					  PIPE_TEXTURE_2D, | ||||
| 					  PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); | ||||
|    pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, | ||||
| 					    PIPE_TEXTURE_2D, | ||||
| 					    PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); | ||||
| @@ -117,15 +114,30 @@ dri_fill_in_modes(struct dri_screen *screen, | ||||
|    pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM, | ||||
| 					    PIPE_TEXTURE_2D, | ||||
| 					    PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); | ||||
|    pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_R5G6B5_UNORM, | ||||
| 					     PIPE_TEXTURE_2D, | ||||
| 					     PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); | ||||
|    pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_A8R8G8B8_UNORM, | ||||
| 					       PIPE_TEXTURE_2D, | ||||
| 					       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); | ||||
|    pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8R8G8B8_UNORM, | ||||
| 					       PIPE_TEXTURE_2D, | ||||
| 					       PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); | ||||
|    pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_R5G6B5_UNORM, | ||||
| 					     PIPE_TEXTURE_2D, | ||||
| 					     PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); | ||||
|  | ||||
|    /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */ | ||||
|    if (screen->sPriv->dri2.loader && | ||||
|        (screen->sPriv->dri2.loader->base.version > 2) && | ||||
|        (screen->sPriv->dri2.loader->getBuffersWithFormat != NULL)) { | ||||
|       pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, | ||||
|                                              PIPE_TEXTURE_2D, | ||||
|                                              PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); | ||||
|       pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, | ||||
|                                              PIPE_TEXTURE_2D, | ||||
|                                              PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); | ||||
|    } else { | ||||
|       pf_z16 = FALSE; | ||||
|       pf_z32 = FALSE; | ||||
|    } | ||||
|  | ||||
|    if (pf_z16) { | ||||
|       depth_bits_array[depth_buffer_factor] = 16; | ||||
| @@ -153,41 +165,43 @@ dri_fill_in_modes(struct dri_screen *screen, | ||||
|    num_modes = | ||||
|       depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4; | ||||
|  | ||||
|    if (pixel_bits == 16 && pf_r5g6b5) { | ||||
|       configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, | ||||
| 				 depth_bits_array, stencil_bits_array, | ||||
| 				 depth_buffer_factor, back_buffer_modes, | ||||
| 				 back_buffer_factor, | ||||
| 				 msaa_samples_array, 1); | ||||
|    if (pf_r5g6b5) | ||||
|       configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, | ||||
|                                         depth_bits_array, stencil_bits_array, | ||||
|                                         depth_buffer_factor, back_buffer_modes, | ||||
|                                         back_buffer_factor, | ||||
|                                         msaa_samples_array, 1); | ||||
|  | ||||
|    if (pf_a8r8g8b8) | ||||
|       configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, | ||||
|                                           depth_bits_array, | ||||
|                                           stencil_bits_array, | ||||
|                                           depth_buffer_factor, | ||||
|                                           back_buffer_modes, | ||||
|                                           back_buffer_factor, | ||||
|                                           msaa_samples_array, 1); | ||||
|  | ||||
|    if (pf_x8r8g8b8) | ||||
|       configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, | ||||
|                                           depth_bits_array, | ||||
|                                           stencil_bits_array, | ||||
|                                           depth_buffer_factor, | ||||
|                                           back_buffer_modes, | ||||
|                                           back_buffer_factor, | ||||
|                                           msaa_samples_array, 1); | ||||
|  | ||||
|    if (pixel_bits == 16) { | ||||
|       configs = configs_r5g6b5; | ||||
|       if (configs_a8r8g8b8) | ||||
|          configs = configs ? driConcatConfigs(configs, configs_a8r8g8b8) : configs_a8r8g8b8; | ||||
|       if (configs_x8r8g8b8) | ||||
| 	 configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8; | ||||
|    } else { | ||||
|       __DRIconfig **configs_a8r8g8b8 = NULL; | ||||
|       __DRIconfig **configs_x8r8g8b8 = NULL; | ||||
|  | ||||
|       if (pf_a8r8g8b8) | ||||
| 	 configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, | ||||
| 					     depth_bits_array, | ||||
| 					     stencil_bits_array, | ||||
| 					     depth_buffer_factor, | ||||
| 					     back_buffer_modes, | ||||
| 					     back_buffer_factor, | ||||
| 					     msaa_samples_array, 1); | ||||
|       if (pf_x8r8g8b8) | ||||
| 	 configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, | ||||
| 					     depth_bits_array, | ||||
| 					     stencil_bits_array, | ||||
| 					     depth_buffer_factor, | ||||
| 					     back_buffer_modes, | ||||
| 					     back_buffer_factor, | ||||
| 					     msaa_samples_array, 1); | ||||
|  | ||||
|       if (configs_a8r8g8b8 && configs_x8r8g8b8) | ||||
| 	 configs = driConcatConfigs(configs_x8r8g8b8, configs_a8r8g8b8); | ||||
|       else if (configs_a8r8g8b8) | ||||
| 	 configs = configs_a8r8g8b8; | ||||
|       else if (configs_x8r8g8b8) | ||||
| 	 configs = configs_x8r8g8b8; | ||||
|       else | ||||
| 	 configs = NULL; | ||||
|       configs = configs_a8r8g8b8; | ||||
|       if (configs_x8r8g8b8) | ||||
| 	 configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8; | ||||
|       if (configs_r5g6b5) | ||||
|          configs = configs ? driConcatConfigs(configs, configs_r5g6b5) : configs_r5g6b5; | ||||
|    } | ||||
|  | ||||
|    if (configs == NULL) { | ||||
|   | ||||
| @@ -21,6 +21,7 @@ if 'python' in env['statetrackers']: | ||||
|             'gdi32', | ||||
|             'user32', | ||||
|             'kernel32', | ||||
|             'ws2_32', | ||||
|         ]) | ||||
|     else: | ||||
|         env.Append(LIBS = [ | ||||
|   | ||||
| @@ -531,6 +531,8 @@ class Context(Object): | ||||
|                     gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f', | ||||
|                     gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f', | ||||
|                     gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B', | ||||
|                     gallium.PIPE_FORMAT_R8G8B8A8_UNORM: '4B', | ||||
|                     gallium.PIPE_FORMAT_R16G16B16_SNORM: '3h', | ||||
|                 }[velem.src_format] | ||||
|  | ||||
|                 data = vbuf.buffer.read() | ||||
| @@ -557,7 +559,7 @@ class Context(Object): | ||||
|  | ||||
|         sys.stdout.write('\t{\n') | ||||
|         for i in range(start, start + count): | ||||
|             if i >= start + 16: | ||||
|             if i >= start + 16 and not self.interpreter.verbosity(3): | ||||
|                 sys.stdout.write('\t...\n') | ||||
|                 break | ||||
|             offset = i*isize | ||||
|   | ||||
| @@ -362,7 +362,7 @@ EXPORTS | ||||
| 	wglShareLists | ||||
| 	wglSwapBuffers | ||||
| 	wglSwapLayerBuffers | ||||
| ;	wglSwapMultipleBuffers | ||||
| 	wglSwapMultipleBuffers | ||||
| 	wglUseFontBitmapsA | ||||
| 	wglUseFontBitmapsW | ||||
| 	wglUseFontOutlinesA | ||||
|   | ||||
| @@ -362,7 +362,7 @@ EXPORTS | ||||
| 	wglShareLists = wglShareLists@8 | ||||
| 	wglSwapBuffers = wglSwapBuffers@4 | ||||
| 	wglSwapLayerBuffers = wglSwapLayerBuffers@8 | ||||
| ;	wglSwapMultipleBuffers = wglSwapMultipleBuffers@8 | ||||
| 	wglSwapMultipleBuffers = wglSwapMultipleBuffers@8 | ||||
| 	wglUseFontBitmapsA = wglUseFontBitmapsA@16 | ||||
| 	wglUseFontBitmapsW = wglUseFontBitmapsW@16 | ||||
| 	wglUseFontOutlinesA = wglUseFontOutlinesA@32 | ||||
|   | ||||
| @@ -80,6 +80,9 @@ DrvCopyContext( | ||||
|    struct stw_context *dst; | ||||
|    BOOL ret = FALSE; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return FALSE; | ||||
|  | ||||
|    pipe_mutex_lock( stw_dev->ctx_mutex ); | ||||
|     | ||||
|    src = stw_lookup_context_locked( dhrcSource ); | ||||
| @@ -107,13 +110,15 @@ DrvShareLists( | ||||
|    struct stw_context *ctx2; | ||||
|    BOOL ret = FALSE; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return FALSE; | ||||
|  | ||||
|    pipe_mutex_lock( stw_dev->ctx_mutex ); | ||||
|     | ||||
|    ctx1 = stw_lookup_context_locked( dhglrc1 ); | ||||
|    ctx2 = stw_lookup_context_locked( dhglrc2 ); | ||||
|  | ||||
|    if (ctx1 && ctx2 && | ||||
|        ctx1->iPixelFormat == ctx2->iPixelFormat) {  | ||||
|    if (ctx1 && ctx2) { | ||||
|       ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx); | ||||
|    } | ||||
|  | ||||
|   | ||||
| @@ -152,24 +152,27 @@ stw_cleanup_thread(void) | ||||
| void | ||||
| stw_cleanup(void) | ||||
| { | ||||
|    unsigned i; | ||||
|    DHGLRC dhglrc; | ||||
|  | ||||
|    debug_printf("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return; | ||||
|     | ||||
|    /* | ||||
|     * Abort cleanup if there are still active contexts. In some situations | ||||
|     * this DLL may be unloaded before the DLL that is using GL contexts is. | ||||
|     */ | ||||
|    pipe_mutex_lock( stw_dev->ctx_mutex ); | ||||
|    { | ||||
|       /* Ensure all contexts are destroyed */ | ||||
|       i = handle_table_get_first_handle(stw_dev->ctx_table); | ||||
|       while (i) { | ||||
|          DrvDeleteContext(i); | ||||
|          i = handle_table_get_next_handle(stw_dev->ctx_table, i); | ||||
|       } | ||||
|       handle_table_destroy(stw_dev->ctx_table); | ||||
|    } | ||||
|    dhglrc = handle_table_get_first_handle(stw_dev->ctx_table); | ||||
|    pipe_mutex_unlock( stw_dev->ctx_mutex ); | ||||
|    if (dhglrc) { | ||||
|       debug_printf("%s: contexts still active -- cleanup aborted\n", __FUNCTION__); | ||||
|       stw_dev = NULL; | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    handle_table_destroy(stw_dev->ctx_table); | ||||
|  | ||||
|    stw_framebuffer_cleanup(); | ||||
|     | ||||
|   | ||||
| @@ -178,7 +178,7 @@ stw_call_window_proc( | ||||
|    if(!tls_data) | ||||
|       return 0; | ||||
|     | ||||
|    if (nCode < 0) | ||||
|    if (nCode < 0 || !stw_dev) | ||||
|        return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); | ||||
|  | ||||
|    if (pParams->message == WM_WINDOWPOSCHANGED) { | ||||
| @@ -333,6 +333,9 @@ stw_framebuffer_cleanup( void ) | ||||
|    struct stw_framebuffer *fb; | ||||
|    struct stw_framebuffer *next; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return; | ||||
|  | ||||
|    pipe_mutex_lock( stw_dev->fb_mutex ); | ||||
|  | ||||
|    fb = stw_dev->fb_head; | ||||
| @@ -388,6 +391,9 @@ stw_framebuffer_from_hdc( | ||||
| { | ||||
|    struct stw_framebuffer *fb; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return NULL; | ||||
|  | ||||
|    pipe_mutex_lock( stw_dev->fb_mutex ); | ||||
|    fb = stw_framebuffer_from_hdc_locked(hdc); | ||||
|    pipe_mutex_unlock( stw_dev->fb_mutex ); | ||||
| @@ -422,6 +428,9 @@ DrvSetPixelFormat( | ||||
|    uint index; | ||||
|    struct stw_framebuffer *fb; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return FALSE; | ||||
|  | ||||
|    index = (uint) iPixelFormat - 1; | ||||
|    count = stw_pixelformat_get_extended_count(); | ||||
|    if (index >= count) | ||||
| @@ -476,6 +485,9 @@ DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data) | ||||
|    struct pipe_screen *screen; | ||||
|    struct pipe_surface *surface; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return FALSE; | ||||
|  | ||||
|    fb = stw_framebuffer_from_hdc( hdc ); | ||||
|    if (fb == NULL) | ||||
|       return FALSE; | ||||
| @@ -577,6 +589,9 @@ DrvSwapBuffers( | ||||
|    struct stw_framebuffer *fb; | ||||
|    struct pipe_surface *surface = NULL; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return FALSE; | ||||
|  | ||||
|    fb = stw_framebuffer_from_hdc( hdc ); | ||||
|    if (fb == NULL) | ||||
|       return FALSE; | ||||
|   | ||||
| @@ -34,6 +34,8 @@ | ||||
|  | ||||
| #include "glapi/glapi.h" | ||||
| #include "stw_ext_gallium.h" | ||||
| #include "stw_device.h" | ||||
| #include "stw_icd.h" | ||||
|  | ||||
| struct stw_extension_entry | ||||
| { | ||||
| @@ -73,6 +75,9 @@ DrvGetProcAddress( | ||||
| { | ||||
|    const struct stw_extension_entry *entry; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return NULL; | ||||
|  | ||||
|    if (lpszProc[0] == 'w' && lpszProc[1] == 'g' && lpszProc[2] == 'l') | ||||
|       for (entry = stw_extension_entries; entry->name; entry++) | ||||
|          if (strcmp( lpszProc, entry->name ) == 0) | ||||
|   | ||||
| @@ -303,6 +303,9 @@ DrvDescribePixelFormat( | ||||
|  | ||||
|    (void) hdc; | ||||
|  | ||||
|    if (!stw_dev) | ||||
|       return 0; | ||||
|  | ||||
|    count = stw_pixelformat_get_extended_count(); | ||||
|    index = (uint) iPixelFormat - 1; | ||||
|  | ||||
|   | ||||
| @@ -97,6 +97,19 @@ wglSwapBuffers( | ||||
| } | ||||
|  | ||||
|  | ||||
| WINGDIAPI DWORD WINAPI | ||||
| wglSwapMultipleBuffers(UINT n, | ||||
|                        CONST WGLSWAP *ps) | ||||
| { | ||||
|    UINT i; | ||||
|  | ||||
|    for (i =0; i < n; ++i) | ||||
|       wglSwapBuffers(ps->hdc); | ||||
|  | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| WINGDIAPI BOOL APIENTRY | ||||
| wglSwapLayerBuffers( | ||||
|    HDC hdc, | ||||
|   | ||||
| @@ -59,5 +59,21 @@ wglSetPixelFormat(HDC hdc, | ||||
|                   int iPixelFormat, | ||||
|                   CONST PIXELFORMATDESCRIPTOR *ppfd); | ||||
|  | ||||
| #if defined(__MINGW32__) || (WINVER < 0x0500) | ||||
|  | ||||
| typedef struct _WGLSWAP | ||||
| { | ||||
|    HDC hdc; | ||||
|    UINT uiFlags; | ||||
| } WGLSWAP; | ||||
|  | ||||
| #define WGL_SWAPMULTIPLE_MAX 16 | ||||
|  | ||||
| WINGDIAPI DWORD WINAPI | ||||
| wglSwapMultipleBuffers(UINT n, | ||||
|                        CONST WGLSWAP *ps); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #endif /* STW_WGL_H_ */ | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #include <xf86.h> | ||||
| #include <xf86i2c.h> | ||||
| #include <xf86Crtc.h> | ||||
| #include <cursorstr.h> | ||||
| #include "xorg_tracker.h" | ||||
| #include "xf86Modes.h" | ||||
|  | ||||
| @@ -146,6 +147,7 @@ crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue, | ||||
|     /* XXX: hockup */ | ||||
| } | ||||
|  | ||||
| #if 0 /* Implement and enable to enable rotation and reflection. */ | ||||
| static void * | ||||
| crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) | ||||
| { | ||||
| @@ -168,6 +170,8 @@ crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) | ||||
|     /* ScrnInfoPtr pScrn = crtc->scrn; */ | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Cursor functions | ||||
|  */ | ||||
| @@ -243,7 +247,11 @@ crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) | ||||
| 	unsigned attr[8]; | ||||
|  | ||||
| 	attr[0] = KMS_BO_TYPE; | ||||
| #ifdef KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8 | ||||
| 	attr[1] = KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; | ||||
| #else | ||||
| 	attr[1] = KMS_BO_TYPE_CURSOR; | ||||
| #endif | ||||
| 	attr[2] = KMS_WIDTH; | ||||
| 	attr[3] = 64; | ||||
| 	attr[4] = KMS_HEIGHT; | ||||
| @@ -272,7 +280,21 @@ err_bo_destroy: | ||||
| static void | ||||
| crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) | ||||
| { | ||||
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); | ||||
|     modesettingPtr ms = modesettingPTR(crtc->scrn); | ||||
|  | ||||
|     /* Older X servers have cursor reference counting bugs leading to use of | ||||
|      * freed memory and consequently random crashes. Should be fixed as of | ||||
|      * xserver 1.8, but this workaround shouldn't hurt anyway. | ||||
|      */ | ||||
|     if (config->cursor) | ||||
|        config->cursor->refcnt++; | ||||
|  | ||||
|     if (ms->cursor) | ||||
|        FreeCursor(ms->cursor, None); | ||||
|  | ||||
|     ms->cursor = config->cursor; | ||||
|  | ||||
|     if (ms->screen) | ||||
| 	crtc_load_cursor_argb_ga3d(crtc, image); | ||||
| #ifdef HAVE_LIBKMS | ||||
| @@ -344,9 +366,9 @@ static const xf86CrtcFuncsRec crtc_funcs = { | ||||
|     .hide_cursor = crtc_hide_cursor, | ||||
|     .load_cursor_argb = crtc_load_cursor_argb, | ||||
|  | ||||
|     .shadow_create = crtc_shadow_create, | ||||
|     .shadow_allocate = crtc_shadow_allocate, | ||||
|     .shadow_destroy = crtc_shadow_destroy, | ||||
|     .shadow_create = NULL, | ||||
|     .shadow_allocate = NULL, | ||||
|     .shadow_destroy = NULL, | ||||
|  | ||||
|     .gamma_set = crtc_gamma_set, | ||||
|     .destroy = crtc_destroy, | ||||
|   | ||||
| @@ -102,14 +102,26 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form | ||||
| 	    pipe_texture_reference(&tex, exa_priv->depth_stencil_tex); | ||||
|         else { | ||||
| 	    struct pipe_texture template; | ||||
|             unsigned depthBits = (format != 0) ? format : pDraw->depth; | ||||
| 	    memset(&template, 0, sizeof(template)); | ||||
| 	    template.target = PIPE_TEXTURE_2D; | ||||
| 	    if (buffer->attachment == DRI2BufferDepth) | ||||
| 		template.format = ms->ds_depth_bits_last ? | ||||
| 		    PIPE_FORMAT_X8Z24_UNORM : PIPE_FORMAT_Z24X8_UNORM; | ||||
| 	    else | ||||
| 		template.format = ms->ds_depth_bits_last ? | ||||
| 		    PIPE_FORMAT_S8Z24_UNORM : PIPE_FORMAT_Z24S8_UNORM; | ||||
| 	    if (buffer->attachment == DRI2BufferDepth) { | ||||
|                switch(depthBits) { | ||||
|                case 16: | ||||
|                   template.format = PIPE_FORMAT_Z16_UNORM; | ||||
|                   break; | ||||
|                case 32: | ||||
|                   template.format = PIPE_FORMAT_Z32_UNORM; | ||||
|                   break; | ||||
|                default: | ||||
|                   template.format = ms->ds_depth_bits_last ? | ||||
|                                     PIPE_FORMAT_X8Z24_UNORM : PIPE_FORMAT_Z24X8_UNORM; | ||||
|                   break; | ||||
|                } | ||||
|             } else { | ||||
|                template.format = ms->ds_depth_bits_last ? | ||||
|                                  PIPE_FORMAT_S8Z24_UNORM : PIPE_FORMAT_Z24S8_UNORM; | ||||
|             } | ||||
| 	    pf_get_block(template.format, &template.block); | ||||
| 	    template.width[0] = pDraw->width; | ||||
| 	    template.height[0] = pDraw->height; | ||||
| @@ -283,6 +295,7 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, | ||||
|     GCPtr gc; | ||||
|     RegionPtr copy_clip; | ||||
|     Bool save_accel; | ||||
|     CustomizerPtr cust = ms->cust; | ||||
|  | ||||
|     /* | ||||
|      * In driCreateBuffers we dewrap windows into the | ||||
| @@ -336,7 +349,8 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, | ||||
|     ValidateGC(dst_draw, gc); | ||||
|  | ||||
|     /* If this is a full buffer swap, throttle on the previous one */ | ||||
|     if (dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) { | ||||
|     if (ms->swapThrottling && | ||||
| 	dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) { | ||||
| 	BoxPtr extents = REGION_EXTENTS(pScreen, pRegion); | ||||
|  | ||||
| 	if (extents->x1 == 0 && extents->y1 == 0 && | ||||
| @@ -358,6 +372,9 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, | ||||
|     DamageRegionAppend(src_draw, pRegion); | ||||
|     DamageRegionProcessPending(src_draw); | ||||
|  | ||||
|    if (cust && cust->winsys_context_throttle) | ||||
|        cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_SWAP); | ||||
|  | ||||
|     (*gc->ops->CopyArea)(src_draw, dst_draw, gc, | ||||
| 			 0, 0, pDraw->width, pDraw->height, 0, 0); | ||||
|     ms->exa->accel = save_accel; | ||||
| @@ -365,8 +382,13 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, | ||||
|     FreeScratchGC(gc); | ||||
|  | ||||
|     ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS, | ||||
| 		   pDestBuffer->attachment == DRI2BufferFrontLeft ? | ||||
| 		   (pDestBuffer->attachment == DRI2BufferFrontLeft | ||||
| 		    && ms->swapThrottling) ? | ||||
| 		   &dst_priv->fence : NULL); | ||||
|  | ||||
|    if (cust && cust->winsys_context_throttle) | ||||
|        cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_RENDER); | ||||
|  | ||||
| } | ||||
|  | ||||
| Bool | ||||
|   | ||||
| @@ -79,12 +79,16 @@ typedef enum | ||||
|     OPTION_SW_CURSOR, | ||||
|     OPTION_2D_ACCEL, | ||||
|     OPTION_DEBUG_FALLBACK, | ||||
|     OPTION_THROTTLE_SWAP, | ||||
|     OPTION_THROTTLE_DIRTY | ||||
| } drv_option_enums; | ||||
|  | ||||
| static const OptionInfoRec drv_options[] = { | ||||
|     {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, | ||||
|     {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, | ||||
|     {OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE}, | ||||
|     {OPTION_THROTTLE_SWAP, "SwapThrottling", OPTV_BOOLEAN, {0}, FALSE}, | ||||
|     {OPTION_THROTTLE_DIRTY, "DirtyThrottling", OPTV_BOOLEAN, {0}, FALSE}, | ||||
|     {-1, NULL, OPTV_NONE, {0}, FALSE} | ||||
| }; | ||||
|  | ||||
| @@ -155,7 +159,7 @@ drv_get_rec(ScrnInfoPtr pScrn) | ||||
|     if (pScrn->driverPrivate) | ||||
| 	return TRUE; | ||||
|  | ||||
|     pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1); | ||||
|     pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec)); | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
| @@ -183,31 +187,66 @@ drv_probe_ddc(ScrnInfoPtr pScrn, int index) | ||||
| static Bool | ||||
| drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) | ||||
| { | ||||
|     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     PixmapPtr rootPixmap; | ||||
|     ScreenPtr pScreen = pScrn->pScreen; | ||||
|     int old_width, old_height; | ||||
|     PixmapPtr rootPixmap; | ||||
|     int i; | ||||
|  | ||||
|     if (width == pScrn->virtualX && height == pScrn->virtualY) | ||||
| 	return TRUE; | ||||
|  | ||||
|     old_width = pScrn->virtualX; | ||||
|     old_height = pScrn->virtualY; | ||||
|     pScrn->virtualX = width; | ||||
|     pScrn->virtualY = height; | ||||
|  | ||||
|     /* | ||||
|      * Remove the old framebuffer & texture. | ||||
|      */ | ||||
|     drmModeRmFB(ms->fd, ms->fb_id); | ||||
|     if (!ms->destroy_front_buffer(pScrn)) | ||||
| 	FatalError("failed to destroy front buffer\n"); | ||||
|     /* ms->create_front_buffer will remove the old front buffer */ | ||||
|  | ||||
|     rootPixmap = pScreen->GetScreenPixmap(pScreen); | ||||
|     if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) | ||||
| 	return FALSE; | ||||
| 	goto error_modify; | ||||
|  | ||||
|     pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8); | ||||
|  | ||||
|     /* now create new frontbuffer */ | ||||
|     return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn); | ||||
|     if (!ms->create_front_buffer(pScrn) || !ms->bind_front_buffer(pScrn)) | ||||
| 	goto error_create; | ||||
|  | ||||
|     /* | ||||
|      * create && bind will turn off all crtc(s) in the kernel so we need to | ||||
|      * re-enable all the crtcs again. For real HW we might want to do this | ||||
|      * before destroying the old framebuffer. | ||||
|      */ | ||||
|     for (i = 0; i < xf86_config->num_crtc; i++) { | ||||
| 	xf86CrtcPtr crtc = xf86_config->crtc[i]; | ||||
|  | ||||
| 	if (!crtc->enabled) | ||||
| 	    continue; | ||||
|  | ||||
| 	crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); | ||||
|     } | ||||
|  | ||||
|     return TRUE; | ||||
|  | ||||
|     /* | ||||
|      * This is the error recovery path. | ||||
|      */ | ||||
| error_create: | ||||
|     if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL)) | ||||
| 	FatalError("failed to resize rootPixmap error path\n"); | ||||
|  | ||||
|     pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8); | ||||
|  | ||||
| error_modify: | ||||
|     pScrn->virtualX = old_width; | ||||
|     pScrn->virtualY = old_height; | ||||
|  | ||||
|     if (ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn)) | ||||
| 	return FALSE; | ||||
|  | ||||
|     FatalError("failed to setup old framebuffer\n"); | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static const xf86CrtcConfigFuncsRec crtc_config_funcs = { | ||||
| @@ -333,6 +372,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) | ||||
|     EntityInfoPtr pEnt; | ||||
|     EntPtr msEnt = NULL; | ||||
|     int max_width, max_height; | ||||
|     CustomizerPtr cust; | ||||
|  | ||||
|     if (pScrn->numEntities != 1) | ||||
| 	return FALSE; | ||||
| @@ -344,6 +384,9 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) | ||||
| 	return TRUE; | ||||
|     } | ||||
|  | ||||
|     cust = (CustomizerPtr) pScrn->driverPrivate; | ||||
|     pScrn->driverPrivate = NULL; | ||||
|  | ||||
|     /* Allocate driverPrivate */ | ||||
|     if (!drv_get_rec(pScrn)) | ||||
| 	return FALSE; | ||||
| @@ -351,6 +394,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) | ||||
|     ms = modesettingPTR(pScrn); | ||||
|     ms->SaveGeneration = -1; | ||||
|     ms->pEnt = pEnt; | ||||
|     ms->cust = cust; | ||||
|  | ||||
|     pScrn->displayWidth = 640;	       /* default it */ | ||||
|  | ||||
| @@ -423,8 +467,8 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) | ||||
|     xf86CrtcConfigInit(pScrn, &crtc_config_funcs); | ||||
|     xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); | ||||
|  | ||||
|     max_width = 8192; | ||||
|     max_height = 8192; | ||||
|     max_width = 2048;  /* A very low default */ | ||||
|     max_height = 2048; /* see screen_init */ | ||||
|     xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height); | ||||
|  | ||||
|     if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { | ||||
| @@ -510,23 +554,29 @@ static void drv_block_handler(int i, pointer blockData, pointer pTimeout, | ||||
|     if (ms->ctx) { | ||||
|        int j; | ||||
|  | ||||
|        ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, &ms->fence[XORG_NR_FENCES-1]); | ||||
|        ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, | ||||
| 		      ms->dirtyThrottling ? | ||||
| 		      &ms->fence[XORG_NR_FENCES-1] : | ||||
| 		      NULL); | ||||
|         | ||||
|        if (ms->fence[0]) | ||||
|           ms->ctx->screen->fence_finish(ms->ctx->screen, ms->fence[0], 0); | ||||
|        if (ms->dirtyThrottling) { | ||||
| 	   if (ms->fence[0]) | ||||
| 	       ms->ctx->screen->fence_finish(ms->ctx->screen, | ||||
| 					     ms->fence[0], 0); | ||||
|    | ||||
|        /* The amount of rendering generated by a block handler can be | ||||
|         * quite small.  Let us get a fair way ahead of hardware before | ||||
|         * throttling. | ||||
|         */ | ||||
|        for (j = 0; j < XORG_NR_FENCES - 1; j++) | ||||
|           ms->screen->fence_reference(ms->screen, | ||||
|                                       &ms->fence[j], | ||||
|                                       ms->fence[j+1]); | ||||
| 	   /* The amount of rendering generated by a block handler can be | ||||
| 	    * quite small.  Let us get a fair way ahead of hardware before | ||||
| 	    * throttling. | ||||
| 	    */ | ||||
| 	   for (j = 0; j < XORG_NR_FENCES - 1; j++) | ||||
| 	       ms->screen->fence_reference(ms->screen, | ||||
| 					   &ms->fence[j], | ||||
| 					   ms->fence[j+1]); | ||||
|  | ||||
|        ms->screen->fence_reference(ms->screen, | ||||
|                                    &ms->fence[XORG_NR_FENCES-1], | ||||
|                                    NULL); | ||||
| 	   ms->screen->fence_reference(ms->screen, | ||||
| 				       &ms->fence[XORG_NR_FENCES-1], | ||||
| 				       NULL); | ||||
|        } | ||||
|     } | ||||
|          | ||||
|  | ||||
| @@ -607,7 +657,11 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     unsigned max_width, max_height; | ||||
|     VisualPtr visual; | ||||
|     CustomizerPtr cust = ms->cust; | ||||
|     MessageType from_st; | ||||
|     MessageType from_dt; | ||||
|  | ||||
|     if (!drv_init_drm(pScrn)) { | ||||
| 	FatalError("Could not init DRM"); | ||||
| @@ -624,6 +678,26 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | ||||
| 	return FALSE; | ||||
|     } | ||||
|  | ||||
|     /* get max width and height */ | ||||
|     { | ||||
| 	drmModeResPtr res; | ||||
| 	res = drmModeGetResources(ms->fd); | ||||
| 	max_width = res->max_width; | ||||
| 	max_height = res->max_height; | ||||
| 	drmModeFreeResources(res); | ||||
|     } | ||||
|  | ||||
|     if (ms->screen) { | ||||
| 	float maxf; | ||||
| 	int max; | ||||
| 	maxf = ms->screen->get_paramf(ms->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); | ||||
| 	max = (1 << (int)(maxf - 1.0f)); | ||||
| 	max_width = max < max_width ? max : max_width; | ||||
| 	max_height = max < max_height ? max : max_height; | ||||
|     } | ||||
|  | ||||
|     xf86CrtcSetSizeRange(pScrn, 1, 1, max_width, max_height); | ||||
|  | ||||
|     pScrn->pScreen = pScreen; | ||||
|  | ||||
|     /* HW dependent - FIXME */ | ||||
| @@ -673,7 +747,20 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | ||||
|     xf86SetBlackWhitePixels(pScreen); | ||||
|  | ||||
|     ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE); | ||||
|     ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, TRUE); | ||||
|     ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d); | ||||
|  | ||||
|     if (cust && cust->winsys_screen_init) | ||||
| 	cust->winsys_screen_init(cust, ms->fd); | ||||
|  | ||||
|     ms->swapThrottling = cust ?  cust->swap_throttling : TRUE; | ||||
|     from_st = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_SWAP, | ||||
| 				&ms->swapThrottling) ? | ||||
| 	X_CONFIG : X_DEFAULT; | ||||
|  | ||||
|     ms->dirtyThrottling = cust ?  cust->dirty_throttling : TRUE; | ||||
|     from_dt = xf86GetOptValBool(ms->Options, OPTION_THROTTLE_DIRTY, | ||||
| 				&ms->dirtyThrottling) ? | ||||
| 	X_CONFIG : X_DEFAULT; | ||||
|  | ||||
|     if (ms->screen) { | ||||
| 	ms->exa = xorg_exa_init(pScrn, ms->accelerate_2d); | ||||
| @@ -684,6 +771,11 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "# Usefull debugging info follows #\n"); | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s backend\n", | ||||
| 	       ms->screen ? "Gallium3D" : "libkms"); | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s\n", | ||||
| 	       ms->screen && ms->accelerate_2d ? "enabled" : "disabled"); | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s\n", | ||||
| @@ -694,6 +786,12 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | ||||
| #else | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled\n"); | ||||
| #endif | ||||
|     xf86DrvMsg(pScrn->scrnIndex, from_st, "Swap Throttling is %s.\n", | ||||
| 	       ms->swapThrottling ? "enabled" : "disabled"); | ||||
|     xf86DrvMsg(pScrn->scrnIndex, from_dt, "Dirty Throttling is %s.\n", | ||||
| 	       ms->dirtyThrottling ? "enabled" : "disabled"); | ||||
|  | ||||
|     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); | ||||
|  | ||||
|     miInitializeBackingStore(pScreen); | ||||
|     xf86SetBackingStore(pScreen); | ||||
| @@ -725,9 +823,6 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | ||||
|     if (serverGeneration == 1) | ||||
| 	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); | ||||
|  | ||||
|     if (ms->winsys_screen_init) | ||||
| 	ms->winsys_screen_init(pScrn); | ||||
|  | ||||
|     return drv_enter_vt(scrnIndex, 1); | ||||
| } | ||||
|  | ||||
| @@ -759,10 +854,11 @@ drv_leave_vt(int scrnIndex, int flags) | ||||
|     ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); | ||||
|     CustomizerPtr cust = ms->cust; | ||||
|     int o; | ||||
|  | ||||
|     if (ms->winsys_leave_vt) | ||||
| 	ms->winsys_leave_vt(pScrn); | ||||
|     if (cust && cust->winsys_leave_vt) | ||||
| 	cust->winsys_leave_vt(cust); | ||||
|  | ||||
|     for (o = 0; o < config->num_crtc; o++) { | ||||
| 	xf86CrtcPtr crtc = config->crtc[o]; | ||||
| @@ -778,6 +874,7 @@ drv_leave_vt(int scrnIndex, int flags) | ||||
|     } | ||||
|  | ||||
|     drmModeRmFB(ms->fd, ms->fb_id); | ||||
|     ms->fb_id = -1; | ||||
|  | ||||
|     drv_restore_hw_state(pScrn); | ||||
|  | ||||
| @@ -796,6 +893,7 @@ drv_enter_vt(int scrnIndex, int flags) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     CustomizerPtr cust = ms->cust; | ||||
|  | ||||
|     if (drmSetMaster(ms->fd)) { | ||||
| 	if (errno == EINVAL) { | ||||
| @@ -826,8 +924,8 @@ drv_enter_vt(int scrnIndex, int flags) | ||||
|     if (!xf86SetDesiredModes(pScrn)) | ||||
| 	return FALSE; | ||||
|  | ||||
|     if (ms->winsys_enter_vt) | ||||
| 	ms->winsys_enter_vt(pScrn); | ||||
|     if (cust && cust->winsys_enter_vt) | ||||
| 	cust->winsys_enter_vt(cust); | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
| @@ -845,13 +943,19 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     CustomizerPtr cust = ms->cust; | ||||
|  | ||||
|     if (pScrn->vtSema) { | ||||
| 	drv_leave_vt(scrnIndex, 0); | ||||
|     } | ||||
|  | ||||
|     if (ms->winsys_screen_close) | ||||
| 	ms->winsys_screen_close(pScrn); | ||||
|     if (ms->cursor) { | ||||
|        FreeCursor(ms->cursor, None); | ||||
|        ms->cursor = NULL; | ||||
|     } | ||||
|  | ||||
|     if (cust && cust->winsys_screen_close) | ||||
| 	cust->winsys_screen_close(cust); | ||||
|  | ||||
| #ifdef DRI2 | ||||
|     if (ms->screen) | ||||
| @@ -900,6 +1004,15 @@ static Bool | ||||
| drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn) | ||||
| { | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|  | ||||
|     if (!ms->root_texture) | ||||
| 	return TRUE; | ||||
|  | ||||
|     if (ms->fb_id != -1) { | ||||
| 	drmModeRmFB(ms->fd, ms->fb_id); | ||||
| 	ms->fb_id = -1; | ||||
|     } | ||||
|  | ||||
|     pipe_texture_reference(&ms->root_texture, NULL); | ||||
|     return TRUE; | ||||
| } | ||||
| @@ -908,7 +1021,7 @@ static Bool | ||||
| drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) | ||||
| { | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     unsigned handle, stride; | ||||
|     unsigned handle, stride, fb_id; | ||||
|     struct pipe_texture *tex; | ||||
|     int ret; | ||||
|  | ||||
| @@ -933,19 +1046,23 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) | ||||
| 		       pScrn->bitsPerPixel, | ||||
| 		       stride, | ||||
| 		       handle, | ||||
| 		       &ms->fb_id); | ||||
| 		       &fb_id); | ||||
|     if (ret) { | ||||
| 	debug_printf("%s: failed to create framebuffer (%i, %s)", | ||||
| 	debug_printf("%s: failed to create framebuffer (%i, %s)\n", | ||||
| 		     __func__, ret, strerror(-ret)); | ||||
| 	goto err_destroy; | ||||
|     } | ||||
|  | ||||
|     if (!drv_destroy_front_buffer_ga3d(pScrn)) | ||||
| 	FatalError("%s: failed to take down old framebuffer\n", __func__); | ||||
|  | ||||
|     pScrn->frameX0 = 0; | ||||
|     pScrn->frameY0 = 0; | ||||
|     drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); | ||||
|  | ||||
|     pipe_texture_reference(&ms->root_texture, tex); | ||||
|     pipe_texture_reference(&tex, NULL); | ||||
|     ms->fb_id = fb_id; | ||||
|  | ||||
|     return TRUE; | ||||
|  | ||||
| @@ -993,6 +1110,11 @@ drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn) | ||||
|     if (!ms->root_bo) | ||||
| 	return TRUE; | ||||
|  | ||||
|     if (ms->fb_id != -1) { | ||||
| 	drmModeRmFB(ms->fd, ms->fb_id); | ||||
| 	ms->fb_id = -1; | ||||
|     } | ||||
|  | ||||
|     kms_bo_unmap(ms->root_bo); | ||||
|     kms_bo_destroy(&ms->root_bo); | ||||
|     return TRUE; | ||||
| @@ -1005,10 +1127,15 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn) | ||||
|     unsigned handle, stride; | ||||
|     struct kms_bo *bo; | ||||
|     unsigned attr[8]; | ||||
|     unsigned fb_id; | ||||
|     int ret; | ||||
|  | ||||
|     attr[0] = KMS_BO_TYPE; | ||||
| #ifdef KMS_BO_TYPE_SCANOUT_X8R8G8B8 | ||||
|     attr[1] = KMS_BO_TYPE_SCANOUT_X8R8G8B8; | ||||
| #else | ||||
|     attr[1] = KMS_BO_TYPE_SCANOUT; | ||||
| #endif | ||||
|     attr[2] = KMS_WIDTH; | ||||
|     attr[3] = pScrn->virtualX; | ||||
|     attr[4] = KMS_HEIGHT; | ||||
| @@ -1031,17 +1158,21 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn) | ||||
| 		       pScrn->bitsPerPixel, | ||||
| 		       stride, | ||||
| 		       handle, | ||||
| 		       &ms->fb_id); | ||||
| 		       &fb_id); | ||||
|     if (ret) { | ||||
| 	debug_printf("%s: failed to create framebuffer (%i, %s)", | ||||
| 		     __func__, ret, strerror(-ret)); | ||||
| 	goto err_destroy; | ||||
|     } | ||||
|  | ||||
|     if (!drv_destroy_front_buffer_kms(pScrn)) | ||||
| 	FatalError("%s: could not takedown old bo", __func__); | ||||
|  | ||||
|     pScrn->frameX0 = 0; | ||||
|     pScrn->frameY0 = 0; | ||||
|     drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); | ||||
|     ms->root_bo = bo; | ||||
|     ms->fb_id = fb_id; | ||||
|  | ||||
|     return TRUE; | ||||
|  | ||||
| @@ -1109,4 +1240,14 @@ static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn) | ||||
|     return TRUE; | ||||
| } | ||||
|  | ||||
| CustomizerPtr xorg_customizer(ScrnInfoPtr pScrn) | ||||
| { | ||||
|     return modesettingPTR(pScrn)->cust; | ||||
| } | ||||
|  | ||||
| Bool xorg_has_gallium(ScrnInfoPtr pScrn) | ||||
| { | ||||
|     return modesettingPTR(pScrn)->screen != NULL; | ||||
| } | ||||
|  | ||||
| /* vim: set sw=4 ts=8 sts=4: */ | ||||
|   | ||||
| @@ -1035,6 +1035,7 @@ xorg_exa_init(ScrnInfoPtr pScrn, Bool accel) | ||||
|    modesettingPtr ms = modesettingPTR(pScrn); | ||||
|    struct exa_context *exa; | ||||
|    ExaDriverPtr pExa; | ||||
|    CustomizerPtr cust = ms->cust; | ||||
|  | ||||
|    exa = xcalloc(1, sizeof(struct exa_context)); | ||||
|    if (!exa) | ||||
| @@ -1093,6 +1094,8 @@ xorg_exa_init(ScrnInfoPtr pScrn, Bool accel) | ||||
|    exa->pipe = ms->api->create_context(ms->api, exa->scrn); | ||||
|    /* Share context with DRI */ | ||||
|    ms->ctx = exa->pipe; | ||||
|    if (cust && cust->winsys_context_throttle) | ||||
|        cust->winsys_context_throttle(cust, ms->ctx, THROTTLE_RENDER); | ||||
|  | ||||
|    exa->renderer = renderer_create(exa->pipe); | ||||
|    exa->accel = accel; | ||||
|   | ||||
| @@ -586,7 +586,7 @@ void renderer_copy_pixmap(struct xorg_renderer *r, | ||||
|  | ||||
|  | ||||
| void renderer_draw_yuv(struct xorg_renderer *r, | ||||
|                        int src_x, int src_y, int src_w, int src_h, | ||||
|                        float src_x, float src_y, float src_w, float src_h, | ||||
|                        int dst_x, int dst_y, int dst_w, int dst_h, | ||||
|                        struct pipe_texture **textures) | ||||
| { | ||||
|   | ||||
| @@ -53,7 +53,7 @@ void renderer_set_constants(struct xorg_renderer *r, | ||||
|  | ||||
|  | ||||
| void renderer_draw_yuv(struct xorg_renderer *r, | ||||
|                        int src_x, int src_y, int src_w, int src_h, | ||||
|                        float src_x, float src_y, float src_w, float src_h, | ||||
|                        int dst_x, int dst_y, int dst_w, int dst_h, | ||||
|                        struct pipe_texture **textures); | ||||
|  | ||||
|   | ||||
| @@ -65,6 +65,24 @@ typedef struct | ||||
|  | ||||
| #define XORG_NR_FENCES 3 | ||||
|  | ||||
| enum xorg_throttling_reason { | ||||
|     THROTTLE_RENDER, | ||||
|     THROTTLE_SWAP | ||||
| }; | ||||
|  | ||||
| typedef struct _CustomizerRec | ||||
| { | ||||
|     Bool dirty_throttling; | ||||
|     Bool swap_throttling; | ||||
|     Bool (*winsys_screen_init)(struct _CustomizerRec *cust, int fd); | ||||
|     Bool (*winsys_screen_close)(struct _CustomizerRec *cust); | ||||
|     Bool (*winsys_enter_vt)(struct _CustomizerRec *cust); | ||||
|     Bool (*winsys_leave_vt)(struct _CustomizerRec *cust); | ||||
|     void (*winsys_context_throttle)(struct _CustomizerRec *cust, | ||||
| 				    struct pipe_context *pipe, | ||||
| 				    enum xorg_throttling_reason reason); | ||||
| } CustomizerRec, *CustomizerPtr; | ||||
|  | ||||
| typedef struct _modesettingRec | ||||
| { | ||||
|     /* drm */ | ||||
| @@ -80,6 +98,9 @@ typedef struct _modesettingRec | ||||
|  | ||||
|     Bool noAccel; | ||||
|     Bool SWCursor; | ||||
|     CursorPtr cursor; | ||||
|     Bool swapThrottling; | ||||
|     Bool dirtyThrottling; | ||||
|     CloseScreenProcPtr CloseScreen; | ||||
|  | ||||
|     /* Broken-out options. */ | ||||
| @@ -115,12 +136,7 @@ typedef struct _modesettingRec | ||||
|     Bool accelerate_2d; | ||||
|     Bool debug_fallback; | ||||
|  | ||||
|     /* winsys hocks */ | ||||
|     Bool (*winsys_screen_init)(ScrnInfoPtr pScr); | ||||
|     Bool (*winsys_screen_close)(ScrnInfoPtr pScr); | ||||
|     Bool (*winsys_enter_vt)(ScrnInfoPtr pScr); | ||||
|     Bool (*winsys_leave_vt)(ScrnInfoPtr pScr); | ||||
|     void *winsys_priv; | ||||
|     CustomizerPtr cust; | ||||
|  | ||||
| #ifdef DRM_MODE_FEATURE_DIRTYFB | ||||
|     DamagePtr damage; | ||||
| @@ -129,6 +145,9 @@ typedef struct _modesettingRec | ||||
|  | ||||
| #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) | ||||
|  | ||||
| CustomizerPtr xorg_customizer(ScrnInfoPtr pScrn); | ||||
|  | ||||
| Bool xorg_has_gallium(ScrnInfoPtr pScrn); | ||||
|  | ||||
| /*********************************************************************** | ||||
|  * xorg_exa.c | ||||
|   | ||||
| @@ -384,11 +384,14 @@ setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv) | ||||
|  | ||||
| static void | ||||
| draw_yuv(struct xorg_xv_port_priv *port, | ||||
|          int src_x, int src_y, int src_w, int src_h, | ||||
|          float src_x, float src_y, float src_w, float src_h, | ||||
|          int dst_x, int dst_y, int dst_w, int dst_h) | ||||
| { | ||||
|    struct pipe_texture **textures = port->yuv[port->current_set]; | ||||
|  | ||||
|    /*debug_printf("  draw_yuv([%d, %d, %d ,%d], [%d, %d, %d, %d])\n", | ||||
|                 src_x, src_y, src_w, src_h, | ||||
|                 dst_x, dst_y, dst_w, dst_h);*/ | ||||
|    renderer_draw_yuv(port->r, | ||||
|                      src_x, src_y, src_w, src_h, | ||||
|                      dst_x, dst_y, dst_w, dst_h, | ||||
| @@ -490,6 +493,9 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id, | ||||
|    exaMoveInPixmap(pPixmap); | ||||
|    dst = exaGetPixmapDriverPrivate(pPixmap); | ||||
|  | ||||
|    /*debug_printf("display_video([%d, %d, %d, %d], [%d, %d, %d, %d])\n", | ||||
|      src_x, src_y, src_w, src_h, dstX, dstY, dst_w, dst_h);*/ | ||||
|  | ||||
|    if (dst && !dst->tex) { | ||||
| 	xorg_exa_set_shared_usage(pPixmap); | ||||
| 	pScrn->pScreen->ModifyPixmapHeader(pPixmap, 0, 0, 0, 0, 0, NULL); | ||||
| @@ -527,10 +533,10 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id, | ||||
|       int box_y2 = pbox->y2; | ||||
|       float diff_x = (float)src_w / (float)dst_w; | ||||
|       float diff_y = (float)src_h / (float)dst_h; | ||||
|       int offset_x = box_x1 - dstX + pPixmap->screen_x; | ||||
|       int offset_y = box_y1 - dstY + pPixmap->screen_y; | ||||
|       int offset_w; | ||||
|       int offset_h; | ||||
|       float offset_x = box_x1 - dstX + pPixmap->screen_x; | ||||
|       float offset_y = box_y1 - dstY + pPixmap->screen_y; | ||||
|       float offset_w; | ||||
|       float offset_h; | ||||
|  | ||||
|       x = box_x1; | ||||
|       y = box_y1; | ||||
| @@ -540,8 +546,9 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id, | ||||
|       offset_w = dst_w - w; | ||||
|       offset_h = dst_h - h; | ||||
|  | ||||
|       draw_yuv(pPriv, src_x + offset_x*diff_x, src_y + offset_y*diff_y, | ||||
|                src_w - offset_w*diff_x, src_h - offset_h*diff_x, | ||||
|       draw_yuv(pPriv, | ||||
|                (float) src_x + offset_x*diff_x, (float) src_y + offset_y*diff_y, | ||||
|                (float) src_w - offset_w*diff_x, (float) src_h - offset_h*diff_y, | ||||
|                x, y, w, h); | ||||
|  | ||||
|       pbox++; | ||||
|   | ||||
| @@ -103,6 +103,9 @@ struct vmw_svga_winsys_context | ||||
|     * referred. | ||||
|     */ | ||||
|    boolean preemptive_flush; | ||||
|  | ||||
|    boolean throttle_set; | ||||
|    uint32_t throttle_us; | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -122,6 +125,7 @@ vmw_swc_flush(struct svga_winsys_context *swc, | ||||
|    struct pipe_fence_handle *fence = NULL; | ||||
|    unsigned i; | ||||
|    enum pipe_error ret; | ||||
|    uint32_t throttle_us; | ||||
|  | ||||
|    ret = pb_validate_validate(vswc->validate); | ||||
|    assert(ret == PIPE_OK); | ||||
| @@ -140,8 +144,13 @@ vmw_swc_flush(struct svga_winsys_context *swc, | ||||
|          *reloc->where = ptr; | ||||
|       } | ||||
|  | ||||
|       throttle_us = vswc->throttle_set ? | ||||
| 	 vswc->throttle_us : vswc->vws->default_throttle_us; | ||||
|  | ||||
|       if (vswc->command.used) | ||||
|          vmw_ioctl_command(vswc->vws, | ||||
| 			   vswc->base.cid, | ||||
| 			   throttle_us, | ||||
|                            vswc->command.buffer, | ||||
|                            vswc->command.used, | ||||
|                            &vswc->last_fence); | ||||
| @@ -385,3 +394,14 @@ vmw_svga_context_create(struct pipe_screen *screen) | ||||
| { | ||||
|    return svga_context_create(screen); | ||||
| } | ||||
|  | ||||
| void | ||||
| vmw_svga_context_set_throttling(struct pipe_context *pipe, | ||||
| 				uint32_t throttle_us) | ||||
| { | ||||
|    struct svga_winsys_context *swc = svga_winsys_context(pipe); | ||||
|    struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); | ||||
|  | ||||
|    vswc->throttle_us = throttle_us; | ||||
|    vswc->throttle_set = TRUE; | ||||
| } | ||||
|   | ||||
| @@ -55,5 +55,8 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws); | ||||
| struct pipe_context * | ||||
| vmw_svga_context_create(struct pipe_screen *screen); | ||||
|  | ||||
| void | ||||
| vmw_svga_context_set_throttling(struct pipe_context *pipe, | ||||
| 				uint32_t throttle_us); | ||||
|  | ||||
| #endif /* VMW_CONTEXT_H_ */ | ||||
|   | ||||
| @@ -37,13 +37,16 @@ | ||||
|  * module. | ||||
|  */ | ||||
| struct vmw_winsys_screen * | ||||
| vmw_winsys_create( int fd ) | ||||
| vmw_winsys_create( int fd, boolean use_old_scanout_flag ) | ||||
| { | ||||
|    struct vmw_winsys_screen *vws = CALLOC_STRUCT(vmw_winsys_screen); | ||||
|    if (!vws) | ||||
|       goto out_no_vws; | ||||
|  | ||||
|    vws->ioctl.drm_fd = fd; | ||||
|    vws->use_old_scanout_flag = use_old_scanout_flag; | ||||
|    debug_printf("%s: use_old_scanout_flag == %s\n", __FUNCTION__, | ||||
| 		use_old_scanout_flag ? "true" : "false"); | ||||
|  | ||||
|    if (!vmw_ioctl_init(vws)) | ||||
|       goto out_no_ioctl; | ||||
| @@ -72,3 +75,13 @@ vmw_winsys_destroy(struct vmw_winsys_screen *vws) | ||||
|    vmw_ioctl_cleanup(vws); | ||||
|    FREE(vws); | ||||
| } | ||||
|  | ||||
| void | ||||
| vmw_winsys_screen_set_throttling(struct pipe_screen *screen, | ||||
| 				 uint32_t throttle_us) | ||||
| { | ||||
|    struct vmw_winsys_screen  *vws = | ||||
|       vmw_winsys_screen(svga_winsys_screen(screen)); | ||||
|  | ||||
|    vws->default_throttle_us = throttle_us; | ||||
| } | ||||
|   | ||||
| @@ -52,6 +52,9 @@ struct vmw_winsys_screen | ||||
| { | ||||
|    struct svga_winsys_screen base; | ||||
|  | ||||
|    boolean use_old_scanout_flag; | ||||
|    uint32_t default_throttle_us; | ||||
|  | ||||
|    struct { | ||||
|       volatile uint32_t *fifo_map; | ||||
|       uint64_t last_fence; | ||||
| @@ -94,9 +97,11 @@ vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, | ||||
|  | ||||
| void | ||||
| vmw_ioctl_command(struct vmw_winsys_screen *vws, | ||||
|                        void *commands, | ||||
|                        uint32_t size, | ||||
|                        uint32_t *fence); | ||||
| 		  int32_t cid, | ||||
| 		  uint32_t throttle_us, | ||||
| 		  void *commands, | ||||
| 		  uint32_t size, | ||||
| 		  uint32_t *fence); | ||||
|  | ||||
| struct vmw_region * | ||||
| vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size); | ||||
| @@ -131,8 +136,9 @@ boolean vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws); | ||||
| void vmw_ioctl_cleanup(struct vmw_winsys_screen *vws); | ||||
| void vmw_pools_cleanup(struct vmw_winsys_screen *vws); | ||||
|  | ||||
| struct vmw_winsys_screen *vmw_winsys_create(int fd); | ||||
| struct vmw_winsys_screen *vmw_winsys_create(int fd, boolean use_old_scanout_flag); | ||||
| void vmw_winsys_destroy(struct vmw_winsys_screen *sws); | ||||
|  | ||||
| void vmw_winsys_screen_set_throttling(struct pipe_screen *screen, | ||||
| 				      uint32_t throttle_us); | ||||
|  | ||||
| #endif /* VMW_SCREEN_H_ */ | ||||
|   | ||||
| @@ -48,8 +48,9 @@ static struct dri1_api_version ddx_required = { 0, 1, 0 }; | ||||
| static struct dri1_api_version ddx_compat = { 0, 0, 0 }; | ||||
| static struct dri1_api_version dri_required = { 4, 0, 0 }; | ||||
| static struct dri1_api_version dri_compat = { 4, 0, 0 }; | ||||
| static struct dri1_api_version drm_required = { 0, 1, 0 }; | ||||
| static struct dri1_api_version drm_compat = { 0, 0, 0 }; | ||||
| static struct dri1_api_version drm_required = { 1, 0, 0 }; | ||||
| static struct dri1_api_version drm_compat = { 1, 0, 0 }; | ||||
| static struct dri1_api_version drm_scanout = { 0, 9, 0 }; | ||||
|  | ||||
| static boolean | ||||
| vmw_dri1_check_version(const struct dri1_api_version *cur, | ||||
| @@ -84,6 +85,7 @@ vmw_drm_create_screen(struct drm_api *drm_api, | ||||
|    struct vmw_winsys_screen *vws; | ||||
|    struct pipe_screen *screen; | ||||
|    struct dri1_create_screen_arg *dri1; | ||||
|    boolean use_old_scanout_flag = FALSE; | ||||
|  | ||||
|    if (!arg || arg->mode == DRM_CREATE_NORMAL) { | ||||
|       struct dri1_api_version drm_ver; | ||||
| @@ -95,11 +97,16 @@ vmw_drm_create_screen(struct drm_api *drm_api, | ||||
|  | ||||
|       drm_ver.major = ver->version_major; | ||||
|       drm_ver.minor = ver->version_minor; | ||||
|       drm_ver.patch_level = 0; /* ??? */ | ||||
|  | ||||
|       drmFreeVersion(ver); | ||||
|       if (!vmw_dri1_check_version(&drm_ver, &drm_required, | ||||
| 				  &drm_compat, "vmwgfx drm driver")) | ||||
| 	 return NULL; | ||||
|  | ||||
|       if (!vmw_dri1_check_version(&drm_ver, &drm_scanout, | ||||
| 				  &drm_compat, "use old scanout field (not a error)")) | ||||
|          use_old_scanout_flag = TRUE; | ||||
|    } | ||||
|  | ||||
|    if (arg != NULL) { | ||||
| @@ -117,6 +124,9 @@ vmw_drm_create_screen(struct drm_api *drm_api, | ||||
| 	 if (!vmw_dri1_check_version(&dri1->drm_version, &drm_required, | ||||
| 				     &drm_compat, "vmwgfx drm driver")) | ||||
| 	    return NULL; | ||||
| 	 if (!vmw_dri1_check_version(&dri1->drm_version, &drm_scanout, | ||||
| 				     &drm_compat, "use old scanout field (not a error)")) | ||||
| 	    use_old_scanout_flag = TRUE; | ||||
| 	 dri1->api = &dri1_api_hooks; | ||||
| 	 break; | ||||
|       default: | ||||
| @@ -124,7 +134,7 @@ vmw_drm_create_screen(struct drm_api *drm_api, | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    vws = vmw_winsys_create( fd ); | ||||
|    vws = vmw_winsys_create( fd, use_old_scanout_flag ); | ||||
|    if (!vws) | ||||
|       goto out_no_vws; | ||||
|  | ||||
| @@ -228,7 +238,7 @@ vmw_dri1_present_locked(struct pipe_context *locked_pipe, | ||||
| 		   cmd.rect.y, | ||||
| 		   cmd.rect.w, cmd.rect.h, cmd.rect.srcx, cmd.rect.srcy); | ||||
|  | ||||
|       vmw_ioctl_command(vws, &cmd, sizeof cmd.header + cmd.header.size, | ||||
|       vmw_ioctl_command(vws, -1, 0, &cmd, sizeof cmd.header + cmd.header.size, | ||||
|                         &fence_seq); | ||||
|       visible = TRUE; | ||||
|    } | ||||
|   | ||||
| @@ -57,6 +57,12 @@ struct vmw_region | ||||
|    uint32_t size; | ||||
| }; | ||||
|  | ||||
| /* XXX: This isn't a real hardware flag, but just a hack for kernel to | ||||
|  * know about primary surfaces. In newer versions of the kernel | ||||
|  * interface the driver uses a special field. | ||||
|  */ | ||||
| #define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9) | ||||
|  | ||||
| static void | ||||
| vmw_check_last_cmd(struct vmw_winsys_screen *vws) | ||||
| { | ||||
| @@ -169,7 +175,17 @@ vmw_ioctl_surface_create(struct vmw_winsys_screen *vws, | ||||
|    vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format); | ||||
|  | ||||
|    memset(&s_arg, 0, sizeof(s_arg)); | ||||
|    req->flags = (uint32_t) flags; | ||||
|    if (vws->use_old_scanout_flag && | ||||
|        (flags & SVGA3D_SURFACE_HINT_SCANOUT)) { | ||||
|       req->flags = (uint32_t) flags; | ||||
|       req->scanout = false; | ||||
|    } else if (flags & SVGA3D_SURFACE_HINT_SCANOUT) { | ||||
|       req->flags = (uint32_t) (flags & ~SVGA3D_SURFACE_HINT_SCANOUT); | ||||
|       req->scanout = true; | ||||
|    } else { | ||||
|       req->flags = (uint32_t) flags; | ||||
|       req->scanout = false; | ||||
|    } | ||||
|    req->format = (uint32_t) format; | ||||
|    req->shareable = 1; | ||||
|  | ||||
| @@ -225,8 +241,9 @@ vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, uint32 sid) | ||||
| } | ||||
|  | ||||
| void | ||||
| vmw_ioctl_command(struct vmw_winsys_screen *vws, void *commands, uint32_t size, | ||||
| 		       uint32_t * pfence) | ||||
| vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid, | ||||
| 		  uint32_t throttle_us, void *commands, uint32_t size, | ||||
| 		  uint32_t *pfence) | ||||
| { | ||||
|    struct drm_vmw_execbuf_arg arg; | ||||
|    struct drm_vmw_fence_rep rep; | ||||
| @@ -259,6 +276,7 @@ vmw_ioctl_command(struct vmw_winsys_screen *vws, void *commands, uint32_t size, | ||||
|    arg.fence_rep = (unsigned long)&rep; | ||||
|    arg.commands = (unsigned long)commands; | ||||
|    arg.command_size = size; | ||||
|    arg.throttle_us = throttle_us; | ||||
|  | ||||
|    do { | ||||
|        ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); | ||||
|   | ||||
| @@ -68,7 +68,8 @@ | ||||
| #define DRM_VMW_PARAM_NUM_FREE_STREAMS 1 | ||||
| #define DRM_VMW_PARAM_3D               2 | ||||
| #define DRM_VMW_PARAM_FIFO_OFFSET      3 | ||||
|  | ||||
| #define DRM_VMW_PARAM_HW_CAPS          4 | ||||
| #define DRM_VMW_PARAM_FIFO_CAPS        5 | ||||
|  | ||||
| /** | ||||
|  * struct drm_vmw_getparam_arg | ||||
| @@ -85,49 +86,6 @@ struct drm_vmw_getparam_arg { | ||||
| 	uint32_t pad64; | ||||
| }; | ||||
|  | ||||
| /*************************************************************************/ | ||||
| /** | ||||
|  * DRM_VMW_EXTENSION - Query device extensions. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * struct drm_vmw_extension_rep | ||||
|  * | ||||
|  * @exists: The queried extension exists. | ||||
|  * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension. | ||||
|  * @driver_sarea_offset: Offset to any space in the DRI SAREA | ||||
|  * used by the extension. | ||||
|  * @major: Major version number of the extension. | ||||
|  * @minor: Minor version number of the extension. | ||||
|  * @pl: Patch level version number of the extension. | ||||
|  * | ||||
|  * Output argument to the DRM_VMW_EXTENSION Ioctl. | ||||
|  */ | ||||
|  | ||||
| struct drm_vmw_extension_rep { | ||||
| 	int32_t exists; | ||||
| 	uint32_t driver_ioctl_offset; | ||||
| 	uint32_t driver_sarea_offset; | ||||
| 	uint32_t major; | ||||
| 	uint32_t minor; | ||||
| 	uint32_t pl; | ||||
| 	uint32_t pad64; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * union drm_vmw_extension_arg | ||||
|  * | ||||
|  * @extension - Ascii name of the extension to be queried. //In | ||||
|  * @rep - Reply as defined above. //Out | ||||
|  * | ||||
|  * Argument to the DRM_VMW_EXTENSION Ioctl. | ||||
|  */ | ||||
|  | ||||
| union drm_vmw_extension_arg { | ||||
| 	char extension[DRM_VMW_EXT_NAME_LEN]; | ||||
| 	struct drm_vmw_extension_rep rep; | ||||
| }; | ||||
|  | ||||
| /*************************************************************************/ | ||||
| /** | ||||
|  * DRM_VMW_CREATE_CONTEXT - Create a host context. | ||||
| @@ -181,6 +139,8 @@ struct drm_vmw_context_arg { | ||||
|  * The size of the array should equal the total number of mipmap levels. | ||||
|  * @shareable: Boolean whether other clients (as identified by file descriptors) | ||||
|  * may reference this surface. | ||||
|  * @scanout: Boolean whether the surface is intended to be used as a | ||||
|  * scanout. | ||||
|  * | ||||
|  * Input data to the DRM_VMW_CREATE_SURFACE Ioctl. | ||||
|  * Output data from the DRM_VMW_REF_SURFACE Ioctl. | ||||
| @@ -192,7 +152,7 @@ struct drm_vmw_surface_create_req { | ||||
| 	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; | ||||
| 	uint64_t size_addr; | ||||
| 	int32_t shareable; | ||||
| 	uint32_t pad64; | ||||
| 	int32_t scanout; | ||||
| }; | ||||
|  | ||||
| /** | ||||
| @@ -295,17 +255,28 @@ union drm_vmw_surface_reference_arg { | ||||
|  * | ||||
|  * @commands: User-space address of a command buffer cast to an uint64_t. | ||||
|  * @command-size: Size in bytes of the command buffer. | ||||
|  * @throttle-us: Sleep until software is less than @throttle_us | ||||
|  * microseconds ahead of hardware. The driver may round this value | ||||
|  * to the nearest kernel tick. | ||||
|  * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an | ||||
|  * uint64_t. | ||||
|  * @version: Allows expanding the execbuf ioctl parameters without breaking | ||||
|  * backwards compatibility, since user-space will always tell the kernel | ||||
|  * which version it uses. | ||||
|  * @flags: Execbuf flags. None currently. | ||||
|  * | ||||
|  * Argument to the DRM_VMW_EXECBUF Ioctl. | ||||
|  */ | ||||
|  | ||||
| #define DRM_VMW_EXECBUF_VERSION 0 | ||||
|  | ||||
| struct drm_vmw_execbuf_arg { | ||||
| 	uint64_t commands; | ||||
| 	uint32_t command_size; | ||||
| 	uint32_t pad64; | ||||
| 	uint32_t throttle_us; | ||||
| 	uint64_t fence_rep; | ||||
| 	 uint32_t version; | ||||
| 	 uint32_t flags; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -40,8 +40,11 @@ | ||||
|  | ||||
| struct vmw_dma_buffer; | ||||
|  | ||||
| struct vmw_driver | ||||
| struct vmw_customizer | ||||
| { | ||||
|     CustomizerRec base; | ||||
|     ScrnInfoPtr pScrn; | ||||
|  | ||||
|     int fd; | ||||
|  | ||||
|     void *cursor_priv; | ||||
| @@ -50,11 +53,10 @@ struct vmw_driver | ||||
|     void *video_priv; | ||||
| }; | ||||
|  | ||||
| static INLINE struct vmw_driver * | ||||
| vmw_driver(ScrnInfoPtr pScrn) | ||||
| static INLINE struct vmw_customizer * | ||||
| vmw_customizer(CustomizerPtr cust) | ||||
| { | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     return ms ? (struct vmw_driver *)ms->winsys_priv : NULL; | ||||
|     return cust ? (struct vmw_customizer *) cust : NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -62,40 +64,40 @@ vmw_driver(ScrnInfoPtr pScrn) | ||||
|  * vmw_video.c | ||||
|  */ | ||||
|  | ||||
| Bool vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw); | ||||
| Bool vmw_video_init(struct vmw_customizer *vmw); | ||||
|  | ||||
| Bool vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw); | ||||
| Bool vmw_video_close(struct vmw_customizer *vmw); | ||||
|  | ||||
| void vmw_video_stop_all(ScrnInfoPtr pScrn, struct vmw_driver *vmw); | ||||
| void vmw_video_stop_all(struct vmw_customizer *vmw); | ||||
|  | ||||
|  | ||||
| /*********************************************************************** | ||||
|  * vmw_ioctl.c | ||||
|  */ | ||||
|  | ||||
| int vmw_ioctl_cursor_bypass(struct vmw_driver *vmw, int xhot, int yhot); | ||||
| int vmw_ioctl_cursor_bypass(struct vmw_customizer *vmw, int xhot, int yhot); | ||||
|  | ||||
| struct vmw_dma_buffer * vmw_ioctl_buffer_create(struct vmw_driver *vmw, | ||||
| struct vmw_dma_buffer * vmw_ioctl_buffer_create(struct vmw_customizer *vmw, | ||||
| 						uint32_t size, | ||||
| 						unsigned *handle); | ||||
|  | ||||
| void * vmw_ioctl_buffer_map(struct vmw_driver *vmw, | ||||
| void * vmw_ioctl_buffer_map(struct vmw_customizer *vmw, | ||||
| 			    struct vmw_dma_buffer *buf); | ||||
|  | ||||
| void vmw_ioctl_buffer_unmap(struct vmw_driver *vmw, | ||||
| void vmw_ioctl_buffer_unmap(struct vmw_customizer *vmw, | ||||
| 			    struct vmw_dma_buffer *buf); | ||||
|  | ||||
| void vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, | ||||
| void vmw_ioctl_buffer_destroy(struct vmw_customizer *vmw, | ||||
| 			      struct vmw_dma_buffer *buf); | ||||
|  | ||||
| int vmw_ioctl_supports_streams(struct vmw_driver *vmw); | ||||
| int vmw_ioctl_supports_streams(struct vmw_customizer *vmw); | ||||
|  | ||||
| int vmw_ioctl_num_streams(struct vmw_driver *vmw, | ||||
| int vmw_ioctl_num_streams(struct vmw_customizer *vmw, | ||||
| 			  uint32_t *ntot, uint32_t *nfree); | ||||
|  | ||||
| int vmw_ioctl_unref_stream(struct vmw_driver *vmw, uint32_t stream_id); | ||||
| int vmw_ioctl_unref_stream(struct vmw_customizer *vmw, uint32_t stream_id); | ||||
|  | ||||
| int vmw_ioctl_claim_stream(struct vmw_driver *vmw, uint32_t *out); | ||||
| int vmw_ioctl_claim_stream(struct vmw_customizer *vmw, uint32_t *out); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -57,7 +57,7 @@ struct vmw_dma_buffer | ||||
| }; | ||||
|  | ||||
| static int | ||||
| vmw_ioctl_get_param(struct vmw_driver *vmw, uint32_t param, uint64_t *out) | ||||
| vmw_ioctl_get_param(struct vmw_customizer *vmw, uint32_t param, uint64_t *out) | ||||
| { | ||||
|     struct drm_vmw_getparam_arg gp_arg; | ||||
|     int ret; | ||||
| @@ -75,7 +75,7 @@ vmw_ioctl_get_param(struct vmw_driver *vmw, uint32_t param, uint64_t *out) | ||||
| } | ||||
|  | ||||
| int | ||||
| vmw_ioctl_supports_streams(struct vmw_driver *vmw) | ||||
| vmw_ioctl_supports_streams(struct vmw_customizer *vmw) | ||||
| { | ||||
|     uint64_t value; | ||||
|     int ret; | ||||
| @@ -88,7 +88,7 @@ vmw_ioctl_supports_streams(struct vmw_driver *vmw) | ||||
| } | ||||
|  | ||||
| int | ||||
| vmw_ioctl_num_streams(struct vmw_driver *vmw, | ||||
| vmw_ioctl_num_streams(struct vmw_customizer *vmw, | ||||
| 		      uint32_t *ntot, uint32_t *nfree) | ||||
| { | ||||
|     uint64_t v1, v2; | ||||
| @@ -109,7 +109,7 @@ vmw_ioctl_num_streams(struct vmw_driver *vmw, | ||||
| } | ||||
|  | ||||
| int | ||||
| vmw_ioctl_claim_stream(struct vmw_driver *vmw, uint32_t *out) | ||||
| vmw_ioctl_claim_stream(struct vmw_customizer *vmw, uint32_t *out) | ||||
| { | ||||
|     struct drm_vmw_stream_arg s_arg; | ||||
|     int ret; | ||||
| @@ -125,7 +125,7 @@ vmw_ioctl_claim_stream(struct vmw_driver *vmw, uint32_t *out) | ||||
| } | ||||
|  | ||||
| int | ||||
| vmw_ioctl_unref_stream(struct vmw_driver *vmw, uint32_t stream_id) | ||||
| vmw_ioctl_unref_stream(struct vmw_customizer *vmw, uint32_t stream_id) | ||||
| { | ||||
|     struct drm_vmw_stream_arg s_arg; | ||||
|     int ret; | ||||
| @@ -140,7 +140,7 @@ vmw_ioctl_unref_stream(struct vmw_driver *vmw, uint32_t stream_id) | ||||
| } | ||||
|  | ||||
| int | ||||
| vmw_ioctl_cursor_bypass(struct vmw_driver *vmw, int xhot, int yhot) | ||||
| vmw_ioctl_cursor_bypass(struct vmw_customizer *vmw, int xhot, int yhot) | ||||
| { | ||||
|     struct drm_vmw_cursor_bypass_arg arg; | ||||
|     int ret; | ||||
| @@ -157,7 +157,7 @@ vmw_ioctl_cursor_bypass(struct vmw_driver *vmw, int xhot, int yhot) | ||||
| } | ||||
|  | ||||
| struct vmw_dma_buffer * | ||||
| vmw_ioctl_buffer_create(struct vmw_driver *vmw, uint32_t size, unsigned *handle) | ||||
| vmw_ioctl_buffer_create(struct vmw_customizer *vmw, uint32_t size, unsigned *handle) | ||||
| { | ||||
|     struct vmw_dma_buffer *buf; | ||||
|     union drm_vmw_alloc_dmabuf_arg arg; | ||||
| @@ -198,7 +198,7 @@ err: | ||||
| } | ||||
|  | ||||
| void | ||||
| vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, struct vmw_dma_buffer *buf)  | ||||
| vmw_ioctl_buffer_destroy(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf) | ||||
| {  | ||||
|     struct drm_vmw_unref_dmabuf_arg arg;  | ||||
|  | ||||
| @@ -215,7 +215,7 @@ vmw_ioctl_buffer_destroy(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) | ||||
| }  | ||||
|  | ||||
| void * | ||||
| vmw_ioctl_buffer_map(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) | ||||
| vmw_ioctl_buffer_map(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf) | ||||
| { | ||||
|     void *map; | ||||
|  | ||||
| @@ -236,7 +236,7 @@ vmw_ioctl_buffer_map(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) | ||||
| } | ||||
|  | ||||
| void | ||||
| vmw_ioctl_buffer_unmap(struct vmw_driver *vmw, struct vmw_dma_buffer *buf) | ||||
| vmw_ioctl_buffer_unmap(struct vmw_customizer *vmw, struct vmw_dma_buffer *buf) | ||||
| { | ||||
|     --buf->map_count; | ||||
| } | ||||
|   | ||||
| @@ -32,16 +32,22 @@ | ||||
|  | ||||
| #include "vmw_hook.h" | ||||
| #include "vmw_driver.h" | ||||
| #include <pipe/p_context.h> | ||||
|  | ||||
| #include "cursorstr.h" | ||||
|  | ||||
| void vmw_winsys_screen_set_throttling(struct pipe_screen *screen, | ||||
| 				      uint32_t throttle_us); | ||||
|  | ||||
|  | ||||
| /* modified version of crtc functions */ | ||||
| xf86CrtcFuncsRec vmw_screen_crtc_funcs; | ||||
|  | ||||
| static void | ||||
| vmw_screen_cursor_load_argb(xf86CrtcPtr crtc, CARD32 *image) | ||||
| { | ||||
|     struct vmw_driver *vmw = modesettingPTR(crtc->scrn)->winsys_priv; | ||||
|     struct vmw_customizer *vmw = | ||||
| 	vmw_customizer(xorg_customizer(crtc->scrn)); | ||||
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); | ||||
|     xf86CrtcFuncsPtr funcs = vmw->cursor_priv; | ||||
|     CursorPtr c = config->cursor; | ||||
| @@ -53,8 +59,9 @@ vmw_screen_cursor_load_argb(xf86CrtcPtr crtc, CARD32 *image) | ||||
| } | ||||
|  | ||||
| static void | ||||
| vmw_screen_cursor_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| vmw_screen_cursor_init(struct vmw_customizer *vmw) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = vmw->pScrn; | ||||
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); | ||||
|     int i; | ||||
|  | ||||
| @@ -70,9 +77,9 @@ vmw_screen_cursor_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| } | ||||
|  | ||||
| static void | ||||
| vmw_screen_cursor_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| vmw_screen_cursor_close(struct vmw_customizer *vmw) | ||||
| { | ||||
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); | ||||
|     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(vmw->pScrn); | ||||
|     int i; | ||||
|  | ||||
|     vmw_ioctl_cursor_bypass(vmw, 0, 0); | ||||
| @@ -81,51 +88,81 @@ vmw_screen_cursor_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| 	config->crtc[i]->funcs = vmw->cursor_priv; | ||||
| } | ||||
|  | ||||
| static Bool | ||||
| vmw_screen_init(ScrnInfoPtr pScrn) | ||||
| static void | ||||
| vmw_context_throttle(CustomizerPtr cust, | ||||
| 		     struct pipe_context *pipe, | ||||
| 		     enum xorg_throttling_reason reason) | ||||
| { | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     struct vmw_driver *vmw; | ||||
|     switch (reason) { | ||||
|     case THROTTLE_RENDER: | ||||
| 	vmw_winsys_screen_set_throttling(pipe->screen, 20000); | ||||
| 	break; | ||||
|     default: | ||||
|       vmw_winsys_screen_set_throttling(pipe->screen, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     vmw = xnfcalloc(sizeof(*vmw), 1); | ||||
|     if (!vmw) | ||||
| 	return FALSE; | ||||
| static void | ||||
| vmw_context_no_throttle(CustomizerPtr cust, | ||||
| 		     struct pipe_context *pipe, | ||||
| 		     enum xorg_throttling_reason reason) | ||||
| { | ||||
|     vmw_winsys_screen_set_throttling(pipe->screen, 0); | ||||
| } | ||||
|  | ||||
| static Bool | ||||
| vmw_screen_init(CustomizerPtr cust, int fd) | ||||
| { | ||||
|     struct vmw_customizer *vmw = vmw_customizer(cust); | ||||
|     drmVersionPtr ver; | ||||
|  | ||||
|     vmw->fd = fd; | ||||
|     ver = drmGetVersion(fd); | ||||
|     if (ver == NULL || | ||||
| 	(ver->version_major == 1 && ver->version_minor < 1)) { | ||||
| 	cust->swap_throttling = TRUE; | ||||
| 	cust->dirty_throttling = TRUE; | ||||
| 	cust->winsys_context_throttle = vmw_context_no_throttle; | ||||
|     } else { | ||||
| 	cust->swap_throttling = TRUE; | ||||
| 	cust->dirty_throttling = FALSE; | ||||
| 	cust->winsys_context_throttle = vmw_context_throttle; | ||||
| 	debug_printf("%s: Enabling kernel throttling.\n", __func__); | ||||
|     } | ||||
|  | ||||
|     if (ver) | ||||
| 	drmFreeVersion(ver); | ||||
|  | ||||
|     vmw_screen_cursor_init(vmw); | ||||
|  | ||||
|     vmw->fd = ms->fd; | ||||
|     ms->winsys_priv = vmw; | ||||
|  | ||||
|     vmw_screen_cursor_init(pScrn, vmw); | ||||
|  | ||||
|     /* if gallium is used then we don't need to do anything more. */ | ||||
|     if (ms->screen) | ||||
|     if (xorg_has_gallium(vmw->pScrn)) | ||||
| 	return TRUE; | ||||
|  | ||||
|     vmw_video_init(pScrn, vmw); | ||||
|     vmw_video_init(vmw); | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
|  | ||||
| static Bool | ||||
| vmw_screen_close(ScrnInfoPtr pScrn) | ||||
| vmw_screen_close(CustomizerPtr cust) | ||||
| { | ||||
|     modesettingPtr ms = modesettingPTR(pScrn); | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(cust); | ||||
|  | ||||
|     if (!vmw) | ||||
| 	return TRUE; | ||||
|  | ||||
|     vmw_screen_cursor_close(pScrn, vmw); | ||||
|     vmw_screen_cursor_close(vmw); | ||||
|  | ||||
|     vmw_video_close(pScrn, vmw); | ||||
|  | ||||
|     ms->winsys_priv = NULL; | ||||
|     xfree(vmw); | ||||
|     vmw_video_close(vmw); | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
|  | ||||
| static Bool | ||||
| vmw_screen_enter_vt(ScrnInfoPtr pScrn) | ||||
| vmw_screen_enter_vt(CustomizerPtr cust) | ||||
| { | ||||
|     debug_printf("%s: enter\n", __func__); | ||||
|  | ||||
| @@ -133,13 +170,13 @@ vmw_screen_enter_vt(ScrnInfoPtr pScrn) | ||||
| } | ||||
|  | ||||
| static Bool | ||||
| vmw_screen_leave_vt(ScrnInfoPtr pScrn) | ||||
| vmw_screen_leave_vt(CustomizerPtr cust) | ||||
| { | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(cust); | ||||
|  | ||||
|     debug_printf("%s: enter\n", __func__); | ||||
|  | ||||
|     vmw_video_stop_all(pScrn, vmw); | ||||
|     vmw_video_stop_all(vmw); | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
| @@ -153,18 +190,27 @@ static Bool (*vmw_screen_pre_init_saved)(ScrnInfoPtr pScrn, int flags) = NULL; | ||||
| static Bool | ||||
| vmw_screen_pre_init(ScrnInfoPtr pScrn, int flags) | ||||
| { | ||||
|     modesettingPtr ms; | ||||
|     struct vmw_customizer *vmw; | ||||
|     CustomizerPtr cust; | ||||
|  | ||||
|     vmw = xnfcalloc(1, sizeof(*vmw)); | ||||
|     if (!vmw) | ||||
| 	return FALSE; | ||||
|  | ||||
|     cust = &vmw->base; | ||||
|  | ||||
|     cust->winsys_screen_init = vmw_screen_init; | ||||
|     cust->winsys_screen_close = vmw_screen_close; | ||||
|     cust->winsys_enter_vt = vmw_screen_enter_vt; | ||||
|     cust->winsys_leave_vt = vmw_screen_leave_vt; | ||||
|     vmw->pScrn = pScrn; | ||||
|  | ||||
|     pScrn->driverPrivate = cust; | ||||
|  | ||||
|     pScrn->PreInit = vmw_screen_pre_init_saved; | ||||
|     if (!pScrn->PreInit(pScrn, flags)) | ||||
| 	return FALSE; | ||||
|  | ||||
|     ms = modesettingPTR(pScrn); | ||||
|     ms->winsys_screen_init = vmw_screen_init; | ||||
|     ms->winsys_screen_close = vmw_screen_close; | ||||
|     ms->winsys_enter_vt = vmw_screen_enter_vt; | ||||
|     ms->winsys_leave_vt = vmw_screen_leave_vt; | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -226,7 +226,7 @@ static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, | ||||
| /* | ||||
|  * Local functions. | ||||
|  */ | ||||
| static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw); | ||||
| static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw); | ||||
|  | ||||
| static int vmw_video_port_init(ScrnInfoPtr pScrn, | ||||
|                                struct vmw_video_port *port, | ||||
| @@ -243,9 +243,9 @@ static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, | ||||
|                                short height, RegionPtr clipBoxes); | ||||
| static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port); | ||||
|  | ||||
| static int vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, | ||||
| static int vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size, | ||||
|                                   struct vmw_video_buffer *out); | ||||
| static int vmw_video_buffer_free(struct vmw_driver *vmw, | ||||
| static int vmw_video_buffer_free(struct vmw_customizer *vmw, | ||||
|                                  struct vmw_video_buffer *out); | ||||
|  | ||||
|  | ||||
| @@ -267,8 +267,9 @@ static int vmw_video_buffer_free(struct vmw_driver *vmw, | ||||
|  */ | ||||
|  | ||||
| Bool | ||||
| vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| vmw_video_init(struct vmw_customizer *vmw) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = vmw->pScrn; | ||||
|     ScreenPtr pScreen = pScrn->pScreen; | ||||
|     XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; | ||||
|     XF86VideoAdaptorPtr newAdaptor = NULL; | ||||
| @@ -345,8 +346,9 @@ vmw_video_init(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
|  */ | ||||
|  | ||||
| Bool | ||||
| vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| vmw_video_close(struct vmw_customizer *vmw) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = vmw->pScrn; | ||||
|     struct vmw_video_private *video; | ||||
|     int i; | ||||
|  | ||||
| @@ -387,8 +389,9 @@ vmw_video_close(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
|  *----------------------------------------------------------------------------- | ||||
|  */ | ||||
|  | ||||
| void vmw_video_stop_all(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| void vmw_video_stop_all(struct vmw_customizer *vmw) | ||||
| { | ||||
|     ScrnInfoPtr pScrn = vmw->pScrn; | ||||
|     struct vmw_video_private *video = vmw->video_priv; | ||||
|     int i; | ||||
|  | ||||
| @@ -421,7 +424,7 @@ void vmw_video_stop_all(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
|  */ | ||||
|  | ||||
| static XF86VideoAdaptorPtr | ||||
| vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_driver *vmw) | ||||
| vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw) | ||||
| { | ||||
|     XF86VideoAdaptorPtr adaptor; | ||||
|     struct vmw_video_private *video; | ||||
| @@ -515,7 +518,7 @@ vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port, | ||||
|                     unsigned char *buf, short width, | ||||
|                     short height, RegionPtr clipBoxes) | ||||
| { | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); | ||||
|     unsigned short w, h; | ||||
|     int i, ret; | ||||
|  | ||||
| @@ -583,7 +586,7 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, | ||||
|                     unsigned char *buf, short width, | ||||
|                     short height, RegionPtr clipBoxes) | ||||
| { | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); | ||||
|     struct drm_vmw_control_stream_arg arg; | ||||
|     unsigned short w, h; | ||||
|     int size; | ||||
| @@ -675,7 +678,7 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, | ||||
| static void | ||||
| vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port) | ||||
| { | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); | ||||
|     uint32 id, colorKey, flags; | ||||
|     Bool isAutoPaintColorkey; | ||||
|     int i; | ||||
| @@ -721,7 +724,7 @@ vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port) | ||||
|  */ | ||||
|  | ||||
| static int | ||||
| vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, | ||||
| vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size, | ||||
|                        struct vmw_video_buffer *out) | ||||
| { | ||||
|     out->buf = vmw_ioctl_buffer_create(vmw, size, &out->handle); | ||||
| @@ -764,7 +767,7 @@ vmw_video_buffer_alloc(struct vmw_driver *vmw, int size, | ||||
|  */ | ||||
|  | ||||
| static int | ||||
| vmw_video_buffer_free(struct vmw_driver *vmw, | ||||
| vmw_video_buffer_free(struct vmw_customizer *vmw, | ||||
|                       struct vmw_video_buffer *out) | ||||
| { | ||||
|     if (out->size == 0) | ||||
| @@ -814,7 +817,7 @@ vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, | ||||
|                  Bool sync, RegionPtr clipBoxes, pointer data, | ||||
|                  DrawablePtr dst) | ||||
| { | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); | ||||
|     struct vmw_video_port *port = data; | ||||
|  | ||||
|     debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, | ||||
| @@ -852,7 +855,7 @@ vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, | ||||
| static void | ||||
| vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) | ||||
| { | ||||
|     struct vmw_driver *vmw = vmw_driver(pScrn); | ||||
|     struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); | ||||
|     struct vmw_video_port *port = data; | ||||
|     struct drm_vmw_control_stream_arg arg; | ||||
|     int ret; | ||||
|   | ||||
| @@ -33,12 +33,50 @@ | ||||
|  | ||||
| #include "vmw_hook.h" | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Defines and modinfo | ||||
|  */ | ||||
|  | ||||
| #define VMWGFX_DRIVER_NAME "vmwgfx" | ||||
|  | ||||
| #define VMW_STRING_INNER(s) #s | ||||
| #define VMW_STRING(str) VMW_STRING_INNER(str) | ||||
|  | ||||
| #define VMWGFX_VERSION_MAJOR 11 | ||||
| #define VMWGFX_VERSION_MINOR 0 | ||||
| #define VMWGFX_VERSION_PATCH 0 | ||||
| #define VMWGFX_VERSION_STRING_MAJOR VMW_STRING(VMWGFX_VERSION_MAJOR) | ||||
| #define VMWGFX_VERSION_STRING_MINOR VMW_STRING(VMWGFX_VERSION_MINOR) | ||||
| #define VMWGFX_VERSION_STRING_PATCH VMW_STRING(VMWGFX_VERSION_PATCH) | ||||
|  | ||||
| #define VMWGFX_DRIVER_VERSION \ | ||||
|    (VMWGFX_VERSION_MAJOR * 65536 + VMWGFX_VERSION_MINOR * 256 + VMWGFX_VERSION_PATCH) | ||||
| #define VMWGFX_DRIVER_VERSION_STRING \ | ||||
|     VMWGFX_VERSION_STRING_MAJOR "." VMWGFX_VERSION_STRING_MINOR \ | ||||
|     "." VMWGFX_VERSION_STRING_PATCH | ||||
|  | ||||
| /* | ||||
|  * Standard four digit version string expected by VMware Tools installer. | ||||
|  * As the driver's version is only  {major, minor, patchlevel}, simply append an | ||||
|  * extra zero for the fourth digit. | ||||
|  */ | ||||
| #ifdef __GNUC__ | ||||
| _X_EXPORT const char vmwgfx_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = | ||||
|     "version=" VMWGFX_DRIVER_VERSION_STRING ".0"; | ||||
| #endif | ||||
|  | ||||
| static void vmw_xorg_identify(int flags); | ||||
| _X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, | ||||
| 				  int entity_num, | ||||
| 				  struct pci_device *device, | ||||
| 				  intptr_t match_data); | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Tables | ||||
|  */ | ||||
|  | ||||
| static const struct pci_id_match vmw_xorg_device_match[] = { | ||||
|     {0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, | ||||
|     {0, 0, 0, 0, 0, 0, 0}, | ||||
| @@ -55,12 +93,12 @@ static PciChipsets vmw_xorg_pci_devices[] = { | ||||
| }; | ||||
|  | ||||
| static XF86ModuleVersionInfo vmw_xorg_version = { | ||||
|     "vmwgfx", | ||||
|     VMWGFX_DRIVER_NAME, | ||||
|     MODULEVENDORSTRING, | ||||
|     MODINFOSTRING1, | ||||
|     MODINFOSTRING2, | ||||
|     XORG_VERSION_CURRENT, | ||||
|     0, 1, 0, /* major, minor, patch */ | ||||
|     VMWGFX_VERSION_MAJOR, VMWGFX_VERSION_MINOR, VMWGFX_VERSION_PATCH, | ||||
|     ABI_CLASS_VIDEODRV, | ||||
|     ABI_VIDEODRV_VERSION, | ||||
|     MOD_CLASS_VIDEODRV, | ||||
| @@ -73,7 +111,7 @@ static XF86ModuleVersionInfo vmw_xorg_version = { | ||||
|  | ||||
| _X_EXPORT DriverRec vmwgfx = { | ||||
|     1, | ||||
|     "vmwgfx", | ||||
|     VMWGFX_DRIVER_NAME, | ||||
|     vmw_xorg_identify, | ||||
|     NULL, | ||||
|     xorg_tracker_available_options, | ||||
| @@ -92,6 +130,7 @@ _X_EXPORT XF86ModuleData vmwgfxModuleData = { | ||||
|     NULL | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Xorg driver functions | ||||
|  */ | ||||
|   | ||||
| @@ -267,13 +267,13 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) | ||||
| { | ||||
|    switch (fdwReason) { | ||||
|    case DLL_PROCESS_ATTACH: | ||||
|       if (!stw_init(&stw_winsys)) { | ||||
|          return FALSE; | ||||
|       } | ||||
|       return stw_init_thread(); | ||||
|       stw_init(&stw_winsys); | ||||
|       stw_init_thread(); | ||||
|       break; | ||||
|  | ||||
|    case DLL_THREAD_ATTACH: | ||||
|       return stw_init_thread(); | ||||
|       stw_init_thread(); | ||||
|       break; | ||||
|  | ||||
|    case DLL_THREAD_DETACH: | ||||
|       stw_cleanup_thread(); | ||||
|   | ||||
| @@ -317,13 +317,13 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) | ||||
| { | ||||
|    switch (fdwReason) { | ||||
|    case DLL_PROCESS_ATTACH: | ||||
|       if (!stw_init(&stw_winsys)) { | ||||
|          return FALSE; | ||||
|       } | ||||
|       return stw_init_thread(); | ||||
|       stw_init(&stw_winsys); | ||||
|       stw_init_thread(); | ||||
|       break; | ||||
|  | ||||
|    case DLL_THREAD_ATTACH: | ||||
|       return stw_init_thread(); | ||||
|       stw_init_thread(); | ||||
|       break; | ||||
|  | ||||
|    case DLL_THREAD_DETACH: | ||||
|       stw_cleanup_thread(); | ||||
|   | ||||
| @@ -437,8 +437,10 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, | ||||
|    psc->ext_list_first_time = GL_TRUE; | ||||
|  | ||||
|    if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), | ||||
|                     &driverName, &deviceName)) | ||||
|                     &driverName, &deviceName)) { | ||||
|       XFree(psp); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    psc->driver = driOpenDriver(driverName); | ||||
|    if (psc->driver == NULL) { | ||||
| @@ -467,17 +469,17 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, | ||||
|    psc->fd = open(deviceName, O_RDWR); | ||||
|    if (psc->fd < 0) { | ||||
|       ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); | ||||
|       return NULL; | ||||
|       goto handle_error; | ||||
|    } | ||||
|  | ||||
|    if (drmGetMagic(psc->fd, &magic)) { | ||||
|       ErrorMessageF("failed to get magic\n"); | ||||
|       return NULL; | ||||
|       goto handle_error; | ||||
|    } | ||||
|  | ||||
|    if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { | ||||
|       ErrorMessageF("failed to authenticate magic %d\n", magic); | ||||
|       return NULL; | ||||
|       goto handle_error; | ||||
|    } | ||||
|  | ||||
|    /* If the server does not support the protocol for | ||||
| @@ -491,7 +493,7 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, | ||||
|  | ||||
|    if (psc->__driScreen == NULL) { | ||||
|       ErrorMessageF("failed to create dri screen\n"); | ||||
|       return NULL; | ||||
|       goto handle_error; | ||||
|    } | ||||
|  | ||||
|    driBindExtensions(psc, 1); | ||||
| @@ -521,6 +523,7 @@ dri2CreateScreen(__GLXscreenConfigs * psc, int screen, | ||||
|  handle_error: | ||||
|    Xfree(driverName); | ||||
|    Xfree(deviceName); | ||||
|    XFree(psp); | ||||
|  | ||||
|    /* FIXME: clean up here */ | ||||
|  | ||||
|   | ||||
| @@ -385,7 +385,8 @@ CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig, | ||||
|    req->glxwindow = (GLXWindow) XAllocID(dpy); | ||||
|    req->numAttribs = (CARD32) i; | ||||
|  | ||||
|    memcpy(data, attrib_list, 8 * i); | ||||
|    if (attrib_list) | ||||
|       memcpy(data, attrib_list, 8 * i); | ||||
|  | ||||
|    UnlockDisplay(dpy); | ||||
|    SyncHandle(); | ||||
|   | ||||
| @@ -291,7 +291,8 @@ __glXInitVertexArrayState(__GLXcontext * gc) | ||||
|  | ||||
|    arrays->stack_index = 0; | ||||
|    arrays->stack = malloc(sizeof(struct array_stack_state) | ||||
|                           * arrays->num_arrays); | ||||
|                           * arrays->num_arrays | ||||
|                           * __GL_CLIENT_ATTRIB_STACK_DEPTH); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -60,14 +60,6 @@ driNewRenderbuffer(gl_format format, GLvoid *addr, | ||||
| { | ||||
|    driRenderbuffer *drb; | ||||
|  | ||||
|    assert(format == GL_RGBA || | ||||
|           format == GL_RGB5 || | ||||
|           format == GL_RGBA8 || | ||||
|           format == GL_DEPTH_COMPONENT16 || | ||||
|           format == GL_DEPTH_COMPONENT24 || | ||||
|           format == GL_DEPTH_COMPONENT32 || | ||||
|           format == GL_STENCIL_INDEX8_EXT); | ||||
|  | ||||
|    assert(cpp > 0); | ||||
|    assert(pitch > 0); | ||||
|  | ||||
|   | ||||
| @@ -254,7 +254,7 @@ void intel_flush_prim(struct intel_context *intel) | ||||
|       BEGIN_BATCH(5, LOOP_CLIPRECTS); | ||||
|       OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | | ||||
| 		I1_LOAD_S(0) | I1_LOAD_S(1) | 1); | ||||
|       assert((offset & !S0_VB_OFFSET_MASK) == 0); | ||||
|       assert((offset & ~S0_VB_OFFSET_MASK) == 0); | ||||
|       OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, offset); | ||||
|       OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | | ||||
| 		(intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); | ||||
| @@ -273,7 +273,7 @@ void intel_flush_prim(struct intel_context *intel) | ||||
|       OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | | ||||
| 		I1_LOAD_S(0) | I1_LOAD_S(2) | 1); | ||||
|       /* S0 */ | ||||
|       assert((offset & !S0_VB_OFFSET_MASK_830) == 0); | ||||
|       assert((offset & ~S0_VB_OFFSET_MASK_830) == 0); | ||||
|       OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, | ||||
| 		offset | (intel->vertex_size << S0_VB_PITCH_SHIFT_830) | | ||||
| 		S0_VB_ENABLE_830); | ||||
|   | ||||
| @@ -770,7 +770,13 @@ get_constant(struct brw_vs_compile *c, | ||||
|    if (c->current_const[argIndex].index != src->Index || relAddr) { | ||||
|       struct brw_reg addrReg = c->regs[PROGRAM_ADDRESS][0]; | ||||
|  | ||||
|       c->current_const[argIndex].index = src->Index; | ||||
|       /* If using a non-relative-addressed constant, then keep track of it for | ||||
|        * later use without reloading. | ||||
|        */ | ||||
|       if (relAddr) | ||||
| 	 c->current_const[argIndex].index = -1; | ||||
|       else | ||||
| 	 c->current_const[argIndex].index = src->Index; | ||||
|  | ||||
| #if 0 | ||||
|       printf("  fetch const[%d] for arg %d into reg %d\n", | ||||
|   | ||||
| @@ -376,6 +376,7 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask) | ||||
|       GLint cx, cy, cw, ch; | ||||
|       drm_clip_rect_t clear; | ||||
|       int i; | ||||
|       drm_intel_bo *aper_array[2]; | ||||
|  | ||||
|       /* Get clear bounds after locking */ | ||||
|       cx = fb->_Xmin; | ||||
| @@ -526,6 +527,15 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask) | ||||
|                assert(x1 < x2); | ||||
|                assert(y1 < y2); | ||||
|  | ||||
| 	       /* do space check before going any further */ | ||||
| 	       aper_array[0] = intel->batch->buf; | ||||
| 	       aper_array[1] = write_buffer; | ||||
|  | ||||
| 	       if (drm_intel_bufmgr_check_aperture_space(aper_array, | ||||
| 							 ARRAY_SIZE(aper_array)) != 0) { | ||||
| 		  intel_batchbuffer_flush(intel->batch); | ||||
| 	       } | ||||
|  | ||||
|                BEGIN_BATCH(6, REFERENCES_CLIPRECTS); | ||||
|                OUT_BATCH(CMD); | ||||
|                OUT_BATCH(BR13); | ||||
|   | ||||
| @@ -172,6 +172,8 @@ do_blit_readpixels(GLcontext * ctx, | ||||
|    struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); | ||||
|    GLuint dst_offset; | ||||
|    GLuint rowLength; | ||||
|    drm_intel_bo *dst_buffer; | ||||
|    drm_clip_rect_t read_bounds, rect, src_rect; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s\n", __FUNCTION__); | ||||
| @@ -212,58 +214,47 @@ do_blit_readpixels(GLcontext * ctx, | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|    else { | ||||
|       rowLength = -rowLength; | ||||
|       if (ctx->ReadBuffer->Name == 0) | ||||
| 	 rowLength = -rowLength; | ||||
|    } | ||||
|  | ||||
|    dst_offset = (GLintptr) _mesa_image_address(2, pack, pixels, width, height, | ||||
| 					       format, type, 0, 0, 0); | ||||
|  | ||||
|    GLboolean all = (width * height * src->cpp == dst->Base.Size && | ||||
| 		    x == 0 && dst_offset == 0); | ||||
|  | ||||
|    /* Although the blits go on the command buffer, need to do this and | ||||
|     * fire with lock held to guarentee cliprects are correct. | ||||
|     */ | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    dst_buffer = intel_bufferobj_buffer(intel, dst, | ||||
| 					       all ? INTEL_WRITE_FULL : | ||||
| 					       INTEL_WRITE_PART); | ||||
|  | ||||
|    if (intel->driReadDrawable->numClipRects) { | ||||
|       GLboolean all = (width * height * src->cpp == dst->Base.Size && | ||||
|                        x == 0 && dst_offset == 0); | ||||
|    src_rect.x1 = x; | ||||
|    if (ctx->ReadBuffer->Name == 0) | ||||
|       src_rect.y1 = ctx->ReadBuffer->Height - (y + height); | ||||
|    else | ||||
|       src_rect.y1 = y; | ||||
|    src_rect.x2 = src_rect.x1 + width; | ||||
|    src_rect.y2 = src_rect.y1 + height; | ||||
|  | ||||
|       dri_bo *dst_buffer = intel_bufferobj_buffer(intel, dst, | ||||
| 						  all ? INTEL_WRITE_FULL : | ||||
| 						  INTEL_WRITE_PART); | ||||
|       __DRIdrawablePrivate *dPriv = intel->driReadDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t rect; | ||||
|       drm_clip_rect_t src_rect; | ||||
|       int i; | ||||
|    read_bounds.x1 = 0; | ||||
|    read_bounds.y1 = 0; | ||||
|    read_bounds.x2 = ctx->ReadBuffer->Width; | ||||
|    read_bounds.y2 = ctx->ReadBuffer->Height; | ||||
|  | ||||
|       src_rect.x1 = dPriv->x + x; | ||||
|       src_rect.y1 = dPriv->y + dPriv->h - (y + height); | ||||
|       src_rect.x2 = src_rect.x1 + width; | ||||
|       src_rect.y2 = src_rect.y1 + height; | ||||
|    if (!intel_intersect_cliprects(&rect, &src_rect, &read_bounds)) | ||||
|       return GL_TRUE; | ||||
|  | ||||
|  | ||||
|  | ||||
|       for (i = 0; i < nbox; i++) { | ||||
|          if (!intel_intersect_cliprects(&rect, &src_rect, &box[i])) | ||||
|             continue; | ||||
|  | ||||
|          if (!intelEmitCopyBlit(intel, | ||||
| 				src->cpp, | ||||
| 				src->pitch, src->buffer, 0, src->tiling, | ||||
| 				rowLength, dst_buffer, dst_offset, GL_FALSE, | ||||
| 				rect.x1, | ||||
| 				rect.y1, | ||||
| 				rect.x1 - src_rect.x1, | ||||
| 				rect.y2 - src_rect.y2, | ||||
| 				rect.x2 - rect.x1, rect.y2 - rect.y1, | ||||
| 				GL_COPY)) { | ||||
| 	    UNLOCK_HARDWARE(intel); | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
|       } | ||||
|    if (!intelEmitCopyBlit(intel, | ||||
| 			  src->cpp, | ||||
| 			  src->pitch, src->buffer, 0, src->tiling, | ||||
| 			  rowLength, dst_buffer, dst_offset, GL_FALSE, | ||||
| 			  rect.x1, | ||||
| 			  rect.y1, | ||||
| 			  rect.x1 - src_rect.x1, | ||||
| 			  rect.y2 - src_rect.y2, | ||||
| 			  rect.x2 - rect.x1, rect.y2 - rect.y1, | ||||
| 			  GL_COPY)) { | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|   | ||||
| @@ -70,8 +70,10 @@ | ||||
|  | ||||
| /** @{ | ||||
|  * 915 definitions | ||||
|  * | ||||
|  * 915 documents say that bits 31:28 and 1 are "undefined, must be zero." | ||||
|  */ | ||||
| #define S0_VB_OFFSET_MASK		0xffffffc0 | ||||
| #define S0_VB_OFFSET_MASK		0x0ffffffc | ||||
| #define S0_AUTO_CACHE_INV_DISABLE	(1<<0) | ||||
| /** @} */ | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user