[D3D] Support games using more than 2 texture coordinates

Lionel Ulmer lionel.ulmer at free.fr
Sat Jun 11 16:04:53 CDT 2005


RealMYST uses three texture coordinates. There still seems to be some
texturing artifacts (they look really ugly sometimes) but at least the
geometry is sound :-)

Changelog:
 - support all possible texture coordinates sizes

-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
Index: dlls/ddraw/d3d_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/d3d_private.h,v
retrieving revision 1.44
diff -u -r1.44 d3d_private.h
--- dlls/ddraw/d3d_private.h	7 Jun 2005 21:34:40 -0000	1.44
+++ dlls/ddraw/d3d_private.h	11 Jun 2005 21:03:13 -0000
@@ -270,6 +270,12 @@
 };
 
 /* Various dump and helper functions */
+#define GET_TEXCOUNT_FROM_FVF(d3dvtVertexType) \
+    (((d3dvtVertexType) & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
+
+#define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \
+    (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1)
+
 extern const char *_get_renderstate(D3DRENDERSTATETYPE type);
 extern void dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat);
 extern void dump_D3DCOLORVALUE(D3DCOLORVALUE *lpCol);
Index: dlls/ddraw/d3d_utils.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/d3d_utils.c,v
retrieving revision 1.1
diff -u -r1.1 d3d_utils.c
--- dlls/ddraw/d3d_utils.c	6 Jun 2005 15:51:50 -0000	1.1
+++ dlls/ddraw/d3d_utils.c	11 Jun 2005 21:03:14 -0000
@@ -235,10 +235,10 @@
     DPRINTF("  %f %f %f %f\n", mat->_41, mat->_42, mat->_43, mat->_44);
 }
 
-
 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType)
 {
     DWORD size = 0;
+    int i;
     
     if (d3dvtVertexType & D3DFVF_NORMAL) size += 3 * sizeof(D3DVALUE);
     if (d3dvtVertexType & D3DFVF_DIFFUSE) size += sizeof(DWORD);
@@ -249,8 +249,10 @@
         case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); break;
 	default: TRACE(" matrix weighting not handled yet...\n");
     }
-    size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
-
+    for (i = 0; i < GET_TEXCOUNT_FROM_FVF(d3dvtVertexType); i++) {
+	size += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i) * sizeof(D3DVALUE);
+    }
+    
     return size;
 }
 
@@ -288,8 +290,8 @@
 	GEN_CASE(D3DFVF_TEX8);
     }
 #undef GEN_CASE
-    for (i = 0; i < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); i++) {
-        DPRINTF(" T%d-s%ld", i + 1, (((d3dvtVertexType >> (16 + (2 * i))) + 1) & 0x03) + 1);
+    for (i = 0; i < GET_TEXCOUNT_FROM_FVF(d3dvtVertexType); i++) {
+        DPRINTF(" T%d-s%ld", i + 1, GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i));
     }
     DPRINTF("\n");
 }
@@ -325,9 +327,9 @@
         strided->specular.lpvData  = ((char *) lpvVertices) + current_offset;
         current_offset += sizeof(DWORD);
     }
-    for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
+    for (tex_index = 0; tex_index < GET_TEXCOUNT_FROM_FVF(d3dvtVertexType); tex_index++) {
         strided->textureCoords[tex_index].lpvData  = ((char *) lpvVertices) + current_offset;
-        current_offset += 2 * sizeof(D3DVALUE);
+        current_offset += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index) * sizeof(D3DVALUE);
     }
     strided->position.dwStride = current_offset;
     strided->normal.dwStride   = current_offset;
Index: dlls/ddraw/device_opengl.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/device_opengl.c,v
retrieving revision 1.2
diff -u -r1.2 device_opengl.c
--- dlls/ddraw/device_opengl.c	7 Jun 2005 21:34:40 -0000	1.2
+++ dlls/ddraw/device_opengl.c	11 Jun 2005 21:03:16 -0000
@@ -1296,14 +1296,20 @@
     }
 }
 
-inline static void handle_texture(D3DVALUE *coords) {
-    glTexCoord2fv(coords);
+static void handle_texture(DWORD size, const D3DVALUE *coords) {
+    switch (size) {
+        case 1: glTexCoord1fv(coords); break;
+	case 2: glTexCoord2fv(coords); break;
+	case 3: glTexCoord3fv(coords); break;
+	case 4: glTexCoord4fv(coords); break;
+    }
 }
-inline static void handle_textures(const D3DVALUE *coords, int tex_stage) {
-    if (GL_extensions.glMultiTexCoord2fv) {
-	GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
+
+inline static void handle_textures(DWORD size, const D3DVALUE *coords, int tex_stage) {
+    if (GL_extensions.max_texture_units > 0) {
+	GL_extensions.glMultiTexCoord[size - 1](GL_TEXTURE0_WINE + tex_stage, coords);
     } else {
-	if (tex_stage == 0) glTexCoord2fv(coords);
+	if (tex_stage == 0) handle_texture(size, coords);
     }
 }
 
@@ -1319,7 +1325,7 @@
     BOOLEAN vertex_lighted = FALSE;
     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
     int num_active_stages = 0;
-    int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
+    int num_tex_index = GET_TEXCOUNT_FROM_FVF(d3dvtVertexType);
     
     /* I put the trace before the various locks... So as to better understand where locks occur :-) */
     if (TRACE_ON(ddraw)) {
@@ -1412,7 +1418,7 @@
 		GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
 	    }
 	    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	    glTexCoordPointer(2, GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
+	    glTexCoordPointer(GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index), GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
 			      lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
 	}
 	if (dwIndices != NULL) {
@@ -1450,7 +1456,7 @@
 		    (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
 		
 		handle_normal(normal);
-		handle_texture(tex_coord);
+		handle_texture(2, tex_coord);
 		handle_xyz(position);
 		
 		TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
@@ -1473,7 +1479,7 @@
 		    (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
 		
 		handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
-		handle_texture(tex_coord);
+		handle_texture(2, tex_coord);
 		handle_xyzrhw(position);
 		
 		TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
@@ -1494,7 +1500,7 @@
 	       Note that people should write a fast path for all vertex formats out there...
 	       */  
 	    unsigned int index;
-	    static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
+	    /* static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 }; */
 	    
 	    for (index = 0; index < dwIndexCount; index++) {
 		int i = (dwIndices == NULL) ? index : dwIndices[index];
@@ -1525,14 +1531,19 @@
 		
 		for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
 		    int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
+		    D3DVALUE *tex_coord;
+		    
 		    if (tex_index >= num_tex_index) {
-			handle_textures((const D3DVALUE *) no_index, tex_stage);
-		    } else {
-			D3DVALUE *tex_coord =
-			    (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
-					  i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
-			handle_textures(tex_coord, tex_stage);
+			/* This will have to be checked on Windows. RealMYST uses this feature and I would find it more
+			 * logical to re-use the index of the previous stage than a default index of '0'.
+			 */
+			
+			/* handle_textures((const D3DVALUE *) no_index, tex_stage); */
+			tex_index = num_tex_index - 1;
 		    }
+		    tex_coord = (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
+					      i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
+		    handle_textures(GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index), tex_coord, tex_stage);
 		}
 		
 		if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
@@ -1580,11 +1591,17 @@
 					   (*color_s >>  0) & 0xFF,
 					   (*color_s >> 24) & 0xFF);
 		    }
-		    for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
+		    for (tex_index = 0; tex_index < GET_TEXCOUNT_FROM_FVF(d3dvtVertexType); tex_index++) {
 			D3DVALUE *tex_coord =
 			    (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
 					  i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
-			TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
+			switch (GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index)) {
+			    case 1: TRACE_(ddraw_geom)(" / %f", tex_coord[0]); break;
+			    case 2: TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]); break;
+			    case 3: TRACE_(ddraw_geom)(" / %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2]); break;
+			    case 4: TRACE_(ddraw_geom)(" / %f %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2], tex_coord[3]); break;
+			    default: TRACE_(ddraw_geom)("Invalid texture size (%ld) !!!", GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index)); break;
+			}
 		    }
 		    TRACE_(ddraw_geom)("\n");
 		}
@@ -4397,15 +4414,20 @@
 	    TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
 	    /* We query the ARB version to be the most portable we can... */
 	    GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
-	    GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
+	    GL_extensions.glMultiTexCoord[0] = pglXGetProcAddressARB("glMultiTexCoord1fvARB");
+	    GL_extensions.glMultiTexCoord[1] = pglXGetProcAddressARB("glMultiTexCoord2fvARB");
+	    GL_extensions.glMultiTexCoord[2] = pglXGetProcAddressARB("glMultiTexCoord3fvARB");
+	    GL_extensions.glMultiTexCoord[3] = pglXGetProcAddressARB("glMultiTexCoord4fvARB");
 	    GL_extensions.glClientActiveTexture = pglXGetProcAddressARB("glClientActiveTextureARB");
+	} else {
+	    GL_extensions.max_texture_units = 0;
 	}
 
 	if (strstr(glExtensions, "GL_EXT_texture_compression_s3tc")) {
 	    TRACE(" - S3TC compression supported\n");
 	    GL_extensions.s3tc_compressed_texture = TRUE;
-	    GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB("glCompressedTexImage2D");
-	    GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB("glCompressedTexSubImage2D");
+	    GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB("glCompressedTexImage2DARB");
+	    GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB("glCompressedTexSubImage2DARB");
 	}
     }
     
Index: dlls/ddraw/gl_api.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/gl_api.h,v
retrieving revision 1.7
diff -u -r1.7 gl_api.h
--- dlls/ddraw/gl_api.h	25 Nov 2003 00:06:33 -0000	1.7
+++ dlls/ddraw/gl_api.h	11 Jun 2005 21:03:16 -0000
@@ -98,8 +98,11 @@
 GL_API_FUNCTION(glStencilFunc)
 GL_API_FUNCTION(glStencilMask)
 GL_API_FUNCTION(glStencilOp)
+GL_API_FUNCTION(glTexCoord1fv)
 GL_API_FUNCTION(glTexCoord2f)
 GL_API_FUNCTION(glTexCoord2fv)
+GL_API_FUNCTION(glTexCoord3fv)
+GL_API_FUNCTION(glTexCoord4fv)
 GL_API_FUNCTION(glTexCoordPointer)
 GL_API_FUNCTION(glTexEnvf)
 GL_API_FUNCTION(glTexEnvfv)
Index: dlls/ddraw/gl_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/gl_private.h,v
retrieving revision 1.8
diff -u -r1.8 gl_private.h
--- dlls/ddraw/gl_private.h	25 Nov 2003 00:06:33 -0000	1.8
+++ dlls/ddraw/gl_private.h	11 Jun 2005 21:03:16 -0000
@@ -141,8 +141,11 @@
 #define glStencilFunc pglStencilFunc
 #define glStencilMask pglStencilMask
 #define glStencilOp pglStencilOp
+#define glTexCoord1fv pglTexCoord1fv
 #define glTexCoord2f pglTexCoord2f
 #define glTexCoord2fv pglTexCoord2fv
+#define glTexCoord3fv pglTexCoord3fv
+#define glTexCoord4fv pglTexCoord4fv
 #define glTexCoordPointer pglTexCoordPointer
 #define glTexEnvf pglTexEnvf
 #define glTexEnvfv pglTexEnvfv
Index: dlls/ddraw/opengl_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/opengl_private.h,v
retrieving revision 1.1
diff -u -r1.1 opengl_private.h
--- dlls/ddraw/opengl_private.h	6 Jun 2005 15:51:50 -0000	1.1
+++ dlls/ddraw/opengl_private.h	11 Jun 2005 21:03:16 -0000
@@ -171,7 +171,7 @@
     /* Multi-texturing */
     GLint max_texture_units;
     void (*glActiveTexture)(GLenum texture);
-    void (*glMultiTexCoord2fv)(GLenum target, const GLfloat *v);
+    void (*glMultiTexCoord[4])(GLenum target, const GLfloat *v);
     void (*glClientActiveTexture)(GLenum texture);
     /* S3TC/DXTN compressed texture */
     BOOLEAN s3tc_compressed_texture;
Index: dlls/ddraw/vertexbuffer.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/vertexbuffer.c,v
retrieving revision 1.1
diff -u -r1.1 vertexbuffer.c
--- dlls/ddraw/vertexbuffer.c	6 Jun 2005 15:51:50 -0000	1.1
+++ dlls/ddraw/vertexbuffer.c	11 Jun 2005 21:03:17 -0000
@@ -358,11 +358,11 @@
 	      (DWORD *) (((char *) lpStrideData->specular.lpvData) + i * lpStrideData->specular.dwStride);
 	    copy_and_next(dest_ptr, color_s, sizeof(DWORD));
 	}
-	for (tex_index = 0; tex_index < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
+	for (tex_index = 0; tex_index < GET_TEXCOUNT_FROM_FVF(dwVertexTypeDesc); tex_index++) {
 	    D3DVALUE *tex_coord =
 	      (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + 
 			    i * lpStrideData->textureCoords[tex_index].dwStride);
-	    copy_and_next(dest_ptr, tex_coord, 2 * sizeof(D3DVALUE));
+	    copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(dwVertexTypeDesc, i) * sizeof(D3DVALUE));
 	}
 
 	if (TRACE_ON(ddraw_geom)) {
@@ -398,11 +398,17 @@
 				   (*color_s >>  0) & 0xFF,
 				   (*color_s >> 24) & 0xFF);
 	    }
-	    for (tex_index = 0; tex_index < ((dwVertexTypeDesc & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
+	    for (tex_index = 0; tex_index < GET_TEXCOUNT_FROM_FVF(dwVertexTypeDesc); tex_index++) {
 	        D3DVALUE *tex_coord =
 		  (D3DVALUE *) (((char *) lpStrideData->textureCoords[tex_index].lpvData) + 
 				i * lpStrideData->textureCoords[tex_index].dwStride);
-		TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
+		switch (GET_TEXCOORD_SIZE_FROM_FVF(dwVertexTypeDesc, tex_index)) {
+		    case 1: TRACE_(ddraw_geom)(" / %f", tex_coord[0]); break;
+		    case 2: TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]); break;
+		    case 3: TRACE_(ddraw_geom)(" / %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2]); break;
+		    case 4: TRACE_(ddraw_geom)(" / %f %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2], tex_coord[3]); break;
+		    default: TRACE_(ddraw_geom)("Invalid texture size (%ld) !!!", GET_TEXCOORD_SIZE_FROM_FVF(dwVertexTypeDesc, tex_index)); break;
+		}
 	    }
 	    TRACE_(ddraw_geom)("\n");
 	}


More information about the wine-patches mailing list