[dx53] Unreal patch

Ann and Jason Edmeades us at the-edmeades.demon.co.uk
Sat Jun 7 16:13:23 CDT 2003


This is a really unreal patch... It makes the intro to Unreal2 look
fantastic, and the weapons in Unreal Tournament actually look correct.
There's a few glitches still after this, but things look a lot better so
its worth getting this in and patching things afterwards

2 comments:
1. I have split drawprimitive into smaller functions in its own module
now as it was both very ugly, and very large and needed large rewrites
for this patch anyway
2. I include in the patch the diagnostics which identified this problem
and make diagnostics a lot easier. I noted it was one of the patches
Alexander didnt apply before, but I would really appreciate them being
in (and they need turning on before compile to impact runtime as well).

I like this patch (and no new GL extensions used so hopefully no compile
issues either) :-)

Jason



Changelog

[53] Make the fixed function pipeline support multiple streams for
created vertex shaders with no function supplied. 
Also split down draw primitive along the lines of the d3dcore
requirements and put in some diagnostic aids

Jason
-------------- next part --------------
Index: dlls/d3d8/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/Makefile.in,v
retrieving revision 1.8
diff -u -r1.8 Makefile.in
--- dlls/d3d8/Makefile.in	4 Jun 2003 21:55:29 -0000	1.8
+++ dlls/d3d8/Makefile.in	7 Jun 2003 21:02:16 -0000
@@ -16,6 +16,7 @@
 	d3d8_main.c \
 	device.c \
 	directx.c \
+	drawprim.c \
 	indexbuffer.c \
 	resource.c \
 	shader.c \
Index: dlls/d3d8/d3d8_private.h
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/d3d8_private.h,v
retrieving revision 1.35
diff -u -r1.35 d3d8_private.h
--- dlls/d3d8/d3d8_private.h	6 Jun 2003 18:12:59 -0000	1.35
+++ dlls/d3d8/d3d8_private.h	7 Jun 2003 21:02:17 -0000
@@ -67,6 +67,15 @@
 #define HIGHEST_TRANSFORMSTATE 512
 #define D3DSBT_RECORDED 0xfffffffe
 
+/* CreateVertexShader can return > 0xFFFF */
+#define VS_HIGHESTFIXEDFXF 0xF0000000
+#define VERTEX_SHADER(Handle) \
+  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
+#define VERTEX_SHADER_DECL(Handle) \
+  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
+#define PIXEL_SHADER(Handle) \
+  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
+
 /* Direct3D8 Interfaces: */
 typedef struct IDirect3DBaseTexture8Impl IDirect3DBaseTexture8Impl;
 typedef struct IDirect3DVolumeTexture8Impl IDirect3DVolumeTexture8Impl;
@@ -112,14 +121,14 @@
 
 /** temporary here waiting for buffer code */
 typedef struct VSHADERINPUTDATA8 {
-  D3DSHADERVECTOR V[16];
+  D3DSHADERVECTOR V[17];
 } VSHADERINPUTDATA8;
 
 /** temporary here waiting for buffer code */
 typedef struct VSHADEROUTPUTDATA8 {
   D3DSHADERVECTOR oPos;
   D3DSHADERVECTOR oD[2];
-  D3DSHADERVECTOR oT[4];
+  D3DSHADERVECTOR oT[8];
   D3DSHADERVECTOR oFog;
   D3DSHADERVECTOR oPts;
 } VSHADEROUTPUTDATA8;
@@ -1064,7 +1073,8 @@
   /* Stream Source */
   UINT                      stream_stride[MAX_STREAMS];
   IDirect3DVertexBuffer8   *stream_source[MAX_STREAMS];
-  
+  BOOL                      streamIsUP;
+
   /* Indices */
   IDirect3DIndexBuffer8*    pIndexData;
   UINT                      baseVertexIndex;
@@ -1141,7 +1151,9 @@
   IDirect3DDevice8Impl* device;
 
   /** precomputed fvf if simple declaration */
-  DWORD   fvf;
+  DWORD   fvf[MAX_STREAMS];
+  DWORD   allFVF;
+
   /** dx8 compatible Declaration fields */
   DWORD*  pDeclaration8;
   DWORD   declaration8Length;
@@ -1197,7 +1209,7 @@
 extern HRESULT WINAPI IDirect3DVertexShaderImpl_ExecuteSW(IDirect3DVertexShaderImpl* This, VSHADERINPUTDATA8* input, VSHADEROUTPUTDATA8* output);
 /* temporary internal Interfaces */
 extern HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShader(IDirect3DDevice8Impl* This, CONST DWORD* pFunction, DWORD Usage, IDirect3DVertexShaderImpl** ppVertexShader);
-extern HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDevice8Impl* This, IDirect3DVertexShaderImpl* vshader, const void* vertexFirstStream, DWORD StartVertexIndex, DWORD idxDecal);
+extern HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDevice8Impl* This, IDirect3DVertexShaderImpl* vshader,  DWORD SkipnStrides);
 
 /* ------------------------ */
 /* IDirect3DPixelShaderImpl */
@@ -1271,5 +1283,38 @@
 const char* debug_d3dressourcetype(D3DRESOURCETYPE res);
 const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType);
 const char* debug_d3dpool(D3DPOOL Pool);
+
+/* Some #defines for additional diagnostics */
+#if 0 /* NOTE: Must be 0 in cvs */
+  /* To avoid having to get gigabytes of trace, the following can be compiled in, and at the start
+     of each frame, a check is made for the existance of C:\D3DTRACE, and if if exists d3d trace   
+     is enabled, and if it doesnt exists it is disabled.                                           */
+# define FRAME_DEBUGGING
+  /*  Adding in the SINGLE_FRAME_DEBUGGING gives a trace of just what makes up a single frame, before
+      the file is deleted                                                                            */
+# if 1
+#  define SINGLE_FRAME_DEBUGGING
+# endif  
+  /* The following, when enabled, lets you see the makeup of the frame, by drawprimitive calls.
+     A check is made for the existence of C:\D3DSHOWFRAME, and if it exists will write the
+     contents of the back buffer into /tmp/backbuffer_* after each primitive array is drawn
+     for a single frame. At the end of the frame, the file is deleted.                         */
+# if 1
+#  define SHOW_FRAME_MAKEUP 1
+# endif  
+extern BOOL isOn;
+extern BOOL isDumpingFrames;
+extern LONG primCounter;
+#endif
+
+/* Per-vertex trace: */
+#if 0 /* NOTE: Must be 0 in cvs */
+# define VTRACE(A) TRACE A
+#else 
+# define VTRACE(A) 
+#endif
+
+#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
+#define TRACE_STRIDED(sd,name) TRACE( #name "=(data:%p, stride:%ld, type:%ld)\n", sd->u.s.name.lpData, sd->u.s.name.dwStride, sd->u.s.name.dwType);
 
 #endif /* __WINE_D3DX8_PRIVATE_H */
Index: dlls/d3d8/d3dcore_gl.h
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/d3dcore_gl.h,v
retrieving revision 1.2
diff -u -r1.2 d3dcore_gl.h
--- dlls/d3d8/d3dcore_gl.h	6 Jun 2003 18:12:59 -0000	1.2
+++ dlls/d3d8/d3dcore_gl.h	7 Jun 2003 21:02:17 -0000
@@ -268,4 +268,44 @@
 #define WINAPI      __stdcall
 #define APIENTRY    WINAPI
 
+/* Routine common to the draw primitive and draw indexed primitive routines */
+void drawPrimitive(LPDIRECT3DDEVICE8 iface,
+                    int PrimitiveType,
+                    long NumPrimitives,
+
+                    /* for Indexed: */
+                    long  StartVertexIndex,
+                    long  StartIdx,
+                    short idxBytes,
+                    const void *idxData,
+                    int   minIndex);
+
+/* Structures required to draw primitives */
+
+
+
+
+
+typedef struct Direct3DStridedData {
+    BYTE     *lpData;        /* Pointer to start of data               */
+    DWORD     dwStride;      /* Stride between occurances of this data */
+    DWORD     dwType;        /* Type (as in D3DVSDT_TYPE)              */
+} Direct3DStridedData;
+
+typedef struct Direct3DVertexStridedData {
+    union {
+        struct {
+             Direct3DStridedData  position;
+             Direct3DStridedData  blendWeights;
+             Direct3DStridedData  blendMatrixIndices;
+             Direct3DStridedData  normal;
+             Direct3DStridedData  pSize;
+             Direct3DStridedData  diffuse;
+             Direct3DStridedData  specular;
+             Direct3DStridedData  texCoords[8];
+        } DUMMYSTRUCTNAME;
+        Direct3DStridedData input[16];  /* Indexed by constants in D3DVSDE_REGISTER */
+    } DUMMYUNIONNAME;
+} Direct3DVertexStridedData;
+
 #endif  /* __WINE_D3DCORE_GL_H */
Index: dlls/d3d8/device.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/device.c,v
retrieving revision 1.70
diff -u -r1.70 device.c
--- dlls/d3d8/device.c	6 Jun 2003 18:12:59 -0000	1.70
+++ dlls/d3d8/device.c	7 Jun 2003 21:02:18 -0000
@@ -41,23 +41,16 @@
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
 
-/* Some #defines for additional diagnostics */
-
-/* Per-vertex trace: */
-#if 0
-# define VTRACE(A) TRACE A
-#else 
-# define VTRACE(A) 
+IDirect3DVertexShaderImpl*            VertexShaders[64];
+IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
+IDirect3DPixelShaderImpl*             PixelShaders[64];
+
+#ifdef FRAME_DEBUGGING
+BOOL isOn             = FALSE;
+BOOL isDumpingFrames  = FALSE;
+LONG primCounter      = 0;
 #endif
 
-
-static IDirect3DVertexShaderImpl* VertexShaders[64];
-static IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
-static IDirect3DPixelShaderImpl*  PixelShaders[64];
-
-/* CreateVertexShader can return > 0xFFFF */
-#define VS_HIGHESTFIXEDFXF 0xF0000000
-
 /*
  * Utility functions or macros
  */
@@ -70,911 +63,6 @@
     memcpy(gl_mat, (mat), 16 * sizeof(float));                                              \
 } while (0)
 
-#define VERTEX_SHADER(Handle) \
-  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
-#define VERTEX_SHADER_DECL(Handle) \
-  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
-#define PIXEL_SHADER(Handle) \
-  ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
-
-#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
-
-/* Routine common to the draw primitive and draw indexed primitive routines */
-void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
-                    int PrimitiveType,
-                    long NumPrimitives,
-                    BOOL  isIndexed,
-
-                    /* For Both:*/
-                    D3DFORMAT fvf,
-                    const void *vertexBufData,
-
-                    /* for Indexed: */
-                    long  StartVertexIndex,
-                    long  StartIdx,
-                    short idxBytes,
-                    const void *idxData,
-                    int   minIndex) {
-
-    int NumVertexes = NumPrimitives;
-    IDirect3DVertexShaderImpl* vertex_shader = NULL;
-    BOOL useVertexShaderFunction = FALSE;
-
-    ICOM_THIS(IDirect3DDevice8Impl,iface);
-
-    /* Dont understand how to handle multiple streams, but if a fixed
-       FVF is passed in rather than a handle, it must use stream 0 */
-    
-    if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
-      vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
-      if (NULL == vertex_shader) {
-          ERR_(d3d_shader)("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
-          return ;
-      }
-      if (NULL == vertex_shader->function) {
-          TRACE_(d3d_shader)("vertex shader declared without program, using FVF pure mode\n");
-      } else {
-          useVertexShaderFunction = TRUE;
-      }
-      fvf = (D3DFORMAT) This->UpdateStateBlock->vertexShaderDecl->fvf;
-      TRACE_(d3d_shader)("vertex shader declared FVF: %08lx\n", This->UpdateStateBlock->vertexShaderDecl->fvf);
-      memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
-
-      /** init Constants */
-      if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
-	TRACE_(d3d_shader)("vertex shader init Constant\n");
-	IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
-      }
-
-    }
-
-    {
-        int                         skip = This->StateBlock->stream_stride[0];
-        GLenum                      primType = GL_POINTS;
-        BOOL                        normal;
-        BOOL                        isRHW;
-        BOOL                        isPtSize;
-        BOOL                        isDiffuse;
-        BOOL                        isSpecular;
-        int                         numBlends;
-        BOOL                        isLastUByte4;
-        int                         numTextures;
-        int                         textureNo;
-        const char                 *curVtx = NULL;
-        const short                *pIdxBufS = NULL;
-        const long                 *pIdxBufL = NULL;
-        const char                 *curPos;
-        BOOL                        isLightingOn = FALSE;
-        int                         vx_index;
-        int                         coordIdxInfo = 0x00;    /* Information on number of coords supplied */
-        float                       s[8], t[8], r[8], q[8]; /* Holding place for tex coords             */
-        const char                 *coordPtr[8];            /* Holding place for the ptr to tex coords  */
-        int                         numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
-
-
-        float x = 0.0f, 
-              y = 0.0f, 
-              z = 0.0f;                     /* x,y,z coordinates          */
-        float nx = 0.0f, 
-              ny =0.0, 
-              nz = 0.0f;                    /* normal x,y,z coordinates   */
-        float rhw = 0.0f;                   /* rhw                        */
-        float ptSize = 0.0f;                /* Point size                 */
-        DWORD diffuseColor = 0xFFFFFFFF;    /* Diffuse Color              */
-        DWORD specularColor = 0;            /* Specular Color             */
-
-        ENTER_GL();
-
-        if (isIndexed) {
-            if (idxBytes == 2) pIdxBufS = (short *) idxData;
-            else pIdxBufL = (long *) idxData;
-        }
-
-        /* Check vertex formats expected ? */
-	/** 
-	 * FVF parser as seen it
-	 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp 
-	 */
-        normal        = fvf & D3DFVF_NORMAL;
-        isRHW         = fvf & D3DFVF_XYZRHW;
-        isLastUByte4  = fvf & D3DFVF_LASTBETA_UBYTE4;
-        numBlends     = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */    
-        isPtSize      = fvf & D3DFVF_PSIZE;
-        isDiffuse     = fvf & D3DFVF_DIFFUSE;
-        isSpecular    = fvf & D3DFVF_SPECULAR;
-        numTextures   = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
-        coordIdxInfo  = (fvf & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
-
-        TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d, coordIdxInfo=%x)\n",
-              fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends, coordIdxInfo);
-
-        /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is 
-           set by the appropriate render state */
-        if (!normal) {
-            isLightingOn = glIsEnabled(GL_LIGHTING);
-            glDisable(GL_LIGHTING);
-            TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
-        }
-
-        if (isRHW) {
-            double X, Y, height, width, minZ, maxZ;
-            /*
-             * Already transformed vertex do not need transform
-             * matrices. Reset all matrices to identity.
-             * Leave the default matrix in world mode.
-             */
-            glMatrixMode(GL_MODELVIEW);
-            checkGLcall("glMatrixMode");
-            glLoadIdentity();
-            checkGLcall("glLoadIdentity");
-	    /**
-	     * As seen in d3d7 code:
-	     *  See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
-	     *  Correctness Tips section).
-	     */
-	    glTranslatef(0.375f, 0.375f, 0.0f);
-	    /**
-	     * 
-	     */
-            glMatrixMode(GL_PROJECTION);
-            checkGLcall("glMatrixMode");
-            glLoadIdentity();
-            checkGLcall("glLoadIdentity");
-	    X = This->StateBlock->viewport.X;
-	    Y = This->StateBlock->viewport.Y;
-            height = This->StateBlock->viewport.Height;
-            width = This->StateBlock->viewport.Width;
-            minZ = This->StateBlock->viewport.MinZ;
-            maxZ = This->StateBlock->viewport.MaxZ;
-            TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
-            /*glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);*/
-	    glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
-            checkGLcall("glOrtho");
-        } else {
-	    double X, Y, height, width;
-	    X = This->StateBlock->viewport.X;
-	    Y = This->StateBlock->viewport.Y;
-            height = This->StateBlock->viewport.Height;
-            width = This->StateBlock->viewport.Width;
-
-            glMatrixMode(GL_MODELVIEW);
-            checkGLcall("glMatrixMode");
-            glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
-            checkGLcall("glLoadMatrixf");
-            glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
-            checkGLcall("glMultMatrixf");
-
-#if 0
-	    /**
-	     * OpenGL seems to map font between pixels
-	     *  well with this it seems better but not perfect
-	     *  anyone have a better idea ?
-	     */
-	    glTranslatef(0.8f / width, -0.8f / height, 0.0f);
-	    /**
-	     *
-	     */
-#endif
-
-            glMatrixMode(GL_PROJECTION);
-            checkGLcall("glMatrixMode");
-            glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
-            checkGLcall("glLoadMatrixf");
-        }
-
-        /* Set OpenGL to the appropriate Primitive Type */
-        switch (PrimitiveType) {
-        case D3DPT_POINTLIST:
-            TRACE("POINTS\n");
-            primType = GL_POINTS;
-            NumVertexes = NumPrimitives;
-            break;
-
-        case D3DPT_LINELIST:
-            TRACE("LINES\n");
-            primType = GL_LINES;
-            NumVertexes = NumPrimitives * 2;
-            break;
-
-        case D3DPT_LINESTRIP:
-            TRACE("LINE_STRIP\n");
-            primType = GL_LINE_STRIP;
-            NumVertexes = NumPrimitives + 1;
-            break;
-
-        case D3DPT_TRIANGLELIST:
-            TRACE("TRIANGLES\n");
-            primType = GL_TRIANGLES;
-            NumVertexes = NumPrimitives * 3;
-            break;
-
-        case D3DPT_TRIANGLESTRIP:
-            TRACE("TRIANGLE_STRIP\n");
-            primType = GL_TRIANGLE_STRIP;
-            NumVertexes = NumPrimitives + 2;
-            break;
-
-        case D3DPT_TRIANGLEFAN:
-            TRACE("TRIANGLE_FAN\n");
-            primType = GL_TRIANGLE_FAN;
-            NumVertexes = NumPrimitives + 2;
-            break;
-
-        default:
-            FIXME("Unhandled primitive\n");
-            break;
-        }
-
-        /* Fixme, Ideally, only use this per-vertex code for software HAL 
-           but until opengl supports all the functions returned to setup 
-           vertex arrays, we need to drop down to the slow mechanism for  
-           certain functions                                              */
-
-        if (isPtSize || isDiffuse || useVertexShaderFunction == TRUE || (numBlends > 0)) {
-            TRACE("Using slow per-vertex code\n");
-
-            /* Enable this one to be able to debug what is going on, but it is slower
-               than the pointer/array version                                          */
-            VTRACE(("glBegin(%x)\n", primType));
-            glBegin(primType);
-
-            /* Draw the primitives */
-            curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
-
-            for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
-
-                if (!isIndexed) {
-                    curPos = curVtx;
-                } else {
-                    if (idxBytes == 2) {
-                        VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
-                        curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
-                    } else {
-                        VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
-                        curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
-                    }
-                }
-
-                /* Work through the vertex buffer */
-                x = *(float *)curPos;
-                curPos = curPos + sizeof(float);
-                y = *(float *)curPos;
-                curPos = curPos + sizeof(float);
-                z = *(float *)curPos;
-                curPos = curPos + sizeof(float);
-                VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
-
-                /* RHW follows, only if transformed */
-                if (isRHW) {
-                    rhw = *(float *)curPos;
-                    curPos = curPos + sizeof(float);
-                    VTRACE(("rhw=%f\n", rhw));
-                }
-
-                /* Blending data */
-                if (numBlends > 0) {
-                    UINT i;
-                    D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
-                    DWORD skippedBlendLastUByte4 = 0;
-
-                    for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
-                        ((float*)&skippedBlend)[i] =  *(float *)curPos; 
-                        curPos = curPos + sizeof(float);
-                    }
-
-                    if (isLastUByte4) {
-                        skippedBlendLastUByte4 =  *(DWORD*)curPos; 
-                        curPos = curPos + sizeof(DWORD);
-                    }
-                }
-
-                /* Vertex Normal Data (untransformed only) */
-                if (normal) {
-                    nx = *(float *)curPos;
-                    curPos = curPos + sizeof(float);
-                    ny = *(float *)curPos;
-                    curPos = curPos + sizeof(float);
-                    nz = *(float *)curPos;
-                    curPos = curPos + sizeof(float);
-                    VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
-                }
-
-                if (isPtSize) {
-                    ptSize = *(float *)curPos;
-                    VTRACE(("ptSize=%f\n", ptSize));
-                    curPos = curPos + sizeof(float);
-                }
-
-                if (isDiffuse) {
-                    diffuseColor = *(DWORD *)curPos;
-                    VTRACE(("diffuseColor=%lx\n", diffuseColor));
-                    curPos = curPos + sizeof(DWORD);
-                }
-
-                if (isSpecular) {
-                    specularColor = *(DWORD *)curPos;
-                    VTRACE(("specularColor=%lx\n", specularColor));
-                    curPos = curPos + sizeof(DWORD);
-                }
-
-                /* Texture coords */
-                /* numTextures indicates the number of texture coordinates supplied */
-                /* However, the first set may not be for stage 0 texture - it all   */
-                /*   depends on D3DTSS_TEXCOORDINDEX.                               */
-                /* The number of bytes for each coordinate set is based off         */
-                /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
-
-                /* Initialize unused coords to unsupplied so we can check later */
-                for (textureNo = numTextures; textureNo < 7; textureNo++) numCoords[textureNo] = -1;
-
-                /* So, for each supplied texture extract the coords */
-                for (textureNo = 0; textureNo < numTextures; ++textureNo) {
-                                        
-                    numCoords[textureNo] = coordIdxInfo & 0x03;
-
-                    /* Always one set */
-                    s[textureNo] = *(float *)curPos;
-                    curPos = curPos + sizeof(float);
-                    if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
-                        t[textureNo] = *(float *)curPos;
-                        curPos = curPos + sizeof(float);
-                        if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
-                            r[textureNo] = *(float *)curPos;
-                            curPos = curPos + sizeof(float);
-                            if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
-                                q[textureNo] = *(float *)curPos;
-                                curPos = curPos + sizeof(float);
-                            }
-                        }
-                    }
-
-                    coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
-                }
-
-                /* Now use the appropriate set of texture indexes */
-                for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
-
-                    if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
-                        FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
-                        continue ;
-                    }
-
-                    /* Query tex coords */
-                    if ((This->StateBlock->textures[textureNo] != NULL) && 
-                        (useVertexShaderFunction == FALSE)) {
-
-                        int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
-
-                        if (coordIdx > 7) {
-                            VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
-                        } else if (coordIdx >= numTextures) {
-                            VTRACE(("tex: %d - Skip tex coords, as requested higher than supplied\n", textureNo));
-                        } else {
-
-                            int coordsToUse = numCoords[coordIdx];
-
-                            /* If texture transform flags in effect, values passed through to vertex
-                               depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
-                            if (coordsToUse > 0 && 
-                                This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) 
-                            {
-                               /* This indicates how many coords to use regardless of the
-                                  texture type. However, d3d/opengl fill in the rest appropriately */
-                               coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
-
-                               /* BUT - Projected is more 'fun' - Move the last coord to the 'q'
-                                  parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
-                               if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
-                                   switch (coordsToUse) {
-                                   case 0:  /* Drop Through */
-                                   case 1:
-                                       FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
-                                       break;
-                                   case 2:
-                                       q[textureNo] = t[textureNo];
-                                       t[textureNo] = 0.0;
-                                       coordsToUse = 4;
-                                       break;
-                                   case 3:
-                                       q[textureNo] = r[textureNo];
-                                       r[textureNo] = 0.0;
-                                       coordsToUse = 4;
-                                       break;
-                                   case 4:  /* Nop here */
-                                       break;
-                                   default:
-                                       FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", 
-                                          This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
-                                   }
-                               }
-                            }
-
-                            switch (coordsToUse) {   /* Supply the provided texture coords */
-                            case D3DFVF_TEXTUREFORMAT1:
-                                VTRACE(("tex:%d, s=%f\n", textureNo, s[coordIdx]));
-                                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-#if defined(GL_VERSION_1_3)
-                                    glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s[coordIdx]);
-#else
-                                    glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx]);
-#endif
-                                } else {
-                                    glTexCoord1f(s[coordIdx]);
-                                }
-                                break;
-                            case D3DFVF_TEXTUREFORMAT2:
-                                VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s[coordIdx], t[coordIdx]));
-                                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-#if defined(GL_VERSION_1_3)
-                                    glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx]);
-#else
-                                    glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx]);
-#endif
-                                } else {
-                                    glTexCoord2f(s[coordIdx], t[coordIdx]);
-                                }
-                                break;
-                            case D3DFVF_TEXTUREFORMAT3:
-                                VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx]));
-                                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-#if defined(GL_VERSION_1_3)
-                                    glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
-#else
-                                    glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
-#endif
-                                } else {
-                                    glTexCoord3f(s[coordIdx], t[coordIdx], r[coordIdx]);
-                                }
-                                break;
-                            case D3DFVF_TEXTUREFORMAT4:
-                                VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]));
-                                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-#if defined(GL_VERSION_1_3)
-                                    glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
-#else
-                                    glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
-#endif
-                                } else {
-                                    glTexCoord4f(s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
-                                }
-                                break;
-                            default:
-                                FIXME("Should not get here as numCoords is two bits only (%x)!\n", numCoords[coordIdx]);
-                            }
-                        }
-                    }
-
-                }
-
-                /** if vertex shader program specified ... using it */
-                if (TRUE == useVertexShaderFunction) {
-
-                    /**
-                     * this code must become the really 
-                     * vs input params init
-                     * 
-                     * because its possible to use input registers for anything
-                     * and some samples use registers for other things than they are
-                     * declared
-                     */
-
-		    /** 
-		     * no really valid declaration, user defined input register use 
-		     * so fill input registers as described in vertex shader declaration
-		     */
-		    IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
-							      (!isIndexed) ? (vx_index * skip) : 
-							                     (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) : 
-							                                       ((pIdxBufL[StartIdx + vx_index]) * skip));
-
-		    memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
-                    IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
-                    /*
-                    TRACE_VECTOR(vertex_shader->output.oPos);
-                    TRACE_VECTOR(vertex_shader->output.oD[0]);
-		    TRACE_VECTOR(vertex_shader->output.oD[1]);
-                    TRACE_VECTOR(vertex_shader->output.oT[0]);
-                    TRACE_VECTOR(vertex_shader->output.oT[1]);
-		    TRACE_VECTOR(vertex_shader->input.V[0]);
-		    TRACE_VECTOR(vertex_shader->data->C[0]);
-		    TRACE_VECTOR(vertex_shader->data->C[1]);
-		    TRACE_VECTOR(vertex_shader->data->C[2]);
-		    TRACE_VECTOR(vertex_shader->data->C[3]);
-		    TRACE_VECTOR(vertex_shader->data->C[4]);
-		    TRACE_VECTOR(vertex_shader->data->C[5]);
-		    TRACE_VECTOR(vertex_shader->data->C[6]);
-		    TRACE_VECTOR(vertex_shader->data->C[7]);
-                    */
-		    x = vertex_shader->output.oPos.x;
-                    y = vertex_shader->output.oPos.y;
-                    z = vertex_shader->output.oPos.z;
-
-                    if (1.0f != vertex_shader->output.oPos.w || isRHW) {
-		      rhw = vertex_shader->output.oPos.w;
-		    }
-		    /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
-		    glColor4fv((float*) &vertex_shader->output.oD[0]);
-		    
-		    /* Requires secondary color extensions to compile... */
-#if defined(GL_EXT_secondary_color)
-		    if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
-		      /*specularColor = D3DCOLORTOCOLORVALUE(vertex_shader->output.oD[1]);*/
-		      GL_EXTCALL(glSecondaryColor3fvEXT)((float*) &vertex_shader->output.oD[1]);
-		      checkGLcall("glSecondaryColor3fvEXT");
-		    }
-#endif
-                    /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
-                    for (textureNo = 0; textureNo < 4; ++textureNo) {
-                        float s, t, r, q;
-
-                        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
-                            FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
-                            continue ;
-                        }
-                        /* Query tex coords */
-                        if (This->StateBlock->textures[textureNo] != NULL) {
-                            switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
-                            case D3DRTYPE_TEXTURE:
-                                /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
-                                s = vertex_shader->output.oT[textureNo].x;
-                                t = vertex_shader->output.oT[textureNo].y;
-                                VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
-                                if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
-                                    VTRACE(("Skip tex coords, as being system generated\n"));
-                                } else {
-                                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-#if defined(GL_VERSION_1_3)
-                                        glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
-#else
-                                        glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
-#endif
-                                        /*checkGLcall("glMultiTexCoord2fARB");*/
-                                    } else {
-                                        glTexCoord2f(s, t);
-                                        /*checkGLcall("gTexCoord2f");*/
-                                    }
-                                }
-                                break;
-
-                            case D3DRTYPE_VOLUMETEXTURE:
-                                /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
-                                s = vertex_shader->output.oT[textureNo].x;
-                                t = vertex_shader->output.oT[textureNo].y;
-                                r = vertex_shader->output.oT[textureNo].z;
-                                VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
-                                if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
-                                    VTRACE(("Skip tex coords, as being system generated\n"));
-                                } else {
-                                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-#if defined(GL_VERSION_1_3)
-                                        glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r); 
-#else
-                                        glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r); 
-#endif
-                                        /*checkGLcall("glMultiTexCoord2fARB");*/
-                                    } else {
-                                        glTexCoord3f(s, t, r);
-                                        /*checkGLcall("gTexCoord3f");*/
-                                    }
-                                }
-                                break;
-
-                            default:
-                                /* Avoid compiler warnings, need these vars later for other textures */
-                                r = 0.0f; q = 0.0f; 
-                                FIXME("Unhandled texture type\n");
-                            }
-                        }
-                    }
-
-                    if (1.0f == rhw || rhw < 0.01f) {
-                        TRACE_(d3d_shader)("Vertex: glVertex:x,y,z=%f,%f,%f\n", x, y, z);
-                        glVertex3f(x, y, z);
-                        /*checkGLcall("glVertex3f");*/
-                    } else {
-		        GLfloat w = 1.0f / rhw;
-                        TRACE_(d3d_shader)("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw);
-			
-                        /*glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);*/
-			glVertex4f(x * w, y * w, z * w, 1.0f);
-                        /*checkGLcall("glVertex4f");*/
-                    }
-                } else { 
-                    /** 
-                     * FALSE == useVertexShaderFunction 
-                     *  using std FVF code
-                     */
-
-                    /* Handle these vertexes */
-                    if (isDiffuse) {
-                        glColor4ub((diffuseColor >> 16) & 0xFF,
-                                   (diffuseColor >>  8) & 0xFF,
-                                   (diffuseColor >>  0) & 0xFF,
-                                   (diffuseColor >> 24) & 0xFF);
-                        VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
-                              ((diffuseColor >> 16) & 0xFF) / 255.0f, 
-                              ((diffuseColor >>  8) & 0xFF) / 255.0f,
-                              ((diffuseColor >>  0) & 0xFF) / 255.0f, 
-                              ((diffuseColor >> 24) & 0xFF) / 255.0f));
-                    }
-
-                    if (normal) {
-                        VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f  /  glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
-                        glNormal3f(nx, ny, nz);
-                        glVertex3f(x, y, z);
-                    } else {
-                        if (1.0f == rhw || rhw < 0.01f) {
-                            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
-                            glVertex3f(x, y, z);
-                        } else {
-                            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
-                            glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
-                        }
-                    }
-                }
-
-                if (!isIndexed) {
-                    curVtx = curVtx + skip;
-                }
-            }
-
-            glEnd();
-            checkGLcall("glEnd and previous calls");
-
-        } else {
-            TRACE("Using fast vertex array code\n");
-
-            /* Faster version, harder to debug */
-            /* Shuffle to the beginning of the vertexes to render and index from there */
-            curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
-            curPos = curVtx;
-
-            /* Set up the vertex pointers */
-            if (isRHW) {
-               glVertexPointer(4, GL_FLOAT, skip, curPos);
-               checkGLcall("glVertexPointer(4, ...)");
-               curPos += 4 * sizeof(float);
-            } else {
-               glVertexPointer(3, GL_FLOAT, skip, curPos);
-               checkGLcall("glVertexPointer(3, ...)");
-               curPos += 3 * sizeof(float);
-            }
-            glEnableClientState(GL_VERTEX_ARRAY);
-            checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
- 
-            if (numBlends > 0) {
-               /* no such functionality in the fixed function GL pipeline */
-               /* FIXME: Wont get here as will drop to slow method        */
-   	       /* FIXME("Cannot handle blending data here in openGl\n");*/
-#if 0
-	       if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
-		 /*FIXME("TODO\n");*/
-	       } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
-		 /*FIXME("TODO\n");*/
-		  /*
-		  GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos); 
-		  checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
-		  glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
-		  checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
-		  */
-	       } else {
-		  FIXME("unsupported blending in openGl\n");
-	       }
-#endif
-	       curPos += numBlends * sizeof(float);
-            } else {
-#if 0
-	       if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
-		  FIXME("TODO\n");
-	       } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
-		  FIXME("TODO\n");
-		  /*
-		  glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
-		  checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
-		  */
-	       }
-#endif
-	    }
-
- 
-            if (normal) {
-                glNormalPointer(GL_FLOAT, skip, curPos);
-                checkGLcall("glNormalPointer");
-                glEnableClientState(GL_NORMAL_ARRAY);
-                checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
-                curPos += 3 * sizeof(float);
-            } else {
-                glDisableClientState(GL_NORMAL_ARRAY);
-                checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
-                glNormal3f(0, 0, 1);
-                checkGLcall("glNormal3f(0, 0, 1)");
-            }
- 
-            if (isPtSize) {
-                /* no such functionality in the fixed function GL pipeline */
-                /* FIXME: Wont get here as will drop to slow method        */
-                FIXME("Cannot change ptSize here in openGl\n");
-                curPos = curPos + sizeof(float);
-            }
-
-            if (isDiffuse) {
-                glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
-                checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
-                glEnableClientState(GL_COLOR_ARRAY);
-                checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
-                curPos += sizeof(DWORD);
-            }
-            else {
-                glDisableClientState(GL_COLOR_ARRAY);
-                checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
-                glColor4f(1, 1, 1, 1);
-                checkGLcall("glColor4f(1, 1, 1, 1)");
-            }
-
-	    /* Requires secondary color extensions to compile... */
-            if (isSpecular) {
-#if defined(GL_EXT_secondary_color)
-                /* FIXME: check for GL_EXT_secondary_color */
-		if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
-		  GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, skip, curPos);
-		  vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
-		  glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
-		  vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
-		}
-#endif
-                curPos += sizeof(DWORD);
-            } else {
-#if defined(GL_EXT_secondary_color)
-	      if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
-                glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
-                vcheckGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
-#if 0
-                GL_EXTCALL(glSecondaryColor3fEXT)(0.0f, 0.0f, 0.0f);
-                vcheckGLcall("glSecondaryColor3fEXT(0, 0, 0)");
-#endif
-	      }
-#endif
-            }
-
-            /* Texture coords */
-            /* numTextures indicates the number of texture coordinates supplied */
-            /* However, the first set may not be for stage 0 texture - it all   */
-            /*   depends on D3DTSS_TEXCOORDINDEX.                               */
-            /* The number of bytes for each coordinate set is based off         */
-            /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
-
-            /* Initialize unused coords to unsupplied so we can check later */
-            for (textureNo = numTextures; textureNo < 7; textureNo++) coordPtr[textureNo] = NULL;
-
-            /* So, for each supplied texture extract the coords */
-            for (textureNo = 0; textureNo < numTextures; ++textureNo) {
-                
-                numCoords[textureNo] = coordIdxInfo & 0x03;
-                coordPtr[textureNo] = curPos;
-
-                /* Always one set */
-                curPos = curPos + sizeof(float);
-                if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
-                    curPos = curPos + sizeof(float);
-                    if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
-                        curPos = curPos + sizeof(float);
-                        if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
-                            curPos = curPos + sizeof(float);
-                        }
-                    }
-                }
-                coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
-            }
-
-            /* Now use the appropriate set of texture indexes */
-            for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
-
-                if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
-                    FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
-                    continue ;
-                }
-
-                /* Query tex coords */
-                if ((This->StateBlock->textures[textureNo] != NULL) && (useVertexShaderFunction == FALSE)) {
-                    int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
-
-                    if (coordIdx > 7) {
-                        VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
-                    } else {
-                        int numFloats = 0;
-                        int coordsToUse = numCoords[coordIdx];
-#if defined(GL_VERSION_1_3)
-                        glClientActiveTexture(GL_TEXTURE0 + textureNo);
-#else
-                        glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
-#endif
-
-                        /* If texture transform flags in effect, values passed through to vertex
-                           depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
-                        if (coordsToUse > 0 && 
-                            This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) 
-                        {
-                           /* This indicates how many coords to use regardless of the
-                              texture type. However, d3d/opengl fill in the rest appropriately */
-                           coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
-
-                           /* BUT - Projected is more 'fun' - Cant be done for ptr mode.
-                              Probably should scan enabled texture units and drop back to
-                              slow mode if found? */
-                           if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
-                               FIXME("Cannot handle projected transform state in fast mode\n");
-                           }
-                        }
-
-                        switch (coordsToUse) {   /* Supply the provided texture coords */
-                        case D3DFVF_TEXTUREFORMAT1: numFloats = 1; break;
-                        case D3DFVF_TEXTUREFORMAT2: numFloats = 2; break;
-                        case D3DFVF_TEXTUREFORMAT3: numFloats = 3; break;
-                        case D3DFVF_TEXTUREFORMAT4: numFloats = 4; break;
-                        default: numFloats = 0; break;           
-                        }
-                            
-                        if (numFloats == 0 || coordIdx >= numTextures) {
-                            VTRACE(("Skipping as invalid request - numfloats=%d, coordIdx=%d, numTextures=%d\n", numFloats, coordIdx, numTextures));
-                            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-                            checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
-                        } else {
-                            VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, coordPtr[coordIdx], numFloats));
-                            glTexCoordPointer(numFloats, GL_FLOAT, skip, coordPtr[coordIdx]);
-                            checkGLcall("glTexCoordPointer(x, ...)");
-                            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-                            checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
-                        }
-                    }
-                }
-            }
-
-            /* Finally do the drawing */
-            if (isIndexed) {
- 
-                TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
-                if (idxBytes==2) {
-#if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
-                    glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
-                                   (char *)idxData+(2 * StartIdx));
-#else
-                    glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
-                                        GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
-#endif
-                } else {
-#if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
-                    glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
-                                   (char *)idxData+(4 * StartIdx));
-#else
-                    glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
-                                        GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
-#endif
-                }
-                checkGLcall("glDrawRangeElements");
-
-            } else {
- 
-                /* Note first is now zero as we shuffled along earlier */
-                TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
-                glDrawArrays(primType, 0, NumVertexes);
-                checkGLcall("glDrawArrays");
- 
-            }
-        }
-
-        /* If no normals, restore previous lighting state */
-        if (!normal) {
-            if (isLightingOn) glEnable(GL_LIGHTING);
-            else glDisable(GL_LIGHTING);
-            TRACE("Restored lighting to original state\n");
-        }
-
-    }
-    LEAVE_GL();
-
-    TRACE("glEnd\n");
-}
-
 /* Apply the current values to the specified texture stage */
 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
     ICOM_THIS(IDirect3DDevice8Impl,iface);
@@ -1221,6 +309,43 @@
     /* Dont call checkGLcall, as glGetError is not applicable here */
     TRACE("glXSwapBuffers called, Starting new frame");
 
+#if defined(FRAME_DEBUGGING)
+{
+    if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
+        if (!isOn) {
+            isOn = TRUE;
+            FIXME("Enabling D3D Trace\n");
+            __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
+#if defined(SHOW_FRAME_MAKEUP)
+            FIXME("Singe Frame snapshots Starting\n");
+            isDumpingFrames = TRUE;
+#endif
+
+#if defined(SINGLE_FRAME_DEBUGGING)
+        } else {
+#if defined(SHOW_FRAME_MAKEUP)
+            FIXME("Singe Frame snapshots Finishing\n");
+            isDumpingFrames = FALSE;
+#endif
+            FIXME("Singe Frame trace complete\n");
+            DeleteFileA("C:\\D3DTRACE");
+            __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
+#endif
+        }
+    } else {
+        if (isOn) {
+            isOn = FALSE;
+#if defined(SHOW_FRAME_MAKEUP)
+            FIXME("Singe Frame snapshots Finishing\n");
+            isDumpingFrames = FALSE;
+#endif
+            FIXME("Disabling D3D Trace\n");
+            __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
+        }
+    }
+}
+#endif
+
     LEAVE_GL();
 
     return D3D_OK;
@@ -4198,15 +3323,11 @@
 }
 HRESULT  WINAPI  IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
 
-    IDirect3DVertexBuffer8     *pVB;
-
     ICOM_THIS(IDirect3DDevice8Impl,iface);
-    pVB = This->StateBlock->stream_source[0];
+    This->StateBlock->streamIsUP = FALSE;
 
     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
-
-    DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
-                   This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
 
     return D3D_OK;
 }
@@ -4214,12 +3335,11 @@
                                                            UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
     UINT idxStride = 2;
     IDirect3DIndexBuffer8      *pIB;
-    IDirect3DVertexBuffer8     *pVB;
     D3DINDEXBUFFER_DESC         IdxBufDsc;
 
     ICOM_THIS(IDirect3DDevice8Impl,iface);
     pIB = This->StateBlock->pIndexData;
-    pVB = This->StateBlock->stream_source[0];
+    This->StateBlock->streamIsUP = FALSE;
 
     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, 
           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
@@ -4232,8 +3352,7 @@
         idxStride = 4;
     }
 
-    DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
-                   This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
+    drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
                    minIndex);
 
     return D3D_OK;
@@ -4246,11 +3365,13 @@
 
     if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
 
-    This->StateBlock->stream_source[0] = NULL;
+    /* Note in the following, its not this type, but thats the purpose of streamIsUP */
+    This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData; 
     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
-    DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
-                   0, 0, 0, NULL, 0);
+    This->StateBlock->streamIsUP = TRUE;
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
     This->StateBlock->stream_stride[0] = 0;
+    This->StateBlock->stream_source[0] = NULL;
 
     /*stream zero settings set to null at end */
     return D3D_OK;
@@ -4271,12 +3392,14 @@
         idxStride = 4;
     }
 
-    This->StateBlock->stream_source[0] = NULL;
+    /* Note in the following, its not this type, but thats the purpose of streamIsUP */
+    This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
+    This->StateBlock->streamIsUP = TRUE;
     This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
-    DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
-                   This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
+    drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
 
     /*stream zero settings set to null at end */
+    This->StateBlock->stream_source[0] = NULL;
     This->StateBlock->stream_stride[0] = 0;
     IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
 
@@ -4313,6 +3436,7 @@
     VertexShaders[i] = object;
     VertexShaderDeclarations[i] = attached_decl;
     *pHandle = VS_HIGHESTFIXEDFXF + i;
+    TRACE("Finished creating vertex shader %lx\n", *pHandle);
 
     return D3D_OK;
 }
Index: dlls/d3d8/shader.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/shader.c,v
retrieving revision 1.13
diff -u -r1.13 shader.c
--- dlls/d3d8/shader.c	4 Jun 2003 22:45:57 -0000	1.13
+++ dlls/d3d8/shader.c	7 Jun 2003 21:02:19 -0000
@@ -34,12 +34,12 @@
 
 /* Shader debugging - Change the following line to enable debugging of software
       vertex shaders                                                             */
-#if 0
+#if 0 /* Must not be 1 in cvs version */
 # define VSTRACE(A) TRACE A
-# define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
+# define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
 #else 
 # define VSTRACE(A) 
-# define TRACE_VECTOR(name)
+# define TRACE_VSVECTOR(name)
 #endif
 
 
@@ -584,30 +584,30 @@
   memset(R, 0, 12 * sizeof(D3DSHADERVECTOR));
 
   /* vshader_program_parse(vshader); */
-#if 0
+#if 0 /* Must not be 1 in cvs */
   TRACE("Input:\n");
-  TRACE_VECTOR(vshader->data->C[0]);
-  TRACE_VECTOR(vshader->data->C[1]);
-  TRACE_VECTOR(vshader->data->C[2]);
-  TRACE_VECTOR(vshader->data->C[3]);
-  TRACE_VECTOR(vshader->data->C[4]);
-  TRACE_VECTOR(vshader->data->C[5]);
-  TRACE_VECTOR(vshader->data->C[6]);
-  TRACE_VECTOR(vshader->data->C[7]);
-  TRACE_VECTOR(vshader->data->C[8]);
-  TRACE_VECTOR(vshader->data->C[64]);
-  TRACE_VECTOR(input->V[D3DVSDE_POSITION]);
-  TRACE_VECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
-  TRACE_VECTOR(input->V[D3DVSDE_BLENDINDICES]);
-  TRACE_VECTOR(input->V[D3DVSDE_NORMAL]);
-  TRACE_VECTOR(input->V[D3DVSDE_PSIZE]);
-  TRACE_VECTOR(input->V[D3DVSDE_DIFFUSE]);
-  TRACE_VECTOR(input->V[D3DVSDE_SPECULAR]);
-  TRACE_VECTOR(input->V[D3DVSDE_TEXCOORD0]);
-  TRACE_VECTOR(input->V[D3DVSDE_TEXCOORD1]);
+  TRACE_VSVECTOR(vshader->data->C[0]);
+  TRACE_VSVECTOR(vshader->data->C[1]);
+  TRACE_VSVECTOR(vshader->data->C[2]);
+  TRACE_VSVECTOR(vshader->data->C[3]);
+  TRACE_VSVECTOR(vshader->data->C[4]);
+  TRACE_VSVECTOR(vshader->data->C[5]);
+  TRACE_VSVECTOR(vshader->data->C[6]);
+  TRACE_VSVECTOR(vshader->data->C[7]);
+  TRACE_VSVECTOR(vshader->data->C[8]);
+  TRACE_VSVECTOR(vshader->data->C[64]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
 #endif
 
-  TRACE_VECTOR(vshader->data->C[64]);
+  TRACE_VSVECTOR(vshader->data->C[64]);
 
   /* the first dword is the version tag */
   /* TODO: parse it */
@@ -756,17 +756,17 @@
       }
       
 #if 0
-      TRACE_VECTOR(output->oPos);
-      TRACE_VECTOR(output->oD[0]);
-      TRACE_VECTOR(output->oD[1]);
-      TRACE_VECTOR(output->oT[0]);
-      TRACE_VECTOR(output->oT[1]);
-      TRACE_VECTOR(R[0]);
-      TRACE_VECTOR(R[1]);
-      TRACE_VECTOR(R[2]);
-      TRACE_VECTOR(R[3]);
-      TRACE_VECTOR(R[4]);
-      TRACE_VECTOR(R[5]);
+      TRACE_VSVECTOR(output->oPos);
+      TRACE_VSVECTOR(output->oD[0]);
+      TRACE_VSVECTOR(output->oD[1]);
+      TRACE_VSVECTOR(output->oT[0]);
+      TRACE_VSVECTOR(output->oT[1]);
+      TRACE_VSVECTOR(R[0]);
+      TRACE_VSVECTOR(R[1]);
+      TRACE_VSVECTOR(R[2]);
+      TRACE_VSVECTOR(R[3]);
+      TRACE_VSVECTOR(R[4]);
+      TRACE_VSVECTOR(R[5]);
 #endif
 
       /* to next opcode token */
@@ -774,26 +774,26 @@
     }
 #if 0
     TRACE("End of current instruction:\n");
-    TRACE_VECTOR(output->oPos);
-    TRACE_VECTOR(output->oD[0]);
-    TRACE_VECTOR(output->oD[1]);
-    TRACE_VECTOR(output->oT[0]);
-    TRACE_VECTOR(output->oT[1]);
-    TRACE_VECTOR(R[0]);
-    TRACE_VECTOR(R[1]);
-    TRACE_VECTOR(R[2]);
-    TRACE_VECTOR(R[3]);
-    TRACE_VECTOR(R[4]);
-    TRACE_VECTOR(R[5]);
+    TRACE_VSVECTOR(output->oPos);
+    TRACE_VSVECTOR(output->oD[0]);
+    TRACE_VSVECTOR(output->oD[1]);
+    TRACE_VSVECTOR(output->oT[0]);
+    TRACE_VSVECTOR(output->oT[1]);
+    TRACE_VSVECTOR(R[0]);
+    TRACE_VSVECTOR(R[1]);
+    TRACE_VSVECTOR(R[2]);
+    TRACE_VSVECTOR(R[3]);
+    TRACE_VSVECTOR(R[4]);
+    TRACE_VSVECTOR(R[5]);
 #endif
   }
-#if 0
+#if 0 /* Must not be 1 in cvs */
     TRACE("Output:\n");
-    TRACE_VECTOR(output->oPos);
-    TRACE_VECTOR(output->oD[0]);
-    TRACE_VECTOR(output->oD[1]);
-    TRACE_VECTOR(output->oT[0]);
-    TRACE_VECTOR(output->oT[1]);
+    TRACE_VSVECTOR(output->oPos);
+    TRACE_VSVECTOR(output->oD[0]);
+    TRACE_VSVECTOR(output->oD[1]);
+    TRACE_VSVECTOR(output->oT[0]);
+    TRACE_VSVECTOR(output->oT[1]);
 #endif
   return D3D_OK;
 }
Index: dlls/d3d8/surface.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/surface.c,v
retrieving revision 1.15
diff -u -r1.15 surface.c
--- dlls/d3d8/surface.c	4 Jun 2003 23:05:46 -0000	1.15
+++ dlls/d3d8/surface.c	7 Jun 2003 21:02:19 -0000
@@ -31,14 +31,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
 
-/* trace: */
-#if 0
-# define VTRACE(A) TRACE A
-#else 
-# define VTRACE(A) 
-#endif
-
-
 /* IDirect3DVolume IUnknown parts follow: */
 HRESULT WINAPI IDirect3DSurface8Impl_QueryInterface(LPDIRECT3DSURFACE8 iface,REFIID riid,LPVOID *ppobj)
 {
Index: dlls/d3d8/utils.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/utils.c,v
retrieving revision 1.5
diff -u -r1.5 utils.c
--- dlls/d3d8/utils.c	6 Jun 2003 18:12:59 -0000	1.5
+++ dlls/d3d8/utils.c	7 Jun 2003 21:02:19 -0000
@@ -35,13 +35,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
-
-#if 0
-# define VTRACE(A) TRACE A
-#else 
-# define VTRACE(A) 
-#endif
-
 const char* debug_d3ddevicetype(D3DDEVTYPE devtype) {
   switch (devtype) {
 #define DEVTYPE_TO_STR(dev) case dev: return #dev
Index: dlls/d3d8/vshaderdeclaration.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/vshaderdeclaration.c,v
retrieving revision 1.3
diff -u -r1.3 vshaderdeclaration.c
--- dlls/d3d8/vshaderdeclaration.c	17 May 2003 18:33:02 -0000	1.3
+++ dlls/d3d8/vshaderdeclaration.c	7 Jun 2003 21:02:19 -0000
@@ -203,6 +203,7 @@
   /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
   object->device = This; /* FIXME: AddRef(This) */
   object->ref = 1;
+  object->allFVF = 0;
 
   while (D3DVSD_END() != *pToken) {
     token = *pToken;
@@ -215,16 +216,27 @@
        * how really works streams, 
        *  in DolphinVS dx8 dsk sample they seems to decal reg numbers !!!
        */
+      DWORD oldStream = stream;
       stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
 
-      if (stream > 0) {
-	/** fvf cannot map mutliple streams, so invalid fvf computing */
-	invalid_fvf = TRUE;
+      /* copy fvf if valid */
+      if (FALSE == invalid_fvf) {
+          fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
+          tex = 0;
+          object->fvf[oldStream] = fvf;
+          object->allFVF |= fvf;
+      } else {
+          object->fvf[oldStream] = 0;
+          tex = 0;
       }
 
+      /* reset valid/invalid fvf */
+      fvf = 0;
+      invalid_fvf = FALSE;
+
     } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
       DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
-      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT) - stream;
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
 
       switch (reg) {
       case D3DVSDE_POSITION:     
@@ -241,7 +253,7 @@
 	  }
 	}
 	break;
-
+      
       case D3DVSDE_BLENDWEIGHT:
 	switch (type) {
 	case D3DVSDT_FLOAT1:     fvf |= D3DFVF_XYZB1;           break;
@@ -305,40 +317,54 @@
 	}
 	break;
 
-	/**
-	 * TODO: for TEX* only FLOAT2 supported
-	 *  by default using texture type info
-	 */
-      case D3DVSDE_TEXCOORD0:    tex = max(tex, D3DFVF_TEX1);   break; 
-      case D3DVSDE_TEXCOORD1:    tex = max(tex, D3DFVF_TEX2);   break;
-      case D3DVSDE_TEXCOORD2:    tex = max(tex, D3DFVF_TEX3);   break;
-      case D3DVSDE_TEXCOORD3:    tex = max(tex, D3DFVF_TEX4);   break;
-      case D3DVSDE_TEXCOORD4:    tex = max(tex, D3DFVF_TEX5);   break;
-      case D3DVSDE_TEXCOORD5:    tex = max(tex, D3DFVF_TEX6);   break;
-      case D3DVSDE_TEXCOORD6:    tex = max(tex, D3DFVF_TEX7);   break;
-      case D3DVSDE_TEXCOORD7:    tex = max(tex, D3DFVF_TEX8);   break;
+      case D3DVSDE_TEXCOORD0:
+      case D3DVSDE_TEXCOORD1:
+      case D3DVSDE_TEXCOORD2:
+      case D3DVSDE_TEXCOORD3:
+      case D3DVSDE_TEXCOORD4:
+      case D3DVSDE_TEXCOORD5:
+      case D3DVSDE_TEXCOORD6:
+      case D3DVSDE_TEXCOORD7:
+         /* Fixme? - assume all tex coords in same stream */
+         {
+             int texNo = 1 + (reg - D3DVSDE_TEXCOORD0);
+             tex = max(tex, texNo);
+             switch (type) {
+             case D3DVSDT_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break;
+             case D3DVSDT_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break;
+             case D3DVSDT_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break;
+             case D3DVSDT_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break;
+             default: 
+               /** errooooorr mismatched use of a register, invalid fvf computing */
+               invalid_fvf = TRUE;
+               TRACE("Mismatched use in VertexShader declaration of D3DVSDE_TEXCOORD? register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+             }
+         }
+         break;
 
       case D3DVSDE_POSITION2:   /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */
       case D3DVSDE_NORMAL2:     /* FIXME i don't know what to do here ;( */
-	FIXME("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token);
+	TRACE("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token);
 	break;
       }
-      /*TRACE("VertexShader declaration define %x as current FVF\n", fvf);*/
+      TRACE("VertexShader declaration define %lx as current FVF\n", fvf);
     }
     len += tokenlen;
     pToken += tokenlen;
   }
-  if (tex > 0) {
-    /*TRACE("VertexShader declaration define %x as texture level\n", tex);*/
-    fvf |= tex;
-  }   
   /* here D3DVSD_END() */
   len +=  Direct3DVextexShaderDeclarationImpl_ParseToken(pToken);
+
   /* copy fvf if valid */
-  if (FALSE == invalid_fvf)
-    object->fvf = fvf;
-  else
-    object->fvf = 0;
+  if (FALSE == invalid_fvf) {
+      fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
+      object->fvf[stream] = fvf;
+      object->allFVF |= fvf;
+  } else {
+      object->fvf[stream] = 0;
+  }
+  TRACE("Completed, allFVF = %lx\n", object->allFVF);
+
   /* compute size */
   object->declaration8Length = len * sizeof(DWORD);
   /* copy the declaration */
@@ -352,9 +378,7 @@
 
 HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDevice8Impl* This,
 							 IDirect3DVertexShaderImpl* vshader,	 
-							 const void* vertexFirstStream,
-							 DWORD StartVertexIndex, 
-							 DWORD idxDecal) {
+							 DWORD SkipnStrides) {
   /** parser data */
   const DWORD* pToken = This->UpdateStateBlock->vertexShaderDecl->pDeclaration8;
   DWORD stream = 0;
@@ -367,7 +391,7 @@
   SHORT u, v, r, t;
   DWORD dw;
 
-  TRACE("(%p) - This:%p - stream:%p, startIdx=%lu, idxDecal=%lu\n", vshader, This, vertexFirstStream, StartVertexIndex, idxDecal);
+  TRACE("(%p) - This:%p, skipstrides=%lu\n", vshader, This, SkipnStrides);
 
   while (D3DVSD_END() != *pToken) {
     token = *pToken;
@@ -376,7 +400,6 @@
     /** FVF generation block */
     if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) {
       IDirect3DVertexBuffer8* pVB;
-      const char* startVtx = NULL;
       int skip = 0;
 
       ++pToken;
@@ -385,25 +408,21 @@
        *  in DolphinVS dx8 dsk sample use it !!!
        */
       stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
-
-      if (0 == stream) {
-	skip = This->StateBlock->stream_stride[0];
-	startVtx = (const char*) vertexFirstStream + (StartVertexIndex * skip);
-	curPos = startVtx + idxDecal;
-	/*TRACE(" using stream[%lu] with %lu decal => curPos %p\n", stream, idxDecal, curPos);*/
-      } else {
-	skip = This->StateBlock->stream_stride[stream];
-	pVB  = This->StateBlock->stream_source[stream];
-
-	if (NULL == pVB) {
+      skip = This->StateBlock->stream_stride[stream];
+      pVB  = This->StateBlock->stream_source[stream];
+      
+      if (NULL == pVB) {
 	  ERR("using unitialised stream[%lu]\n", stream);
 	  return D3DERR_INVALIDCALL;
-	} else {
-	  startVtx = ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory + (StartVertexIndex * skip);
-	  /** do we need to decal if we use idxBuffer */
-	  curPos = startVtx + idxDecal;
-	  /*TRACE(" using stream[%lu] with %lu decal\n", stream, idxDecal);*/
-	}
+      } else {
+          if (This->StateBlock->streamIsUP == TRUE) {
+              curPos = ((char *) pVB) + (SkipnStrides * skip);   /* Not really a VB */
+          } else {
+              curPos = ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory + (SkipnStrides * skip);
+          }
+	  
+	  TRACE(" using stream[%lu] with %p (%p + (Stride %d * skip %ld))\n", stream, curPos, 
+                 ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory, skip, SkipnStrides);
       }
     } else if (D3DVSD_TOKEN_CONSTMEM == tokentype) {
       /** Const decl */
--- /dev/null	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3d8/drawprim.c	2003-06-07 22:58:52.000000000 +0100
@@ -0,0 +1,1351 @@
+/*
+ * D3D8 utils
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <math.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include "d3d8_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
+
+extern IDirect3DVertexShaderImpl*            VertexShaders[64];
+extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
+extern IDirect3DPixelShaderImpl*             PixelShaders[64];
+
+/* Useful holding place for 4 floats */
+typedef struct _D3DVECTOR_4 {
+    float x;
+    float y;
+    float z;
+    float w;
+} D3DVECTOR_4;
+
+#undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
+
+/* Returns bits for what is expected from the fixed function pipeline, and whether 
+   a vertex shader will be in use. Note the fvf bits returned may be split over
+   multiple streams only if the vertex shader was created, otherwise it all relates
+   to stream 0                                                                      */
+BOOL initializeFVF(LPDIRECT3DDEVICE8 iface, 
+                   DWORD *FVFbits,                 /* What to expect in the FVF across all streams */
+                   BOOL *useVertexShaderFunction)  /* Should we use the vertex shader              */
+{
+
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    /* The first thing to work out is if we are using the fixed function pipeline 
+       which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
+       is the FVF, or with a shader which was created with no function - in which
+       case there is an FVF per declared stream. If this occurs, we also maintain
+       an 'OR' of all the FVF's together so we know what to expect across all the     
+       streams                                                                        */
+
+    if (This->UpdateStateBlock->VertexShader <= VS_HIGHESTFIXEDFXF) {
+
+        /* Use this as the FVF */
+        *FVFbits = This->UpdateStateBlock->VertexShader;
+        *useVertexShaderFunction = FALSE;
+        TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
+
+    } else {
+
+        /* Use created shader */
+        IDirect3DVertexShaderImpl* vertex_shader = NULL;
+        vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
+
+        if (vertex_shader == NULL) {
+
+            /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
+            ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
+            return TRUE;
+
+        } else {
+
+            *FVFbits = This->UpdateStateBlock->vertexShaderDecl->allFVF;
+
+            if (vertex_shader->function == NULL) {
+                /* No function, so many streams supplied plus FVF definition pre stream */
+                *useVertexShaderFunction = FALSE;
+                TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n", 
+                            This->StateBlock->VertexShader, *FVFbits);
+            } else {
+                /* Vertex shader needs calling */
+                *useVertexShaderFunction = TRUE;
+                TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
+            }
+        }
+    }
+    return FALSE;
+}
+
+/* Issues the glBegin call for gl given the primitive type and count */
+DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
+                    DWORD            NumPrimitives,
+                    GLenum          *primType)
+{
+    DWORD   NumVertexes = NumPrimitives;
+
+    switch (PrimitiveType) {
+    case D3DPT_POINTLIST:
+        TRACE("POINTS\n");
+        *primType = GL_POINTS;
+        NumVertexes = NumPrimitives;
+        break;
+
+    case D3DPT_LINELIST:
+        TRACE("LINES\n");
+        *primType = GL_LINES;
+        NumVertexes = NumPrimitives * 2;
+        break;
+
+    case D3DPT_LINESTRIP:
+        TRACE("LINE_STRIP\n");
+        *primType = GL_LINE_STRIP;
+        NumVertexes = NumPrimitives + 1;
+        break;
+
+    case D3DPT_TRIANGLELIST:
+        TRACE("TRIANGLES\n");
+        *primType = GL_TRIANGLES;
+        NumVertexes = NumPrimitives * 3;
+        break;
+
+    case D3DPT_TRIANGLESTRIP:
+        TRACE("TRIANGLE_STRIP\n");
+        *primType = GL_TRIANGLE_STRIP;
+        NumVertexes = NumPrimitives + 2;
+        break;
+
+    case D3DPT_TRIANGLEFAN:
+        TRACE("TRIANGLE_FAN\n");
+        *primType = GL_TRIANGLE_FAN;
+        NumVertexes = NumPrimitives + 2;
+        break;
+
+    default:
+        FIXME("Unhandled primitive\n");
+        *primType    = GL_POINTS;
+        break;
+    }  
+    return NumVertexes;
+}
+
+/* Setup views - Transformed & lit if RHW, else untransformed.
+       Only unlit if Normals are supplied                       
+    Returns: Whether to restore lighting afterwards           */
+BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_lit) {
+
+    BOOL isLightingOn = FALSE;
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is 
+       set by the appropriate render state                                    */
+    if (vtx_lit) {
+        isLightingOn = glIsEnabled(GL_LIGHTING);
+        glDisable(GL_LIGHTING);
+        checkGLcall("glDisable(GL_LIGHTING);");
+        TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
+    }
+
+    if (vtx_transformed) {
+        double X, Y, height, width, minZ, maxZ;
+
+        /* Transformed already into viewport coordinates, so we do not need transform
+           matrices. Reset all matrices to identity and leave the default matrix in world 
+           mode.                                                                         */
+        glMatrixMode(GL_MODELVIEW);
+        checkGLcall("glMatrixMode");
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity");
+        /**
+         * As seen in d3d7 code:
+         *  See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
+         *  Correctness Tips section).
+         */
+        glTranslatef(0.375f, 0.375f, 0.0f);
+        checkGLcall("glTranslatef(0.375f, 0.375f, 0.0f)");
+
+        glMatrixMode(GL_PROJECTION);
+        checkGLcall("glMatrixMode");
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity");
+
+        /* Set up the viewport to be full viewport */
+        X      = This->StateBlock->viewport.X;
+        Y      = This->StateBlock->viewport.Y;
+        height = This->StateBlock->viewport.Height;
+        width  = This->StateBlock->viewport.Width;
+        minZ   = This->StateBlock->viewport.MinZ;
+        maxZ   = This->StateBlock->viewport.MaxZ;
+        TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
+        glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
+        checkGLcall("glOrtho");
+
+    } else {
+
+        /* Untransformed, so relies on the view and projection matrices */
+        glMatrixMode(GL_MODELVIEW);
+        checkGLcall("glMatrixMode");
+        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+        glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
+        checkGLcall("glMultMatrixf");
+
+
+        glMatrixMode(GL_PROJECTION);
+        checkGLcall("glMatrixMode");
+        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+    }
+    return isLightingOn;
+}
+
+void primitiveConvertToStridedData(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
+
+    short         LoopThroughTo = 0;
+    short         nStream;
+    BOOL          canDoViaGLPointers = TRUE;
+    int           numBlends;
+    int           numTextures;
+    int           textureNo;
+    int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
+    int           numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
+
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    /* OK, Now to setup the data locations 
+       For the non-created vertex shaders, the VertexShader var holds the real 
+          FVF and only stream 0 matters
+       For the created vertex shaders, there is an FVF per stream              */
+    if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
+        LoopThroughTo = MAX_STREAMS;
+    } else {
+        LoopThroughTo = 1;
+    }
+
+    /* Work through stream by stream */
+    for (nStream=0; nStream<LoopThroughTo; nStream++) {
+        DWORD  stride  = This->StateBlock->stream_stride[nStream];
+        BYTE  *data    = NULL;
+        DWORD  thisFVF = 0;
+
+        /* Skip empty streams */
+        if (This->StateBlock->stream_source[nStream] == NULL) continue;
+
+        /* Retrieve appropriate FVF */
+        if (LoopThroughTo == 1) { /* VertexShader is FVF */
+            thisFVF = This->UpdateStateBlock->VertexShader;
+            /* Handle memory passed directly as well as vertex buffers */
+            if (This->StateBlock->streamIsUP == TRUE) {
+                data    = (BYTE *)This->StateBlock->stream_source[nStream];
+            } else {
+                data    = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
+            }
+        } else {
+            thisFVF = This->StateBlock->vertexShaderDecl->fvf[nStream];
+            data    = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
+        }
+        VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
+        if (thisFVF == 0) continue;
+
+        /* Now convert the stream into pointers */
+
+        /* Shuffle to the beginning of the vertexes to render and index from there */
+        data = data + (BaseVertexIndex * stride);
+
+        /* Either 3 or 4 floats depending on the FVF */
+        /* FIXME: Can blending data be in a different stream to the position data? 
+              and if so using the fixed pipeline how do we handle it               */
+        if (thisFVF & D3DFVF_POSITION_MASK) {
+            strided->u.s.position.lpData    = data;
+            strided->u.s.position.dwType    = D3DVSDT_FLOAT3;
+            strided->u.s.position.dwStride  = stride;
+            data += 3 * sizeof(float);
+            if (thisFVF & D3DFVF_XYZRHW) {
+                strided->u.s.position.dwType = D3DVSDT_FLOAT4;
+                data += sizeof(float);
+            }
+        }
+
+        /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
+        /** do we have to Check This->UpdateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
+        numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 + 
+                    ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);    /* WARNING can be < 0 because -2 */
+        if (numBlends > 0) {
+            canDoViaGLPointers = FALSE; 
+            strided->u.s.blendWeights.lpData    = data;
+            strided->u.s.blendWeights.dwType    = D3DVSDT_FLOAT1 + (numBlends - 1);
+            strided->u.s.blendWeights.dwStride  = stride;
+            data += numBlends * sizeof(FLOAT);
+
+            if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
+                strided->u.s.blendMatrixIndices.lpData = data;
+                strided->u.s.blendMatrixIndices.dwType  = D3DVSDT_UBYTE4; 
+                strided->u.s.blendMatrixIndices.dwStride= stride; 
+                data += sizeof(DWORD);
+            }
+        }
+
+        /* Normal is always 3 floats */
+        if (thisFVF & D3DFVF_NORMAL) {
+            strided->u.s.normal.lpData    = data;
+            strided->u.s.normal.dwType    = D3DVSDT_FLOAT3;
+            strided->u.s.normal.dwStride  = stride;
+            data += 3 * sizeof(FLOAT);
+        }
+
+        /* Pointsize is a single float */
+        if (thisFVF & D3DFVF_PSIZE) {
+            strided->u.s.pSize.lpData    = data;
+            strided->u.s.pSize.dwType    = D3DVSDT_FLOAT1;
+            strided->u.s.pSize.dwStride  = stride;
+            data += sizeof(FLOAT);
+        }
+
+        /* Diffuse is 4 unsigned bytes */
+        if (thisFVF & D3DFVF_DIFFUSE) {
+            strided->u.s.diffuse.lpData    = data;
+            strided->u.s.diffuse.dwType    = D3DVSDT_SHORT4;
+            strided->u.s.diffuse.dwStride  = stride;
+            data += sizeof(DWORD);
+        }
+
+        /* Specular is 4 unsigned bytes */
+        if (thisFVF & D3DFVF_SPECULAR) {
+            strided->u.s.specular.lpData    = data;
+            strided->u.s.specular.dwType    = D3DVSDT_SHORT4;
+            strided->u.s.specular.dwStride  = stride;
+            data += sizeof(DWORD);
+        }
+
+        /* Texture coords */
+        numTextures   = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+        coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
+
+        /* numTextures indicates the number of texture coordinates supplied */
+        /* However, the first set may not be for stage 0 texture - it all   */
+        /*   depends on D3DTSS_TEXCOORDINDEX.                               */
+        /* The number of bytes for each coordinate set is based off         */
+        /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
+
+        /* So, for each supplied texture extract the coords */
+        for (textureNo = 0; textureNo < numTextures; ++textureNo) {
+
+            strided->u.s.texCoords[textureNo].lpData    = data;
+            strided->u.s.texCoords[textureNo].dwType    = D3DVSDT_FLOAT1;
+            strided->u.s.texCoords[textureNo].dwStride  = stride;
+            numCoords[textureNo] = coordIdxInfo & 0x03;
+
+            /* Always one set */
+            data += sizeof(float);
+            if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
+                strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT2;
+                data += sizeof(float);
+                if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
+                    strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT3;
+                    data += sizeof(float);
+                    if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
+                        strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT4;
+                        data += sizeof(float);
+                    }
+                }
+            }
+            coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
+        }
+    }
+}
+
+/* Draw a single vertex using this information */
+void draw_vertex(LPDIRECT3DDEVICE8 iface,                              /* interface    */
+                 BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
+                 BOOL isNormal, float nx, float ny, float nz,          /* normal       */
+                 BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
+                 BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
+                 BOOL isPtSize, float ptSize,                       /* pointSize    */
+                 D3DVECTOR_4 *texcoords, int *numcoords)               /* texture info */
+{
+    int textureNo;
+    float s, t, r, q;
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    /* Diffuse -------------------------------- */
+    if (isDiffuse == TRUE) {
+        glColor4fv(dRGBA);
+        VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
+    }
+
+    /* Specular Colour ------------------------------------------*/
+    if (isSpecular == TRUE) {
+#if defined(GL_EXT_secondary_color)
+        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+          GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
+          VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
+        }
+#endif
+    }
+
+    /* Normal -------------------------------- */
+    if (isNormal == TRUE) {
+        VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
+        glNormal3f(nx, ny, nz);
+    } 
+
+    /* Point Size ----------------------------------------------*/
+    if (isPtSize == TRUE) {
+
+        /* no such functionality in the fixed function GL pipeline */
+        FIXME("Cannot change ptSize here in openGl\n");
+    }
+
+    /* Texture coords --------------------------- */
+    for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+
+        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+            FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
+            continue ;
+        }
+
+        /* Query tex coords */
+        if (This->StateBlock->textures[textureNo] != NULL) {
+
+            int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
+            if (coordIdx > 7) {
+                VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
+                continue;
+            } else if (numcoords[coordIdx] == 0) {
+                TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
+                continue;
+            } else {
+
+                /* Initialize vars */
+                s = 0.0f;
+                t = 0.0f;
+                r = 0.0f;
+                q = 0.0f;
+
+                switch (numcoords[coordIdx]) {
+                case 4: q = texcoords[coordIdx].w; /* drop through */
+                case 3: r = texcoords[coordIdx].z; /* drop through */
+                case 2: t = texcoords[coordIdx].y; /* drop through */
+                case 1: s = texcoords[coordIdx].x; 
+                }
+
+                switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
+                case D3DTTFF_COUNT1:
+                    VTRACE(("tex:%d, s=%f\n", textureNo, s));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
+#else
+                        glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
+#endif
+                    } else {
+                        glTexCoord1f(s);
+                    }
+                    break;
+                case D3DTTFF_COUNT2:
+                    VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
+#else
+                        glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
+#endif
+                    } else {
+                        glTexCoord2f(s, t);
+                    }
+                    break;
+                case D3DTTFF_COUNT3:
+                    VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
+#else
+                        glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
+#endif
+                    } else {
+                        glTexCoord3f(s, t, r);
+                    }
+                    break;
+                case D3DTTFF_COUNT4:
+                    VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
+#else
+                        glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
+#endif
+                    } else {
+                        glTexCoord4f(s, t, r, q);
+                    }
+                    break;
+                default:
+                    FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
+                }
+            }
+        }
+    } /* End of textures */
+
+    /* Position -------------------------------- */
+    if (isXYZ == TRUE) {
+        if (1.0f == rhw || rhw < 0.01f) {
+            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
+            glVertex3f(x, y, z);
+        } else {
+            GLfloat w = 1.0f / rhw;
+            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
+            glVertex4f(x * w, y * w, z * w, 1.0f);
+        }
+    }
+}
+
+/* 
+ * Actually draw using the supplied information.
+ * Faster GL version using pointers to data, harder to debug though 
+ * Note does not handle vertex shaders yet                             
+ */
+void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
+                     int PrimitiveType, ULONG NumPrimitives,
+                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
+    int          textureNo   = 0;
+    GLenum       glPrimType  = GL_POINTS;
+    int          NumVertexes = NumPrimitives;
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    TRACE("Using fast vertex array code\n");
+
+    /* Vertex Pointers -----------------------------------------*/
+    if (sd->u.s.position.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n", 
+                sd->u.s.position.dwStride, 
+                sd->u.s.position.dwType + 1, 
+                sd->u.s.position.lpData));
+        glVertexPointer(sd->u.s.position.dwType + 1, GL_FLOAT, 
+                        sd->u.s.position.dwStride, 
+                        sd->u.s.position.lpData);
+        checkGLcall("glVertexPointer(...)");
+        glEnableClientState(GL_VERTEX_ARRAY);
+        checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
+
+    } else {
+
+        glDisableClientState(GL_VERTEX_ARRAY);
+        checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
+    }
+
+    /* Blend Data ----------------------------------------------*/
+    if ((sd->u.s.blendWeights.lpData != NULL) || 
+        (sd->u.s.blendMatrixIndices.lpData != NULL)) {
+        /* FIXME: Wont get here as will drop to slow method        */
+        FIXME("Blending not supported in fast draw routine\n");
+
+#if 0 /* Vertex blend support needs to be added */
+        if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
+            /*FIXME("TODO\n");*/
+        } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
+            /*FIXME("TODO\n");*/
+            /*
+            GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos); 
+            checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
+            glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
+            checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
+            */
+        } else {
+            FIXME("unsupported blending in openGl\n");
+        }
+    } else {
+        if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
+            FIXME("TODO\n");
+        } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
+            FIXME("TODO\n");
+            /*
+            glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
+            checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
+            */
+        }
+#endif
+    }
+
+    /* Normals -------------------------------------------------*/
+    if (sd->u.s.normal.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n", 
+                sd->u.s.normal.dwStride, 
+                sd->u.s.normal.lpData));
+        glNormalPointer(GL_FLOAT, 
+                        sd->u.s.normal.dwStride, 
+                        sd->u.s.normal.lpData);
+        checkGLcall("glNormalPointer(...)");
+        glEnableClientState(GL_NORMAL_ARRAY);
+        checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
+
+    } else {
+
+        glDisableClientState(GL_NORMAL_ARRAY);
+        checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
+        glNormal3f(0, 0, 1);
+        checkGLcall("glNormal3f(0, 0, 1)");
+    }
+
+    /* Point Size ----------------------------------------------*/
+    if (sd->u.s.pSize.lpData != NULL) {
+
+        /* no such functionality in the fixed function GL pipeline */
+        /* FIXME: Wont get here as will drop to slow method        */
+        FIXME("Cannot change ptSize here in openGl\n");
+    }
+
+    /* Diffuse Colour ------------------------------------------*/
+    /*  WARNING: Data here MUST be in RGBA format, so cannot    */
+    /*     go directly into fast mode from app pgm, because     */
+    /*     directx requires data in BGRA format.                */
+    if (sd->u.s.diffuse.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n", 
+                sd->u.s.diffuse.dwStride, 
+                sd->u.s.diffuse.lpData));
+        glColorPointer(4, GL_UNSIGNED_BYTE, 
+                       sd->u.s.diffuse.dwStride, 
+                       sd->u.s.diffuse.lpData);
+        checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
+        glEnableClientState(GL_COLOR_ARRAY);
+        checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
+
+    } else {
+
+        glDisableClientState(GL_COLOR_ARRAY);
+        checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        checkGLcall("glColor4f(1, 1, 1, 1)");
+    }
+
+    /* Specular Colour ------------------------------------------*/
+    if (sd->u.s.specular.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n", 
+                sd->u.s.specular.dwStride, 
+                sd->u.s.specular.lpData));
+
+#if defined(GL_VERSION_1_4)
+        glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, 
+                                   sd->u.s.specular.dwStride, 
+                                   sd->u.s.specular.lpData);
+        vcheckGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, ...)");
+        glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
+        vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
+#elif defined(GL_EXT_secondary_color)
+        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+            GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
+                                                   sd->u.s.specular.dwStride, 
+                                                   sd->u.s.specular.lpData);
+            checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
+            glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+            checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+        }
+#else
+        /* Missing specular color is not critical, no warnings */
+        VTRACE(("Specular colour is not supported in this GL implementation\n"));
+#endif
+
+    } else {
+
+#if defined(GL_VERSION_1_4)
+        glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
+        checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
+        glSecondaryColor3f(0, 0, 0);
+        checkGLcall("glSecondaryColor3f(0, 0, 0)");
+#elif defined(GL_EXT_secondary_color)
+        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+              glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+            checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+            GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
+            checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
+        }
+#else
+        /* Do not worry if specular colour missing and disable request */
+#endif
+    }
+
+    /* Texture coords -------------------------------------------*/
+    for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+
+        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+            FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
+            continue ;
+        }
+
+        /* Query tex coords */
+        if (This->StateBlock->textures[textureNo] != NULL) {
+            int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
+
+            if (coordIdx > 7) {
+                VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
+            } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
+                VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
+            } else {
+                int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
+                int numFloats = coordsToUse;
+#if defined(GL_VERSION_1_3)
+                glClientActiveTexture(GL_TEXTURE0 + textureNo);
+#else
+                glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
+#endif
+
+                /* If texture transform flags in effect, values passed through to vertex
+                   depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
+                if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
+
+                    /* This indicates how many coords to use regardless of the
+                       texture type. However, d3d/opengl fill in the rest appropriately */
+                    coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
+
+                    /* BUT - Projected is more 'fun' - Cant be done for ptr mode.
+                       Probably should scan enabled texture units and drop back to
+                       slow mode if found? */
+                    if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
+                        FIXME("Cannot handle projected transform state in fast mode\n");
+                    }
+
+                    switch (coordsToUse) {   /* Supply the provided texture coords */
+                    case D3DFVF_TEXTUREFORMAT1: numFloats = 1; break;
+                    case D3DFVF_TEXTUREFORMAT2: numFloats = 2; break;
+                    case D3DFVF_TEXTUREFORMAT3: numFloats = 3; break;
+                    case D3DFVF_TEXTUREFORMAT4: numFloats = 4; break;
+                    default: numFloats = 0; break;           
+                    }
+                }
+
+                if (numFloats == 0) {
+                    FIXME("Skipping as invalid request - numfloats=%d, coordIdx=%d\n", numFloats, coordIdx);
+                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+                    checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
+                } else {
+                    VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, sd->u.s.texCoords[coordIdx].lpData, numFloats));
+                    glTexCoordPointer(numFloats, GL_FLOAT, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
+                    checkGLcall("glTexCoordPointer(x, ...)");
+                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                    checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
+                }
+            }
+        }
+    }
+
+    /* Ok, Work out which primitive is requested and how many vertexes that 
+       will be                                                              */
+    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
+
+    /* Finally do the drawing */
+    if (idxData != NULL) {
+
+        TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
+        if (idxSize==2) {
+#if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
+            glDrawElements(glPrimType, NumVertexes, GL_UNSIGNED_SHORT,
+                           (char *)idxData+(2 * startIdx));
+#else
+            glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
+                                GL_UNSIGNED_SHORT, (char *)idxData+(2 * startIdx));
+#endif
+        } else {
+#if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
+            glDrawElements(glPrimType, NumVertexes, GL_UNSIGNED_INT,
+                           (char *)idxData+(4 * startIdx));
+#else
+            glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
+                                GL_UNSIGNED_INT, (char *)idxData+(2 * startIdx));
+#endif
+        }
+        checkGLcall("glDrawRangeElements");
+
+    } else {
+
+        /* Note first is now zero as we shuffled along earlier */
+        TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
+        glDrawArrays(glPrimType, 0, NumVertexes);
+        checkGLcall("glDrawArrays");
+
+    }
+}
+
+/* 
+ * Actually draw using the supplied information.
+ * Slower GL version which extracts info about each vertex in turn
+ */
+void drawStridedSlow(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
+                     int PrimitiveType, ULONG NumPrimitives,
+                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
+
+    int                        textureNo    = 0;
+    GLenum                     glPrimType   = GL_POINTS;
+    int                        NumVertexes  = NumPrimitives;
+    const short               *pIdxBufS     = NULL;
+    const long                *pIdxBufL     = NULL;
+    LONG                       SkipnStrides = 0;
+    LONG                       vx_index;
+    float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
+    float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
+    float rhw = 0.0f;                      /* rhw                        */
+    float ptSize = 0.0f;                   /* Point size                 */
+    DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
+    DWORD specularColor = 0;               /* Specular Color             */
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    TRACE("Using slow vertex array code\n");
+
+    /* Variable Initialization */
+    if (idxData != NULL) {
+        if (idxSize == 2) pIdxBufS = (short *) idxData;
+        else pIdxBufL = (long *) idxData;
+    }
+
+    /* Ok, Work out which primitive is requested and how many vertexes that will be */
+    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
+
+    /* Start drawing in GL */
+    VTRACE(("glBegin(%x)\n", glPrimType));
+    glBegin(glPrimType);
+
+    /* For each primitive */
+    for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
+
+        /* Initialize diffuse color */
+        diffuseColor = 0xFFFFFFFF;
+
+        /* For indexed data, we need to go a few more strides in */
+        if (idxData != NULL) {
+
+            /* Indexed so work out the number of strides to skip */
+            if (idxSize == 2) {
+                VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
+                SkipnStrides = pIdxBufS[startIdx+vx_index];
+            } else {
+                VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
+                SkipnStrides = pIdxBufL[startIdx+vx_index];
+            }
+        }
+
+        /* Position Information ------------------ */
+        if (sd->u.s.position.lpData != NULL) {
+
+            float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
+            x = ptrToCoords[0];
+            y = ptrToCoords[1];
+            z = ptrToCoords[2];
+            rhw = 1.0;
+            VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
+
+            /* RHW follows, only if transformed, ie 4 floats were provided */
+            if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
+                rhw = ptrToCoords[3];
+                VTRACE(("rhw=%f\n", rhw));
+            }
+        }
+
+        /* Blending data -------------------------- */
+        if (sd->u.s.blendWeights.lpData != NULL) {
+            /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
+            FIXME("Blending not supported yet\n");
+
+            if (sd->u.s.blendMatrixIndices.lpData != NULL) {
+                /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
+            }
+        }
+
+        /* Vertex Normal Data (untransformed only)- */
+        if (sd->u.s.normal.lpData != NULL) {
+
+            float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
+            nx = ptrToCoords[0];
+            ny = ptrToCoords[1];
+            nz = ptrToCoords[2];
+            VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
+        }
+
+        /* Point Size ----------------------------- */
+        if (sd->u.s.pSize.lpData != NULL) {
+
+            float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
+            ptSize = ptrToCoords[0];
+            VTRACE(("ptSize=%f\n", ptSize));
+            FIXME("No support for ptSize yet\n");
+        }
+
+        /* Diffuse -------------------------------- */
+        if (sd->u.s.diffuse.lpData != NULL) {
+
+            DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
+            diffuseColor = ptrToCoords[0];
+            VTRACE(("diffuseColor=%lx\n", diffuseColor));
+        }
+
+        /* Specular  -------------------------------- */
+        if (sd->u.s.specular.lpData != NULL) {
+
+            DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
+            specularColor = ptrToCoords[0];
+            VTRACE(("specularColor=%lx\n", specularColor));
+        }
+
+        /* Texture coords --------------------------- */
+        for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+
+            if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+                FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
+                continue ;
+            }
+
+            /* Query tex coords */
+            if (This->StateBlock->textures[textureNo] != NULL) {
+
+                int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
+                float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
+                float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
+
+                if (coordIdx > 7) {
+                    VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
+                    continue;
+                } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
+                    TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
+                    continue;
+                } else {
+
+                    int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
+
+                    /* If texture transform flags in effect, values passed through to vertex
+                       depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
+                    if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
+
+                        /* This indicates how many coords to use regardless of the
+                           texture type. However, d3d/opengl fill in the rest appropriately */
+                        coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
+
+                        switch (coordsToUse) {
+                        case 4: q = ptrToCoords[3]; /* drop through */
+                        case 3: r = ptrToCoords[2]; /* drop through */
+                        case 2: t = ptrToCoords[1]; /* drop through */
+                        case 1: s = ptrToCoords[0]; 
+                        }
+
+                        /* BUT - Projected is more 'fun' - Move the last coord to the 'q'
+                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
+                        if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
+                            switch (coordsToUse) {
+                            case 0:  /* Drop Through */
+                            case 1:
+                                FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
+                                break;
+                            case 2:
+                                q = t;
+                                t = 0.0;
+                                coordsToUse = 4;
+                                break;
+                            case 3:
+                                q = r;
+                                r = 0.0;
+                                coordsToUse = 4;
+                                break;
+                            case 4:  /* Nop here */
+                                break;
+                            default:
+                                FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", 
+                                      This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
+                            }
+                        }
+                    } else {
+                        switch (coordsToUse) {
+                        case 4: q = ptrToCoords[3]; /* drop through */
+                        case 3: r = ptrToCoords[2]; /* drop through */
+                        case 2: t = ptrToCoords[1]; /* drop through */
+                        case 1: s = ptrToCoords[0]; 
+                        }
+                    }
+
+                    switch (coordsToUse) {   /* Supply the provided texture coords */
+                    case D3DTTFF_COUNT1:
+                        VTRACE(("tex:%d, s=%f\n", textureNo, s));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
+#else
+                            glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
+#endif
+                        } else {
+                            glTexCoord1f(s);
+                        }
+                        break;
+                    case D3DTTFF_COUNT2:
+                        VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
+#else
+                            glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
+#endif
+                        } else {
+                            glTexCoord2f(s, t);
+                        }
+                        break;
+                    case D3DTTFF_COUNT3:
+                        VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
+#else
+                            glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
+#endif
+                        } else {
+                            glTexCoord3f(s, t, r);
+                        }
+                        break;
+                    case D3DTTFF_COUNT4:
+                        VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
+#else
+                            glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
+#endif
+                        } else {
+                            glTexCoord4f(s, t, r, q);
+                        }
+                        break;
+                    default:
+                        FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
+                    }
+                }
+            }
+        } /* End of textures */
+
+
+        /* Diffuse -------------------------------- */
+        if (sd->u.s.diffuse.lpData != NULL) {
+            glColor4ub((diffuseColor >> 16) & 0xFF,
+                       (diffuseColor >>  8) & 0xFF,
+                       (diffuseColor >>  0) & 0xFF,
+                       (diffuseColor >> 24) & 0xFF);
+            VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
+                    ((diffuseColor >> 16) & 0xFF) / 255.0f, 
+                    ((diffuseColor >>  8) & 0xFF) / 255.0f,
+                    ((diffuseColor >>  0) & 0xFF) / 255.0f, 
+                    ((diffuseColor >> 24) & 0xFF) / 255.0f));
+        }
+
+        /* Normal -------------------------------- */
+        if (sd->u.s.normal.lpData != NULL) {
+            VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
+            glNormal3f(nx, ny, nz);
+        } 
+        
+        /* Position -------------------------------- */
+        if (sd->u.s.position.lpData != NULL) {
+            if (1.0f == rhw || rhw < 0.01f) {
+                VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
+                glVertex3f(x, y, z);
+            } else {
+                VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
+                glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
+            }
+        }
+
+        /* For non indexed mode, step onto next parts */
+        if (idxData == NULL) {
+            SkipnStrides += 1;
+        }
+    }
+
+    glEnd();
+    checkGLcall("glEnd and previous calls");
+}
+
+/* 
+ * Draw with emulated vertex shaders
+ * Note: strided data is uninitialized, as we need to pass the vertex
+ *     shader directly as ordering irs yet                             
+ */
+void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
+                     int PrimitiveType, ULONG NumPrimitives,
+                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
+
+    int                        textureNo    = 0;
+    GLenum                     glPrimType   = GL_POINTS;
+    int                        NumVertexes  = NumPrimitives;
+    const short               *pIdxBufS     = NULL;
+    const long                *pIdxBufL     = NULL;
+    LONG                       SkipnStrides = 0;
+    LONG                       vx_index;
+    float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
+    float rhw = 0.0f;                      /* rhw                        */
+    float ptSize = 0.0f;                   /* Point size                 */
+    D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
+    int   numcoords[8];                    /* Number of coords           */
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+    IDirect3DVertexShaderImpl* vertex_shader = NULL;
+
+    TRACE("Using slow software vertex shader code\n");
+
+    /* Variable Initialization */
+    if (idxData != NULL) {
+        if (idxSize == 2) pIdxBufS = (short *) idxData;
+        else pIdxBufL = (long *) idxData;
+    }
+
+    /* Ok, Work out which primitive is requested and how many vertexes that will be */
+    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
+
+    /* Retrieve the VS information */
+    vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
+
+    /* Start drawing in GL */
+    VTRACE(("glBegin(%x)\n", glPrimType));
+    glBegin(glPrimType);
+
+    /* For each primitive */
+    for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
+
+        /* For indexed data, we need to go a few more strides in */
+        if (idxData != NULL) {
+
+            /* Indexed so work out the number of strides to skip */
+            if (idxSize == 2) {
+                VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
+                SkipnStrides = pIdxBufS[startIdx+vx_index];
+            } else {
+                VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
+                SkipnStrides = pIdxBufL[startIdx+vx_index];
+            }
+        }
+
+        /* Fill the vertex shader input */
+        IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, SkipnStrides);
+
+        /* Now execute the vertex shader */
+        memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
+        IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
+
+        /*
+        TRACE_VECTOR(vertex_shader->output.oPos);
+        TRACE_VECTOR(vertex_shader->output.oD[0]);
+        TRACE_VECTOR(vertex_shader->output.oD[1]);
+        TRACE_VECTOR(vertex_shader->output.oT[0]);
+        TRACE_VECTOR(vertex_shader->output.oT[1]);
+        TRACE_VECTOR(vertex_shader->input.V[0]);
+        TRACE_VECTOR(vertex_shader->data->C[0]);
+        TRACE_VECTOR(vertex_shader->data->C[1]);
+        TRACE_VECTOR(vertex_shader->data->C[2]);
+        TRACE_VECTOR(vertex_shader->data->C[3]);
+        TRACE_VECTOR(vertex_shader->data->C[4]);
+        TRACE_VECTOR(vertex_shader->data->C[5]);
+        TRACE_VECTOR(vertex_shader->data->C[6]);
+        TRACE_VECTOR(vertex_shader->data->C[7]);
+        */
+
+        /* Extract out the output */
+        /*FIXME: Fog coords? */
+        x = vertex_shader->output.oPos.x;
+        y = vertex_shader->output.oPos.y;
+        z = vertex_shader->output.oPos.z;
+        rhw = vertex_shader->output.oPos.w;
+        ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
+
+        /** Update textures coords using vertex_shader->output.oT[0->7] */
+        memset(texcoords, 0x00, sizeof(texcoords));
+        memset(numcoords, 0x00, sizeof(numcoords));
+        for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+            if (This->StateBlock->textures[textureNo] != NULL) {
+               texcoords[textureNo].x   = vertex_shader->output.oT[textureNo].x;
+               texcoords[textureNo].y   = vertex_shader->output.oT[textureNo].y;
+               texcoords[textureNo].z   = vertex_shader->output.oT[textureNo].z;
+               texcoords[textureNo].w   = vertex_shader->output.oT[textureNo].w;
+               if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
+                   numcoords[textureNo]    = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
+               } else {
+                   switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
+                   case D3DRTYPE_TEXTURE:       numcoords[textureNo]    = 2; break;
+                   case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo]    = 3; break;
+                   default:                     numcoords[textureNo]    = 4;
+                   }
+               }
+            } else {
+                numcoords[textureNo]    = 0;
+            }
+        }
+
+        /* Draw using this information */
+        draw_vertex(iface,
+                    TRUE, x, y, z, rhw, 
+                    FALSE, 0.0f, 0.0f, 0.0f, 
+                    TRUE, (float*) &vertex_shader->output.oD[0],  
+                    TRUE, (float*) &vertex_shader->output.oD[1],  
+                    FALSE, ptSize,         /* FIXME: Change back when supported */
+                    texcoords, numcoords);
+
+        /* For non indexed mode, step onto next parts */
+        if (idxData == NULL) {
+            SkipnStrides += 1;
+        }
+
+    } /* for each vertex */
+
+    glEnd();
+    checkGLcall("glEnd and previous calls");
+}
+
+/* Routine common to the draw primitive and draw indexed primitive routines */
+void drawPrimitive(LPDIRECT3DDEVICE8 iface,
+                    int PrimitiveType, long NumPrimitives,
+
+                    /* for Indexed: */
+                    long  StartVertexIndex,
+                    long  StartIdx,
+                    short idxSize,
+                    const void *idxData,
+                    int   minIndex) {
+
+    BOOL                          rc = FALSE;
+    DWORD                         fvf = 0;
+    IDirect3DVertexShaderImpl    *vertex_shader = NULL;
+    BOOL                          useVertexShaderFunction = FALSE;
+    BOOL                          isLightingOn = FALSE;
+    Direct3DVertexStridedData     dataLocations;
+    ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+
+    /* Work out what the FVF should look like */
+    rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
+    if (rc) return;
+
+    /* If we will be using a vertex shader, do some initialization for it */
+    if (useVertexShaderFunction == TRUE) {
+        vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
+        memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
+
+        /** init Constants */
+        if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
+            TRACE_(d3d_shader)("vertex shader init Constant\n");
+            IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
+        }
+    }
+
+    /* Ok, we will be updating the screen from here onwards so grab the lock */
+    ENTER_GL();
+
+    /* Setup transform matrices and sort out */
+    isLightingOn = primitiveInitState(iface, 
+                                      fvf & D3DFVF_XYZRHW, 
+                                      !(fvf & D3DFVF_NORMAL));
+
+    /* Initialize all values to null */
+    if (useVertexShaderFunction == FALSE) {
+        memset(&dataLocations, 0x00, sizeof(dataLocations));
+
+        /* Convert to strided data */
+        primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex); 
+
+        /* Dump out what parts we have supplied */
+        TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
+        TRACE_STRIDED((&dataLocations), position);
+        TRACE_STRIDED((&dataLocations), blendWeights);
+        TRACE_STRIDED((&dataLocations), blendMatrixIndices);
+        TRACE_STRIDED((&dataLocations), normal);
+        TRACE_STRIDED((&dataLocations), pSize);
+        TRACE_STRIDED((&dataLocations), diffuse);
+        TRACE_STRIDED((&dataLocations), specular);
+        TRACE_STRIDED((&dataLocations), texCoords[0]);
+        TRACE_STRIDED((&dataLocations), texCoords[1]);
+        TRACE_STRIDED((&dataLocations), texCoords[2]);
+        TRACE_STRIDED((&dataLocations), texCoords[3]);
+        TRACE_STRIDED((&dataLocations), texCoords[4]);
+        TRACE_STRIDED((&dataLocations), texCoords[5]);
+        TRACE_STRIDED((&dataLocations), texCoords[6]);
+        TRACE_STRIDED((&dataLocations), texCoords[7]);
+    }
+
+    /* Now draw the graphics to the screen */
+    if  (useVertexShaderFunction == TRUE) {
+
+        /* Ideally, we should have software FV and hardware VS, possibly
+           depending on the device type?                                 */
+
+        /* We will have to use the very, very slow emulation layer */
+        drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, 
+                        idxData, idxSize, minIndex, StartIdx);            
+
+    } else if ((dataLocations.u.s.pSize.lpData        != NULL) || 
+               (dataLocations.u.s.diffuse.lpData      != NULL) || 
+               (dataLocations.u.s.blendWeights.lpData != NULL)) {
+
+        /* Fixme, Ideally, only use the per-vertex code for software HAL 
+           but until opengl supports all the functions returned to setup 
+           vertex arrays, we need to drop down to the slow mechanism for  
+           certain functions                                              */
+
+        /* We will have to use the slow version of GL per vertex setup */
+        drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives, 
+                        idxData, idxSize, minIndex, StartIdx); 
+
+    } else {
+
+        /* We can use the fast version of GL pointers */
+        drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives, 
+                        idxData, idxSize, minIndex, StartIdx);
+    }
+
+    /* If no normals, restore previous lighting state */
+    if (!(fvf & D3DFVF_NORMAL)) {
+        if (isLightingOn) glEnable(GL_LIGHTING);
+        else glDisable(GL_LIGHTING);
+        TRACE("Restored lighting to original state\n");
+    }
+
+    /* Finshed updating the screen, restore lock */
+    LEAVE_GL();
+    TRACE("Done all gl drawing\n");
+
+    /* Diagnostics */
+#if defined(SHOW_FRAME_MAKEUP)
+    {
+        if (isDumpingFrames == TRUE) {
+            D3DLOCKED_RECT r;
+            char buffer[80];
+            IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->backBuffer, &r, NULL, D3DLOCK_READONLY);
+            sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter++);
+            IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->backBuffer, buffer);
+            IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->backBuffer);
+        }
+    }
+#endif
+}


More information about the wine-patches mailing list