Authors: Christian Costa <titan.costa@wanadoo.fr>, Jason Edmeades <us@the-edmeades...
[wine] / dlls / d3d8 / drawprim.c
1 /*
2  * D3D8 utils
3  *
4  * Copyright 2002-2004 Jason Edmeades
5  * Copyright 2002-2004 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <math.h>
26 #include <stdarg.h>
27
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "wine/debug.h"
35
36 #include "d3d8_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
39 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
40
41 extern IDirect3DVertexShaderImpl*            VertexShaders[64];
42 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
43 extern IDirect3DPixelShaderImpl*             PixelShaders[64];
44
45 /* Useful holding place for 4 floats */
46 typedef struct _D3DVECTOR_4 {
47     float x;
48     float y;
49     float z;
50     float w;
51 } D3DVECTOR_4;
52
53 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
54
55 /* Returns bits for what is expected from the fixed function pipeline, and whether 
56    a vertex shader will be in use. Note the fvf bits returned may be split over
57    multiple streams only if the vertex shader was created, otherwise it all relates
58    to stream 0                                                                      */
59 BOOL initializeFVF(LPDIRECT3DDEVICE8 iface, 
60                    DWORD *FVFbits,                 /* What to expect in the FVF across all streams */
61                    BOOL *useVertexShaderFunction)  /* Should we use the vertex shader              */
62 {
63
64     ICOM_THIS(IDirect3DDevice8Impl,iface);
65
66     /* The first thing to work out is if we are using the fixed function pipeline 
67        which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
68        is the FVF, or with a shader which was created with no function - in which
69        case there is an FVF per declared stream. If this occurs, we also maintain
70        an 'OR' of all the FVF's together so we know what to expect across all the     
71        streams                                                                        */
72
73     if (This->UpdateStateBlock->VertexShader <= VS_HIGHESTFIXEDFXF) {
74
75         /* Use this as the FVF */
76         *FVFbits = This->UpdateStateBlock->VertexShader;
77         *useVertexShaderFunction = FALSE;
78         TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
79
80     } else {
81
82         /* Use created shader */
83         IDirect3DVertexShaderImpl* vertex_shader = NULL;
84         vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
85
86         if (vertex_shader == NULL) {
87
88             /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
89             ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
90             return TRUE;
91
92         } else {
93
94             *FVFbits = This->UpdateStateBlock->vertexShaderDecl->allFVF;
95
96             if (vertex_shader->function == NULL) {
97                 /* No function, so many streams supplied plus FVF definition pre stream */
98                 *useVertexShaderFunction = FALSE;
99                 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n", 
100                             This->StateBlock->VertexShader, *FVFbits);
101             } else {
102                 /* Vertex shader needs calling */
103                 *useVertexShaderFunction = TRUE;
104                 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
105             }
106         }
107     }
108     return FALSE;
109 }
110
111 /* Issues the glBegin call for gl given the primitive type and count */
112 DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
113                     DWORD            NumPrimitives,
114                     GLenum          *primType)
115 {
116     DWORD   NumVertexes = NumPrimitives;
117
118     switch (PrimitiveType) {
119     case D3DPT_POINTLIST:
120         TRACE("POINTS\n");
121         *primType = GL_POINTS;
122         NumVertexes = NumPrimitives;
123         break;
124
125     case D3DPT_LINELIST:
126         TRACE("LINES\n");
127         *primType = GL_LINES;
128         NumVertexes = NumPrimitives * 2;
129         break;
130
131     case D3DPT_LINESTRIP:
132         TRACE("LINE_STRIP\n");
133         *primType = GL_LINE_STRIP;
134         NumVertexes = NumPrimitives + 1;
135         break;
136
137     case D3DPT_TRIANGLELIST:
138         TRACE("TRIANGLES\n");
139         *primType = GL_TRIANGLES;
140         NumVertexes = NumPrimitives * 3;
141         break;
142
143     case D3DPT_TRIANGLESTRIP:
144         TRACE("TRIANGLE_STRIP\n");
145         *primType = GL_TRIANGLE_STRIP;
146         NumVertexes = NumPrimitives + 2;
147         break;
148
149     case D3DPT_TRIANGLEFAN:
150         TRACE("TRIANGLE_FAN\n");
151         *primType = GL_TRIANGLE_FAN;
152         NumVertexes = NumPrimitives + 2;
153         break;
154
155     default:
156         FIXME("Unhandled primitive\n");
157         *primType    = GL_POINTS;
158         break;
159     }  
160     return NumVertexes;
161 }
162
163 /* Ensure the appropriate material states are set up - only change
164    state if really required                                        */
165 void init_materials(LPDIRECT3DDEVICE8 iface, BOOL isDiffuseSupplied) {
166
167     BOOL requires_material_reset = FALSE;
168     ICOM_THIS(IDirect3DDevice8Impl,iface);
169
170     if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == TRUE) {
171         /* If we have not set up the material color tracking, do it now as required */
172         glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
173         checkGLcall("glDisable GL_COLOR_MATERIAL");
174         TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
175         glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
176         checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
177         glEnable(GL_COLOR_MATERIAL); 
178         checkGLcall("glEnable GL_COLOR_MATERIAL");
179         This->tracking_color = IS_TRACKING;
180         requires_material_reset = TRUE; /* Restore material settings as will be used */
181
182     } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
183                (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
184         /* If we are tracking the current color but one isn't supplied, don't! */
185         glDisable(GL_COLOR_MATERIAL);
186         checkGLcall("glDisable GL_COLOR_MATERIAL");
187         This->tracking_color = NEEDS_TRACKING;
188         requires_material_reset = TRUE; /* Restore material settings as will be used */
189
190     } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied == TRUE) {
191         /* No need to reset material colors since no change to gl_color_material */
192         requires_material_reset = FALSE;
193
194     } else if (This->tracking_color == NEEDS_DISABLE) {
195         glDisable(GL_COLOR_MATERIAL);
196         checkGLcall("glDisable GL_COLOR_MATERIAL");
197         This->tracking_color = DISABLED_TRACKING;
198         requires_material_reset = TRUE; /* Restore material settings as will be used */
199     }
200
201     /* Reset the material colors which may have been tracking the color*/
202     if (requires_material_reset == TRUE) {
203         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->StateBlock->material.Ambient);
204         checkGLcall("glMaterialfv");
205         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->StateBlock->material.Diffuse);
206         checkGLcall("glMaterialfv");
207         if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
208            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->StateBlock->material.Specular);
209            checkGLcall("glMaterialfv");
210         } else {
211            float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
212            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
213            checkGLcall("glMaterialfv");
214         }
215         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->StateBlock->material.Emissive);
216         checkGLcall("glMaterialfv");
217     }
218
219 }
220
221 static GLfloat invymat[16]={
222         1.0f, 0.0f, 0.0f, 0.0f,
223         0.0f, -1.0f, 0.0f, 0.0f,
224         0.0f, 0.0f, 1.0f, 0.0f,
225         0.0f, 0.0f, 0.0f, 1.0f};
226
227 /* Setup views - Transformed & lit if RHW, else untransformed.
228        Only unlit if Normals are supplied                       
229     Returns: Whether to restore lighting afterwards           */
230 BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
231
232     BOOL isLightingOn = FALSE;
233     ICOM_THIS(IDirect3DDevice8Impl,iface);
234
235     /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
236        set by the appropriate render state. Note Vertex Shader output is already lit */
237     if (vtx_lit || useVS) {
238         isLightingOn = glIsEnabled(GL_LIGHTING);
239         glDisable(GL_LIGHTING);
240         checkGLcall("glDisable(GL_LIGHTING);");
241         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
242     }
243
244     if (!useVS && vtx_transformed) {
245
246         /* If the last draw was transformed as well, no need to reapply all the matrixes */
247         if (!This->last_was_rhw) {
248
249             double X, Y, height, width, minZ, maxZ;
250             This->last_was_rhw = TRUE;
251
252             /* Transformed already into viewport coordinates, so we do not need transform
253                matrices. Reset all matrices to identity and leave the default matrix in world 
254                mode.                                                                         */
255             glMatrixMode(GL_MODELVIEW);
256             checkGLcall("glMatrixMode");
257             glLoadIdentity();
258             checkGLcall("glLoadIdentity");
259
260             glMatrixMode(GL_PROJECTION);
261             checkGLcall("glMatrixMode");
262             glLoadIdentity();
263             checkGLcall("glLoadIdentity");
264
265             /* Set up the viewport to be full viewport */
266             X      = This->StateBlock->viewport.X;
267             Y      = This->StateBlock->viewport.Y;
268             height = This->StateBlock->viewport.Height;
269             width  = This->StateBlock->viewport.Width;
270             minZ   = This->StateBlock->viewport.MinZ;
271             maxZ   = This->StateBlock->viewport.MaxZ;
272             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
273             glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
274             checkGLcall("glOrtho");
275
276             /* Window Coord 0 is the middle of the first pixel, so translate by half
277                a pixel (See comment above glTranslate below)                         */
278             glTranslatef(0.5, 0.5, 0);
279             checkGLcall("glTranslatef(0.5, 0.5, 0)");
280             if (This->renderUpsideDown) {
281                 glMultMatrixf(invymat);
282                 checkGLcall("glMultMatrixf(invymat)");
283             }
284         }
285
286     } else {
287
288         /* Untransformed, so relies on the view and projection matrices */
289
290         if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
291             /* Only reapply when have to */
292             This->modelview_valid = TRUE;
293             glMatrixMode(GL_MODELVIEW);
294             checkGLcall("glMatrixMode");
295
296             /* In the general case, the view matrix is the identity matrix */
297             if (This->view_ident) {
298                 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
299                 checkGLcall("glLoadMatrixf");
300             } else {
301                 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
302                 checkGLcall("glLoadMatrixf");
303                 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
304                 checkGLcall("glMultMatrixf");
305             }
306         }
307
308         if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
309             /* Only reapply when have to */
310             This->proj_valid = TRUE;
311             glMatrixMode(GL_PROJECTION);
312             checkGLcall("glMatrixMode");
313
314             /* The rule is that the window coordinate 0 does not correspond to the
315                beginning of the first pixel, but the center of the first pixel.
316                As a consequence if you want to correctly draw one line exactly from
317                the left to the right end of the viewport (with all matrices set to
318                be identity), the x coords of both ends of the line would be not
319                -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
320                instead.                                                               */
321             glLoadIdentity();
322             glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
323             checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
324
325             if (This->renderUpsideDown) {
326                 glMultMatrixf(invymat);
327                 checkGLcall("glMultMatrixf(invymat)");
328             }
329             glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
330             checkGLcall("glLoadMatrixf");
331         }
332
333         /* Vertex Shader output is already transformed, so set up identity matrices */
334         /* FIXME: Actually, only true for software emulated ones, so when h/w ones  
335              come along this needs to take into account whether s/w ones were 
336              requested or not                                                       */
337         if (useVS) {
338             glMatrixMode(GL_MODELVIEW);
339             checkGLcall("glMatrixMode");
340             glLoadIdentity();
341             glMatrixMode(GL_PROJECTION);
342             checkGLcall("glMatrixMode");
343             glLoadIdentity();
344             /* Window Coord 0 is the middle of the first pixel, so translate by half
345                a pixel (See comment above glTranslate above)                         */
346             glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
347             checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
348             if (This->renderUpsideDown) {
349                 glMultMatrixf(invymat);
350                 checkGLcall("glMultMatrixf(invymat)");
351             }
352             This->modelview_valid = FALSE;
353             This->proj_valid = FALSE;
354         } 
355         This->last_was_rhw = FALSE;
356     }
357     return isLightingOn;
358 }
359
360 void primitiveConvertToStridedData(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
361
362     short         LoopThroughTo = 0;
363     short         nStream;
364     BOOL          canDoViaGLPointers = TRUE;
365     int           numBlends;
366     int           numTextures;
367     int           textureNo;
368     int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
369     int           numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
370
371     ICOM_THIS(IDirect3DDevice8Impl,iface);
372
373     /* OK, Now to setup the data locations 
374        For the non-created vertex shaders, the VertexShader var holds the real 
375           FVF and only stream 0 matters
376        For the created vertex shaders, there is an FVF per stream              */
377     if (!This->StateBlock->streamIsUP && (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF)) {
378         LoopThroughTo = MAX_STREAMS;
379     } else {
380         LoopThroughTo = 1;
381     }
382
383     /* Work through stream by stream */
384     for (nStream=0; nStream<LoopThroughTo; nStream++) {
385         DWORD  stride  = This->StateBlock->stream_stride[nStream];
386         BYTE  *data    = NULL;
387         DWORD  thisFVF = 0;
388
389         /* Skip empty streams */
390         if (This->StateBlock->stream_source[nStream] == NULL) continue;
391
392         /* Retrieve appropriate FVF */
393         if (LoopThroughTo == 1) { /* VertexShader is FVF */
394             thisFVF = This->UpdateStateBlock->VertexShader;
395             /* Handle memory passed directly as well as vertex buffers */
396             if (This->StateBlock->streamIsUP == TRUE) {
397                 data    = (BYTE *)This->StateBlock->stream_source[nStream];
398             } else {
399                 data    = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
400             }
401         } else {
402             thisFVF = This->StateBlock->vertexShaderDecl->fvf[nStream];
403             data    = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
404         }
405         VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
406         if (thisFVF == 0) continue;
407
408         /* Now convert the stream into pointers */
409
410         /* Shuffle to the beginning of the vertexes to render and index from there */
411         data = data + (BaseVertexIndex * stride);
412
413         /* Either 3 or 4 floats depending on the FVF */
414         /* FIXME: Can blending data be in a different stream to the position data? 
415               and if so using the fixed pipeline how do we handle it               */
416         if (thisFVF & D3DFVF_POSITION_MASK) {
417             strided->u.s.position.lpData    = data;
418             strided->u.s.position.dwType    = D3DVSDT_FLOAT3;
419             strided->u.s.position.dwStride  = stride;
420             data += 3 * sizeof(float);
421             if (thisFVF & D3DFVF_XYZRHW) {
422                 strided->u.s.position.dwType = D3DVSDT_FLOAT4;
423                 data += sizeof(float);
424             }
425         }
426
427         /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
428         /** do we have to Check This->UpdateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
429         numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 + 
430                     ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);    /* WARNING can be < 0 because -2 */
431         if (numBlends > 0) {
432             canDoViaGLPointers = FALSE; 
433             strided->u.s.blendWeights.lpData    = data;
434             strided->u.s.blendWeights.dwType    = D3DVSDT_FLOAT1 + (numBlends - 1);
435             strided->u.s.blendWeights.dwStride  = stride;
436             data += numBlends * sizeof(FLOAT);
437
438             if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
439                 strided->u.s.blendMatrixIndices.lpData = data;
440                 strided->u.s.blendMatrixIndices.dwType  = D3DVSDT_UBYTE4; 
441                 strided->u.s.blendMatrixIndices.dwStride= stride; 
442                 data += sizeof(DWORD);
443             }
444         }
445
446         /* Normal is always 3 floats */
447         if (thisFVF & D3DFVF_NORMAL) {
448             strided->u.s.normal.lpData    = data;
449             strided->u.s.normal.dwType    = D3DVSDT_FLOAT3;
450             strided->u.s.normal.dwStride  = stride;
451             data += 3 * sizeof(FLOAT);
452         }
453
454         /* Pointsize is a single float */
455         if (thisFVF & D3DFVF_PSIZE) {
456             strided->u.s.pSize.lpData    = data;
457             strided->u.s.pSize.dwType    = D3DVSDT_FLOAT1;
458             strided->u.s.pSize.dwStride  = stride;
459             data += sizeof(FLOAT);
460         }
461
462         /* Diffuse is 4 unsigned bytes */
463         if (thisFVF & D3DFVF_DIFFUSE) {
464             strided->u.s.diffuse.lpData    = data;
465             strided->u.s.diffuse.dwType    = D3DVSDT_SHORT4;
466             strided->u.s.diffuse.dwStride  = stride;
467             data += sizeof(DWORD);
468         }
469
470         /* Specular is 4 unsigned bytes */
471         if (thisFVF & D3DFVF_SPECULAR) {
472             strided->u.s.specular.lpData    = data;
473             strided->u.s.specular.dwType    = D3DVSDT_SHORT4;
474             strided->u.s.specular.dwStride  = stride;
475             data += sizeof(DWORD);
476         }
477
478         /* Texture coords */
479         numTextures   = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
480         coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
481
482         /* numTextures indicates the number of texture coordinates supplied */
483         /* However, the first set may not be for stage 0 texture - it all   */
484         /*   depends on D3DTSS_TEXCOORDINDEX.                               */
485         /* The number of bytes for each coordinate set is based off         */
486         /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
487
488         /* So, for each supplied texture extract the coords */
489         for (textureNo = 0; textureNo < numTextures; ++textureNo) {
490
491             strided->u.s.texCoords[textureNo].lpData    = data;
492             strided->u.s.texCoords[textureNo].dwType    = D3DVSDT_FLOAT1;
493             strided->u.s.texCoords[textureNo].dwStride  = stride;
494             numCoords[textureNo] = coordIdxInfo & 0x03;
495
496             /* Always one set */
497             data += sizeof(float);
498             if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
499                 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT2;
500                 data += sizeof(float);
501                 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
502                     strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT3;
503                     data += sizeof(float);
504                     if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
505                         strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT4;
506                         data += sizeof(float);
507                     }
508                 }
509             }
510             coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
511         }
512     }
513 }
514
515 /* Draw a single vertex using this information */
516 void draw_vertex(LPDIRECT3DDEVICE8 iface,                              /* interface    */
517                  BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
518                  BOOL isNormal, float nx, float ny, float nz,          /* normal       */
519                  BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
520                  BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
521                  BOOL isPtSize, float ptSize,                       /* pointSize    */
522                  D3DVECTOR_4 *texcoords, int *numcoords)               /* texture info */
523 {
524     int textureNo;
525     float s, t, r, q;
526     ICOM_THIS(IDirect3DDevice8Impl,iface);
527
528     /* Diffuse -------------------------------- */
529     if (isDiffuse == TRUE) {
530         glColor4fv(dRGBA);
531         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
532     }
533
534     /* Specular Colour ------------------------------------------*/
535     if (isSpecular == TRUE) {
536         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
537           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
538           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
539         } else {
540           VTRACE(("Specular color extensions not supplied\n"));
541         }
542     }
543
544     /* Normal -------------------------------- */
545     if (isNormal == TRUE) {
546         VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
547         glNormal3f(nx, ny, nz);
548     } 
549
550     /* Point Size ----------------------------------------------*/
551     if (isPtSize == TRUE) {
552
553         /* no such functionality in the fixed function GL pipeline */
554         FIXME("Cannot change ptSize here in openGl\n");
555     }
556
557     /* Texture coords --------------------------- */
558     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
559
560         if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
561             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
562             continue ;
563         }
564
565         /* Query tex coords */
566         if (This->StateBlock->textures[textureNo] != NULL) {
567
568             int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
569             if (coordIdx > 7) {
570                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
571                 continue;
572             } else if (numcoords[coordIdx] == 0) {
573                 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
574                 continue;
575             } else {
576
577                 /* Initialize vars */
578                 s = 0.0f;
579                 t = 0.0f;
580                 r = 0.0f;
581                 q = 0.0f;
582
583                 switch (numcoords[coordIdx]) {
584                 case 4: q = texcoords[coordIdx].w; /* drop through */
585                 case 3: r = texcoords[coordIdx].z; /* drop through */
586                 case 2: t = texcoords[coordIdx].y; /* drop through */
587                 case 1: s = texcoords[coordIdx].x; 
588                 }
589
590                 switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
591                 case D3DTTFF_COUNT1:
592                     VTRACE(("tex:%d, s=%f\n", textureNo, s));
593                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
594 #if defined(GL_VERSION_1_3)
595                         glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
596 #else
597                         glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
598 #endif
599                     } else {
600                         glTexCoord1f(s);
601                     }
602                     break;
603                 case D3DTTFF_COUNT2:
604                     VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
605                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
606 #if defined(GL_VERSION_1_3)
607                         glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
608 #else
609                         glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
610 #endif
611                     } else {
612                         glTexCoord2f(s, t);
613                     }
614                     break;
615                 case D3DTTFF_COUNT3:
616                     VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
617                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
618 #if defined(GL_VERSION_1_3)
619                         glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
620 #else
621                         glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
622 #endif
623                     } else {
624                         glTexCoord3f(s, t, r);
625                     }
626                     break;
627                 case D3DTTFF_COUNT4:
628                     VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
629                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
630 #if defined(GL_VERSION_1_3)
631                         glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
632 #else
633                         glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
634 #endif
635                     } else {
636                         glTexCoord4f(s, t, r, q);
637                     }
638                     break;
639                 default:
640                     FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
641                 }
642             }
643         }
644     } /* End of textures */
645
646     /* Position -------------------------------- */
647     if (isXYZ == TRUE) {
648         if (1.0f == rhw || rhw < 0.00001f) {
649             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
650             glVertex3f(x, y, z);
651         } else {
652             /* Cannot optimize by dividing through by rhw as rhw is required
653                later for perspective in the GL pipeline for vertex shaders   */
654             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
655             glVertex4f(x,y,z,rhw);
656         }
657     }
658 }
659
660 /* 
661  * Actually draw using the supplied information.
662  * Faster GL version using pointers to data, harder to debug though 
663  * Note does not handle vertex shaders yet                             
664  */
665 void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
666                      int PrimitiveType, ULONG NumPrimitives,
667                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
668     int          textureNo   = 0;
669     GLenum       glPrimType  = GL_POINTS;
670     int          NumVertexes = NumPrimitives;
671     ICOM_THIS(IDirect3DDevice8Impl,iface);
672
673     TRACE("Using fast vertex array code\n");
674
675     /* Vertex Pointers -----------------------------------------*/
676     if (sd->u.s.position.lpData != NULL) {
677
678         /* Note dwType == float3 or float4 == 2 or 3 */
679         VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n", 
680                 sd->u.s.position.dwStride, 
681                 sd->u.s.position.dwType + 1, 
682                 sd->u.s.position.lpData));
683
684         /* Disable RHW mode as 'w' coord handling for rhw mode should
685            not impact screen position whereas in GL it does. This may 
686            result in very slightly distored textures in rhw mode, but
687            a very minimal different                                   */
688         glVertexPointer(3, GL_FLOAT,  /* RHW: Was 'sd->u.s.position.dwType + 1' */
689                         sd->u.s.position.dwStride, 
690                         sd->u.s.position.lpData);
691         checkGLcall("glVertexPointer(...)");
692         glEnableClientState(GL_VERTEX_ARRAY);
693         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
694
695     } else {
696
697         glDisableClientState(GL_VERTEX_ARRAY);
698         checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
699     }
700
701     /* Blend Data ----------------------------------------------*/
702     if ((sd->u.s.blendWeights.lpData != NULL) || 
703         (sd->u.s.blendMatrixIndices.lpData != NULL)) {
704         /* FIXME: Won't get here as will drop to slow method        */
705         FIXME("Blending not supported in fast draw routine\n");
706
707 #if 0 /* Vertex blend support needs to be added */
708         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
709             /*FIXME("TODO\n");*/
710         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
711             /*FIXME("TODO\n");*/
712             /*
713             GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos); 
714             checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
715             glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
716             checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
717             */
718         } else {
719             FIXME("unsupported blending in openGl\n");
720         }
721     } else {
722         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
723             FIXME("TODO\n");
724         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
725             FIXME("TODO\n");
726             /*
727             glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
728             checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
729             */
730         }
731 #endif
732     }
733
734     /* Normals -------------------------------------------------*/
735     if (sd->u.s.normal.lpData != NULL) {
736
737         /* Note dwType == float3 or float4 == 2 or 3 */
738         VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n", 
739                 sd->u.s.normal.dwStride, 
740                 sd->u.s.normal.lpData));
741         glNormalPointer(GL_FLOAT, 
742                         sd->u.s.normal.dwStride, 
743                         sd->u.s.normal.lpData);
744         checkGLcall("glNormalPointer(...)");
745         glEnableClientState(GL_NORMAL_ARRAY);
746         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
747
748     } else {
749
750         glDisableClientState(GL_NORMAL_ARRAY);
751         checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
752         glNormal3f(0, 0, 1);
753         checkGLcall("glNormal3f(0, 0, 1)");
754     }
755
756     /* Point Size ----------------------------------------------*/
757     if (sd->u.s.pSize.lpData != NULL) {
758
759         /* no such functionality in the fixed function GL pipeline */
760         /* FIXME: Won't get here as will drop to slow method        */
761         FIXME("Cannot change ptSize here in openGl\n");
762     }
763
764     /* Diffuse Colour ------------------------------------------*/
765     /*  WARNING: Data here MUST be in RGBA format, so cannot    */
766     /*     go directly into fast mode from app pgm, because     */
767     /*     directx requires data in BGRA format.                */
768     if (sd->u.s.diffuse.lpData != NULL) {
769
770         /* Note dwType == float3 or float4 == 2 or 3 */
771         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n", 
772                 sd->u.s.diffuse.dwStride, 
773                 sd->u.s.diffuse.lpData));
774         glColorPointer(4, GL_UNSIGNED_BYTE, 
775                        sd->u.s.diffuse.dwStride, 
776                        sd->u.s.diffuse.lpData);
777         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
778         glEnableClientState(GL_COLOR_ARRAY);
779         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
780
781     } else {
782
783         glDisableClientState(GL_COLOR_ARRAY);
784         checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
785         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
786         checkGLcall("glColor4f(1, 1, 1, 1)");
787     }
788
789     /* Specular Colour ------------------------------------------*/
790     if (sd->u.s.specular.lpData != NULL) {
791
792         /* Note dwType == float3 or float4 == 2 or 3 */
793         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n", 
794                 sd->u.s.specular.dwStride, 
795                 sd->u.s.specular.lpData));
796
797         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
798             GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
799                                                    sd->u.s.specular.dwStride, 
800                                                    sd->u.s.specular.lpData);
801             vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
802             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
803             vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
804         } else {
805           /* Missing specular color is not critical, no warnings */
806           VTRACE(("Specular colour is not supported in this GL implementation\n"));
807         }
808
809     } else {
810
811       if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
812         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
813         checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
814         GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
815         checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
816       } else {
817         /* Missing specular color is not critical, no warnings */
818         VTRACE(("Specular colour is not supported in this GL implementation\n"));
819       }
820     }
821
822     /* Texture coords -------------------------------------------*/
823     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
824
825         /* Select the correct texture stage */
826 #if defined(GL_VERSION_1_3)
827         glClientActiveTexture(GL_TEXTURE0 + textureNo);
828 #else
829         glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
830 #endif
831
832         /* Query tex coords */
833         if (This->StateBlock->textures[textureNo] != NULL) {
834             int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
835
836             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
837                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
838                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
839 #if defined(GL_VERSION_1_3)
840                 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
841 #else
842                 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
843 #endif
844                 continue;
845             }
846
847             if (coordIdx > 7) {
848                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
849                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
850 #if defined(GL_VERSION_1_3)
851                 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
852 #else
853                 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
854 #endif
855             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
856                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
857                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
858 #if defined(GL_VERSION_1_3)
859                 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
860 #else
861                 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
862 #endif
863             } else {
864
865                 /* The coords to supply depend completely on the fvf / vertex shader */
866                 GLint size;
867                 GLenum type;
868
869                 switch (sd->u.s.texCoords[coordIdx].dwType) {
870                 case D3DVSDT_FLOAT1: size = 1, type = GL_FLOAT; break;
871                 case D3DVSDT_FLOAT2: size = 2, type = GL_FLOAT; break;
872                 case D3DVSDT_FLOAT3: size = 3, type = GL_FLOAT; break;
873                 case D3DVSDT_FLOAT4: size = 4, type = GL_FLOAT; break;
874                 case D3DVSDT_SHORT2: size = 2, type = GL_SHORT; break;
875                 case D3DVSDT_SHORT4: size = 4, type = GL_SHORT; break;
876                 case D3DVSDT_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
877                 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
878                       size = 4; type = GL_UNSIGNED_BYTE;
879                 }
880
881                 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
882                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
883             }
884         } else {
885             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
886 #if defined(GL_VERSION_1_3)
887             glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
888 #else
889             glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
890 #endif
891         }
892     } 
893
894     /* Ok, Work out which primitive is requested and how many vertexes that 
895        will be                                                              */
896     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
897
898     /* Finally do the drawing */
899     if (idxData != NULL) {
900
901         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
902 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
903         glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
904                       (char *)idxData+(idxSize * startIdx));
905 #else
906         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
907                       idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT, 
908                       (char *)idxData+(idxSize * startIdx));
909 #endif
910         checkGLcall("glDrawRangeElements");
911
912     } else {
913
914         /* Note first is now zero as we shuffled along earlier */
915         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
916         glDrawArrays(glPrimType, 0, NumVertexes);
917         checkGLcall("glDrawArrays");
918
919     }
920 }
921
922 /* 
923  * Actually draw using the supplied information.
924  * Slower GL version which extracts info about each vertex in turn
925  */
926 void drawStridedSlow(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
927                      int PrimitiveType, ULONG NumPrimitives,
928                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
929
930     int                        textureNo    = 0;
931     GLenum                     glPrimType   = GL_POINTS;
932     int                        NumVertexes  = NumPrimitives;
933     const short               *pIdxBufS     = NULL;
934     const long                *pIdxBufL     = NULL;
935     LONG                       SkipnStrides = 0;
936     LONG                       vx_index;
937     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
938     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
939     float rhw = 0.0f;                      /* rhw                        */
940     float ptSize = 0.0f;                   /* Point size                 */
941     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
942     DWORD specularColor = 0;               /* Specular Color             */
943     ICOM_THIS(IDirect3DDevice8Impl,iface);
944
945     TRACE("Using slow vertex array code\n");
946
947     /* Variable Initialization */
948     if (idxData != NULL) {
949         if (idxSize == 2) pIdxBufS = (short *) idxData;
950         else pIdxBufL = (long *) idxData;
951     }
952
953     /* Ok, Work out which primitive is requested and how many vertexes that will be */
954     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
955
956     /* Start drawing in GL */
957     VTRACE(("glBegin(%x)\n", glPrimType));
958     glBegin(glPrimType);
959
960     /* For each primitive */
961     for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
962
963         /* Initialize diffuse color */
964         diffuseColor = 0xFFFFFFFF;
965
966         /* For indexed data, we need to go a few more strides in */
967         if (idxData != NULL) {
968
969             /* Indexed so work out the number of strides to skip */
970             if (idxSize == 2) {
971                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
972                 SkipnStrides = pIdxBufS[startIdx+vx_index];
973             } else {
974                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
975                 SkipnStrides = pIdxBufL[startIdx+vx_index];
976             }
977         }
978
979         /* Position Information ------------------ */
980         if (sd->u.s.position.lpData != NULL) {
981
982             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
983             x = ptrToCoords[0];
984             y = ptrToCoords[1];
985             z = ptrToCoords[2];
986             rhw = 1.0;
987             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
988
989             /* RHW follows, only if transformed, ie 4 floats were provided */
990             if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
991                 rhw = ptrToCoords[3];
992                 VTRACE(("rhw=%f\n", rhw));
993             }
994         }
995
996         /* Blending data -------------------------- */
997         if (sd->u.s.blendWeights.lpData != NULL) {
998             /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
999             FIXME("Blending not supported yet\n");
1000
1001             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1002                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1003             }
1004         }
1005
1006         /* Vertex Normal Data (untransformed only)- */
1007         if (sd->u.s.normal.lpData != NULL) {
1008
1009             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1010             nx = ptrToCoords[0];
1011             ny = ptrToCoords[1];
1012             nz = ptrToCoords[2];
1013             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1014         }
1015
1016         /* Point Size ----------------------------- */
1017         if (sd->u.s.pSize.lpData != NULL) {
1018
1019             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1020             ptSize = ptrToCoords[0];
1021             VTRACE(("ptSize=%f\n", ptSize));
1022             FIXME("No support for ptSize yet\n");
1023         }
1024
1025         /* Diffuse -------------------------------- */
1026         if (sd->u.s.diffuse.lpData != NULL) {
1027
1028             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1029             diffuseColor = ptrToCoords[0];
1030             VTRACE(("diffuseColor=%lx\n", diffuseColor));
1031         }
1032
1033         /* Specular  -------------------------------- */
1034         if (sd->u.s.specular.lpData != NULL) {
1035
1036             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1037             specularColor = ptrToCoords[0];
1038             VTRACE(("specularColor=%lx\n", specularColor));
1039         }
1040
1041         /* Texture coords --------------------------- */
1042         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1043
1044             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1045                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1046                 continue ;
1047             }
1048
1049             /* Query tex coords */
1050             if (This->StateBlock->textures[textureNo] != NULL) {
1051
1052                 int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
1053                 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1054                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1055
1056                 if (coordIdx > 7) {
1057                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1058                     continue;
1059                 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1060                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1061                     continue;
1062                 } else {
1063
1064                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
1065
1066                     /* The coords to supply depend completely on the fvf / vertex shader */
1067                     switch (coordsToUse) {
1068                     case 4: q = ptrToCoords[3]; /* drop through */
1069                     case 3: r = ptrToCoords[2]; /* drop through */
1070                     case 2: t = ptrToCoords[1]; /* drop through */
1071                     case 1: s = ptrToCoords[0]; 
1072                     }
1073
1074                     /* Projected is more 'fun' - Move the last coord to the 'q'
1075                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1076                     if ((This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1077                         (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1078
1079                         if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1080                             switch (coordsToUse) {
1081                             case 0:  /* Drop Through */
1082                             case 1:
1083                                 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1084                                 break;
1085                             case 2:
1086                                 q = t;
1087                                 t = 0.0;
1088                                 coordsToUse = 4;
1089                                 break;
1090                             case 3:
1091                                 q = r;
1092                                 r = 0.0;
1093                                 coordsToUse = 4;
1094                                 break;
1095                             case 4:  /* Nop here */
1096                                 break;
1097                             default:
1098                                 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", 
1099                                       This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1100                             }
1101                         }
1102                     }
1103
1104                     switch (coordsToUse) {   /* Supply the provided texture coords */
1105                     case D3DTTFF_COUNT1:
1106                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1107                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1108 #if defined(GL_VERSION_1_3)
1109                             glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1110 #else
1111                             glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1112 #endif
1113                         } else {
1114                             glTexCoord1f(s);
1115                         }
1116                         break;
1117                     case D3DTTFF_COUNT2:
1118                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1119                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1120 #if defined(GL_VERSION_1_3)
1121                             glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1122 #else
1123                             glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1124 #endif
1125                         } else {
1126                             glTexCoord2f(s, t);
1127                         }
1128                         break;
1129                     case D3DTTFF_COUNT3:
1130                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1131                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1132 #if defined(GL_VERSION_1_3)
1133                             glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1134 #else
1135                             glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1136 #endif
1137                         } else {
1138                             glTexCoord3f(s, t, r);
1139                         }
1140                         break;
1141                     case D3DTTFF_COUNT4:
1142                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1143                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1144 #if defined(GL_VERSION_1_3)
1145                             glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1146 #else
1147                             glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1148 #endif
1149                         } else {
1150                             glTexCoord4f(s, t, r, q);
1151                         }
1152                         break;
1153                     default:
1154                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1155                     }
1156                 }
1157             }
1158         } /* End of textures */
1159
1160         /* Diffuse -------------------------------- */
1161         if (sd->u.s.diffuse.lpData != NULL) {
1162             glColor4ub((diffuseColor >> 16) & 0xFF,
1163                        (diffuseColor >>  8) & 0xFF,
1164                        (diffuseColor >>  0) & 0xFF,
1165                        (diffuseColor >> 24) & 0xFF);
1166             VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
1167                     ((diffuseColor >> 16) & 0xFF) / 255.0f, 
1168                     ((diffuseColor >>  8) & 0xFF) / 255.0f,
1169                     ((diffuseColor >>  0) & 0xFF) / 255.0f, 
1170                     ((diffuseColor >> 24) & 0xFF) / 255.0f));
1171         } else {
1172             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1173         }
1174
1175         /* Specular ------------------------------- */
1176         if (sd->u.s.diffuse.lpData != NULL) {
1177             VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n", 
1178                     ((specularColor >> 16) & 0xFF) / 255.0f, 
1179                     ((specularColor >>  8) & 0xFF) / 255.0f,
1180                     ((specularColor >>  0) & 0xFF) / 255.0f));
1181             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1182                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1183                            (specularColor >> 16) & 0xFF,
1184                            (specularColor >>  8) & 0xFF,
1185                            (specularColor >>  0) & 0xFF);
1186             } else {
1187               /* Do not worry if specular colour missing and disable request */
1188               VTRACE(("Specular color extensions not supplied\n"));
1189             }
1190         } else {
1191             if (vx_index == 0) {
1192               if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1193                 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1194               } else {
1195                 /* Do not worry if specular colour missing and disable request */
1196                 VTRACE(("Specular color extensions not supplied\n"));
1197               }
1198             } 
1199         }
1200
1201         /* Normal -------------------------------- */
1202         if (sd->u.s.normal.lpData != NULL) {
1203             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1204             glNormal3f(nx, ny, nz);
1205         } else {
1206             if (vx_index == 0) glNormal3f(0, 0, 1);
1207         }
1208         
1209         /* Position -------------------------------- */
1210         if (sd->u.s.position.lpData != NULL) {
1211             if (1.0f == rhw || rhw < 0.0001f) {
1212                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1213                 glVertex3f(x, y, z);
1214             } else {
1215                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1216                 /* Disable RHW mode as 'w' coord handling for rhw mode should
1217                    not impact screen position whereas in GL it does. This may 
1218                    result in very slightly distored textures in rhw mode, but
1219                    a very minimal different. In slow mode a possible 'fix' is
1220                    glVertex4f(x*rhw,y*rhw,z*rhw,rhw) but not sure this is right */
1221                 glVertex3f(x,y,z);
1222             }
1223         }
1224
1225         /* For non indexed mode, step onto next parts */
1226         if (idxData == NULL) {
1227             SkipnStrides += 1;
1228         }
1229     }
1230
1231     glEnd();
1232     checkGLcall("glEnd and previous calls");
1233 }
1234
1235 /* 
1236  * Draw with emulated vertex shaders
1237  * Note: strided data is uninitialized, as we need to pass the vertex
1238  *     shader directly as ordering irs yet                             
1239  */
1240 void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
1241                      int PrimitiveType, ULONG NumPrimitives,
1242                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1243
1244     int                        textureNo    = 0;
1245     GLenum                     glPrimType   = GL_POINTS;
1246     int                        NumVertexes  = NumPrimitives;
1247     const short               *pIdxBufS     = NULL;
1248     const long                *pIdxBufL     = NULL;
1249     LONG                       SkipnStrides = 0;
1250     LONG                       vx_index;
1251     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1252     float rhw = 0.0f;                      /* rhw                        */
1253     float ptSize = 0.0f;                   /* Point size                 */
1254     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1255     int   numcoords[8];                    /* Number of coords           */
1256     ICOM_THIS(IDirect3DDevice8Impl,iface);
1257
1258     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1259
1260     TRACE("Using slow software vertex shader code\n");
1261
1262     /* Variable Initialization */
1263     if (idxData != NULL) {
1264         if (idxSize == 2) pIdxBufS = (short *) idxData;
1265         else pIdxBufL = (long *) idxData;
1266     }
1267
1268     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1269     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1270
1271     /* Retrieve the VS information */
1272     vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1273
1274     /* Start drawing in GL */
1275     VTRACE(("glBegin(%x)\n", glPrimType));
1276     glBegin(glPrimType);
1277
1278     /* For each primitive */
1279     for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1280
1281         /* For indexed data, we need to go a few more strides in */
1282         if (idxData != NULL) {
1283
1284             /* Indexed so work out the number of strides to skip */
1285             if (idxSize == 2) {
1286                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1287                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1288             } else {
1289                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1290                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1291             }
1292         }
1293
1294         /* Fill the vertex shader input */
1295         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1296
1297         /* Initialize the output fields to the same defaults as it would normally have */
1298         memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1299         vertex_shader->output.oD[0].x = 1.0;
1300         vertex_shader->output.oD[0].y = 1.0;
1301         vertex_shader->output.oD[0].z = 1.0;
1302         vertex_shader->output.oD[0].w = 1.0; 
1303
1304         /* Now execute the vertex shader */
1305         IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1306
1307         /*
1308         TRACE_VECTOR(vertex_shader->output.oPos);
1309         TRACE_VECTOR(vertex_shader->output.oD[0]);
1310         TRACE_VECTOR(vertex_shader->output.oD[1]);
1311         TRACE_VECTOR(vertex_shader->output.oT[0]);
1312         TRACE_VECTOR(vertex_shader->output.oT[1]);
1313         TRACE_VECTOR(vertex_shader->input.V[0]);
1314         TRACE_VECTOR(vertex_shader->data->C[0]);
1315         TRACE_VECTOR(vertex_shader->data->C[1]);
1316         TRACE_VECTOR(vertex_shader->data->C[2]);
1317         TRACE_VECTOR(vertex_shader->data->C[3]);
1318         TRACE_VECTOR(vertex_shader->data->C[4]);
1319         TRACE_VECTOR(vertex_shader->data->C[5]);
1320         TRACE_VECTOR(vertex_shader->data->C[6]);
1321         TRACE_VECTOR(vertex_shader->data->C[7]);
1322         */
1323
1324         /* Extract out the output */
1325         /*FIXME: Fog coords? */
1326         x = vertex_shader->output.oPos.x;
1327         y = vertex_shader->output.oPos.y;
1328         z = vertex_shader->output.oPos.z;
1329         rhw = vertex_shader->output.oPos.w;
1330         ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1331
1332         /** Update textures coords using vertex_shader->output.oT[0->7] */
1333         memset(texcoords, 0x00, sizeof(texcoords));
1334         memset(numcoords, 0x00, sizeof(numcoords));
1335         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1336             if (This->StateBlock->textures[textureNo] != NULL) {
1337                texcoords[textureNo].x   = vertex_shader->output.oT[textureNo].x;
1338                texcoords[textureNo].y   = vertex_shader->output.oT[textureNo].y;
1339                texcoords[textureNo].z   = vertex_shader->output.oT[textureNo].z;
1340                texcoords[textureNo].w   = vertex_shader->output.oT[textureNo].w;
1341                if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1342                    numcoords[textureNo]    = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1343                } else {
1344                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
1345                    case D3DRTYPE_TEXTURE:       numcoords[textureNo]    = 2; break;
1346                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo]    = 3; break;
1347                    default:                     numcoords[textureNo]    = 4;
1348                    }
1349                }
1350             } else {
1351                 numcoords[textureNo]    = 0;
1352             }
1353         }
1354
1355         /* Draw using this information */
1356         draw_vertex(iface,
1357                     TRUE, x, y, z, rhw, 
1358                     TRUE, 0.0f, 0.0f, 1.0f, 
1359                     TRUE, (float*) &vertex_shader->output.oD[0],  
1360                     TRUE, (float*) &vertex_shader->output.oD[1],  
1361                     FALSE, ptSize,         /* FIXME: Change back when supported */
1362                     texcoords, numcoords);
1363
1364         /* For non indexed mode, step onto next parts */
1365         if (idxData == NULL) {
1366             SkipnStrides += 1;
1367         }
1368
1369     } /* for each vertex */
1370
1371     glEnd();
1372     checkGLcall("glEnd and previous calls");
1373 }
1374
1375 void drawStridedHardwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
1376                      int PrimitiveType, ULONG NumPrimitives,
1377                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1378
1379     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1380     int                        i;
1381     int                        NumVertexes;
1382     int                        glPrimType;
1383     int                        maxAttribs;
1384
1385     ICOM_THIS(IDirect3DDevice8Impl,iface);
1386     TRACE("Drawing with hardware vertex shaders\n");
1387
1388     /* Retrieve the VS information */
1389     vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1390
1391     /* Enable the Vertex Shader */
1392     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1393     checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1394     glEnable(GL_VERTEX_PROGRAM_ARB);
1395     checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1396
1397     /* Update the constants */
1398     for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1399         GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->StateBlock->vertexShaderConstant[i]));
1400         checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1401     }
1402
1403     /* Set up the vertex.attr[n] inputs */
1404     IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1405
1406     /* Ok, Work out which primitive is requested and how many vertexes that 
1407        will be                                                              */
1408     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1409
1410     /* Finally do the drawing */
1411     if (idxData != NULL) {
1412
1413         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1414 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1415         glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1416                       (char *)idxData+(idxSize * startIdx));
1417 #else
1418         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
1419                       idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT, 
1420                       (char *)idxData+(idxSize * startIdx));
1421 #endif
1422         checkGLcall("glDrawRangeElements");
1423
1424     } else {
1425
1426         /* Note first is now zero as we shuffled along earlier */
1427         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1428         glDrawArrays(glPrimType, 0, NumVertexes);
1429         checkGLcall("glDrawArrays");
1430
1431     }
1432     
1433     {
1434     GLint errPos;
1435     glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1436     if (errPos != -1)
1437         FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1438     }
1439
1440
1441     /* Leave all the attribs disabled */
1442     glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1443     /* MESA does not support it right not */
1444     if (glGetError() != GL_NO_ERROR)
1445         maxAttribs = 16;
1446     for (i=0; i<maxAttribs; i++) {
1447         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1448         checkGLcall("glDisableVertexAttribArrayARB(reg);");
1449     }
1450
1451     /* Done */
1452     glDisable(GL_VERTEX_PROGRAM_ARB);
1453 }
1454
1455 /* Routine common to the draw primitive and draw indexed primitive routines */
1456 void drawPrimitive(LPDIRECT3DDEVICE8 iface,
1457                     int PrimitiveType, long NumPrimitives,
1458
1459                     /* for Indexed: */
1460                     long  StartVertexIndex,
1461                     long  StartIdx,
1462                     short idxSize,
1463                     const void *idxData,
1464                     int   minIndex) {
1465
1466     BOOL                          rc = FALSE;
1467     DWORD                         fvf = 0;
1468     IDirect3DVertexShaderImpl    *vertex_shader = NULL;
1469     BOOL                          useVertexShaderFunction = FALSE;
1470     BOOL                          isLightingOn = FALSE;
1471     Direct3DVertexStridedData     dataLocations;
1472     ICOM_THIS(IDirect3DDevice8Impl,iface);
1473     int                           i;
1474     int                           useHW = FALSE;
1475
1476     /* Work out what the FVF should look like */
1477     rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1478     if (rc) return;
1479
1480     /* If we will be using a vertex shader, do some initialization for it */
1481     if (useVertexShaderFunction == TRUE) {
1482         vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
1483         memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1484
1485         useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1486                  This->devType != D3DDEVTYPE_REF &&
1487                  !This->StateBlock->renderstate[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1488                  vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1489
1490         /** init Constants */
1491         if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
1492             TRACE_(d3d_shader)("vertex shader initializing constants\n");
1493             IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
1494         }
1495     }
1496
1497     /* Ok, we will be updating the screen from here onwards so grab the lock */
1498     ENTER_GL();
1499
1500     /* Setup transform matrices and sort out */
1501     if (useHW) {
1502         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1503            So make sure lighting is disabled. */
1504         isLightingOn = glIsEnabled(GL_LIGHTING);
1505         glDisable(GL_LIGHTING);
1506         checkGLcall("glDisable(GL_LIGHTING);");
1507         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn); 
1508     } else
1509         isLightingOn = primitiveInitState(iface, 
1510                                           fvf & D3DFVF_XYZRHW, 
1511                                           !(fvf & D3DFVF_NORMAL),
1512                                           useVertexShaderFunction);
1513
1514     /* Initialize all values to null */
1515     if (useVertexShaderFunction == FALSE) {
1516         memset(&dataLocations, 0x00, sizeof(dataLocations));
1517
1518         /* Convert to strided data */
1519         primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex); 
1520
1521         /* Dump out what parts we have supplied */
1522         TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1523         TRACE_STRIDED((&dataLocations), position);
1524         TRACE_STRIDED((&dataLocations), blendWeights);
1525         TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1526         TRACE_STRIDED((&dataLocations), normal);
1527         TRACE_STRIDED((&dataLocations), pSize);
1528         TRACE_STRIDED((&dataLocations), diffuse);
1529         TRACE_STRIDED((&dataLocations), specular);
1530         TRACE_STRIDED((&dataLocations), texCoords[0]);
1531         TRACE_STRIDED((&dataLocations), texCoords[1]);
1532         TRACE_STRIDED((&dataLocations), texCoords[2]);
1533         TRACE_STRIDED((&dataLocations), texCoords[3]);
1534         TRACE_STRIDED((&dataLocations), texCoords[4]);
1535         TRACE_STRIDED((&dataLocations), texCoords[5]);
1536         TRACE_STRIDED((&dataLocations), texCoords[6]);
1537         TRACE_STRIDED((&dataLocations), texCoords[7]);
1538     }
1539
1540     /* Now initialize the materials state */
1541     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1542
1543     /* And re-upload any dirty textures */
1544     for (i=0; i<GL_LIMITS(textures); i++) {
1545         
1546         if ((This->StateBlock->textures[i] != NULL) && 
1547             (IDirect3DBaseTexture8Impl_IsDirty(This->StateBlock->textures[i])))
1548         {
1549             /* Load up the texture now */
1550             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) This->StateBlock->textures[i]);
1551         }
1552     }
1553
1554     /* Now draw the graphics to the screen */
1555     if  (useVertexShaderFunction == TRUE) {
1556
1557         /* Ideally, we should have software FV and hardware VS, possibly
1558            depending on the device type?                                 */
1559
1560         if (useHW) {
1561             TRACE("Swap HW vertex shader\n");
1562             drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1563                         idxData, idxSize, minIndex, StartIdx);            
1564         } else {
1565             /* We will have to use the very, very slow emulation layer */
1566             TRACE("Swap SW vertex shader\n");
1567             drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1568                         idxData, idxSize, minIndex, StartIdx);            
1569         }
1570
1571     } else if ((dataLocations.u.s.pSize.lpData        != NULL) || 
1572                (dataLocations.u.s.diffuse.lpData      != NULL) || 
1573                (dataLocations.u.s.blendWeights.lpData != NULL)) {
1574
1575         /* Fixme, Ideally, only use the per-vertex code for software HAL 
1576            but until opengl supports all the functions returned to setup 
1577            vertex arrays, we need to drop down to the slow mechanism for  
1578            certain functions                                              */
1579
1580         /* We will have to use the slow version of GL per vertex setup */
1581         drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1582                         idxData, idxSize, minIndex, StartIdx); 
1583
1584     } else {
1585
1586         /* We can use the fast version of GL pointers */
1587         drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1588                         idxData, idxSize, minIndex, StartIdx);
1589     }
1590
1591     /* If vertex shaders or no normals, restore previous lighting state */
1592     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1593         if (isLightingOn) glEnable(GL_LIGHTING);
1594         else glDisable(GL_LIGHTING);
1595         TRACE("Restored lighting to original state\n");
1596     }
1597
1598     /* Finshed updating the screen, restore lock */
1599     LEAVE_GL();
1600     TRACE("Done all gl drawing\n");
1601
1602     /* Diagnostics */
1603 #if defined(SHOW_FRAME_MAKEUP)
1604     {
1605         if (isDumpingFrames == TRUE) {
1606             D3DLOCKED_RECT r;
1607             char buffer[80];
1608             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1609             sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1610             TRACE("Saving screenshot %s\n", buffer);
1611             IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1612             IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1613
1614 #if defined(SHOW_TEXTURE_MAKEUP)
1615            {
1616             LPDIRECT3DSURFACE8 pSur;
1617             int textureNo;
1618             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1619                 if (This->StateBlock->textures[textureNo] != NULL) {
1620                     sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1621                     TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->StateBlock->textures[textureNo])->format));
1622                     IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->StateBlock->textures[textureNo], 0, &pSur);
1623                     IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1624                     IDirect3DSurface8Impl_Release(pSur);
1625                 }
1626             }
1627            }
1628 #endif
1629            primCounter = primCounter + 1; 
1630         }
1631     }
1632 #endif
1633 }