[dx53] Try 2

Ann and Jason Edmeades us at the-edmeades.demon.co.uk
Sat Jun 7 18:51:36 CDT 2003


As I said before, except I had broken warcraft so had to delete a few
lines from my patch! Note this also accounts for one of the graphical
glitches I was noticing.

All looks good so here goes...

-------------------------

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

-------------------------
-------------- 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 23:27:21 -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 23:27:21 -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 23:27:21 -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 23:27:22 -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);
@@ -1219,7 +307,45 @@
 
     glXSwapBuffers(This->display, This->drawable);
     /* Dont call checkGLcall, as glGetError is not applicable here */
-    TRACE("glXSwapBuffers called, Starting new frame");
+    TRACE("glXSwapBuffers called, Starting new frame\n");
+
+#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;
+            glClear(GL_COLOR_BUFFER_BIT);
+#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();
 
@@ -4198,15 +3324,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 +3336,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 +3353,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 +3366,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 +3393,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 +3437,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 23:27:23 -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 23:27:23 -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 23:27:23 -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 23:27:24 -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-08 01:20:44.000000000 +0100
@@ -0,0 +1,1343 @@
+/*
+ * 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");
+                    }
+
+                    /* coordsToUse maps to D3DTTFF_COUNT1,2,3,4 == 1,2,3,4 which is correct */
+                }
+                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++);
+            TRACE("Saving screenshot %s\n", buffer);
+            IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->backBuffer, buffer);
+            IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->backBuffer);
+        }
+    }
+#endif
+}


More information about the wine-patches mailing list