Assorted spelling fixes.
[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 defined(GL_EXT_secondary_color)
537         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
538           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
539           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
540         }
541 #endif
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 defined(GL_VERSION_1_4)
798         glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, 
799                                    sd->u.s.specular.dwStride, 
800                                    sd->u.s.specular.lpData);
801         vcheckGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, ...)");
802         glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
803         vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
804 #elif defined(GL_EXT_secondary_color)
805         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
806             GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
807                                                    sd->u.s.specular.dwStride, 
808                                                    sd->u.s.specular.lpData);
809             checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
810             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
811             checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
812         }
813 #else
814         /* Missing specular color is not critical, no warnings */
815         VTRACE(("Specular colour is not supported in this GL implementation\n"));
816 #endif
817
818     } else {
819
820 #if defined(GL_VERSION_1_4)
821         glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
822         checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
823         glSecondaryColor3f(0, 0, 0);
824         checkGLcall("glSecondaryColor3f(0, 0, 0)");
825 #elif defined(GL_EXT_secondary_color)
826         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
827               glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
828             checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
829             GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
830             checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
831         }
832 #else
833         /* Do not worry if specular colour missing and disable request */
834 #endif
835     }
836
837     /* Texture coords -------------------------------------------*/
838     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
839
840         /* Select the correct texture stage */
841 #if defined(GL_VERSION_1_3)
842         glClientActiveTexture(GL_TEXTURE0 + textureNo);
843 #else
844         glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
845 #endif
846
847         /* Query tex coords */
848         if (This->StateBlock->textures[textureNo] != NULL) {
849             int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
850
851             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
852                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
853                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
854 #if defined(GL_VERSION_1_3)
855                 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
856 #else
857                 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
858 #endif
859                 continue;
860             }
861
862             if (coordIdx > 7) {
863                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
864                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
865 #if defined(GL_VERSION_1_3)
866                 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
867 #else
868                 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
869 #endif
870             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
871                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
872                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
873 #if defined(GL_VERSION_1_3)
874                 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
875 #else
876                 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
877 #endif
878             } else {
879
880                 /* The coords to supply depend completely on the fvf / vertex shader */
881                 GLint size;
882                 GLenum type;
883
884                 switch (sd->u.s.texCoords[coordIdx].dwType) {
885                 case D3DVSDT_FLOAT1: size = 1, type = GL_FLOAT; break;
886                 case D3DVSDT_FLOAT2: size = 2, type = GL_FLOAT; break;
887                 case D3DVSDT_FLOAT3: size = 3, type = GL_FLOAT; break;
888                 case D3DVSDT_FLOAT4: size = 4, type = GL_FLOAT; break;
889                 case D3DVSDT_SHORT2: size = 2, type = GL_SHORT; break;
890                 case D3DVSDT_SHORT4: size = 4, type = GL_SHORT; break;
891                 case D3DVSDT_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
892                 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
893                       size = 4; type = GL_UNSIGNED_BYTE;
894                 }
895
896                 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
897                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
898             }
899         } else {
900             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
901 #if defined(GL_VERSION_1_3)
902             glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
903 #else
904             glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
905 #endif
906         }
907     } 
908
909     /* Ok, Work out which primitive is requested and how many vertexes that 
910        will be                                                              */
911     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
912
913     /* Finally do the drawing */
914     if (idxData != NULL) {
915
916         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
917 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
918         glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
919                       (char *)idxData+(idxSize * startIdx));
920 #else
921         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
922                       idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT, 
923                       (char *)idxData+(idxSize * startIdx));
924 #endif
925         checkGLcall("glDrawRangeElements");
926
927     } else {
928
929         /* Note first is now zero as we shuffled along earlier */
930         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
931         glDrawArrays(glPrimType, 0, NumVertexes);
932         checkGLcall("glDrawArrays");
933
934     }
935 }
936
937 /* 
938  * Actually draw using the supplied information.
939  * Slower GL version which extracts info about each vertex in turn
940  */
941 void drawStridedSlow(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
942                      int PrimitiveType, ULONG NumPrimitives,
943                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
944
945     int                        textureNo    = 0;
946     GLenum                     glPrimType   = GL_POINTS;
947     int                        NumVertexes  = NumPrimitives;
948     const short               *pIdxBufS     = NULL;
949     const long                *pIdxBufL     = NULL;
950     LONG                       SkipnStrides = 0;
951     LONG                       vx_index;
952     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
953     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
954     float rhw = 0.0f;                      /* rhw                        */
955     float ptSize = 0.0f;                   /* Point size                 */
956     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
957     DWORD specularColor = 0;               /* Specular Color             */
958     ICOM_THIS(IDirect3DDevice8Impl,iface);
959
960     TRACE("Using slow vertex array code\n");
961
962     /* Variable Initialization */
963     if (idxData != NULL) {
964         if (idxSize == 2) pIdxBufS = (short *) idxData;
965         else pIdxBufL = (long *) idxData;
966     }
967
968     /* Ok, Work out which primitive is requested and how many vertexes that will be */
969     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
970
971     /* Start drawing in GL */
972     VTRACE(("glBegin(%x)\n", glPrimType));
973     glBegin(glPrimType);
974
975     /* For each primitive */
976     for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
977
978         /* Initialize diffuse color */
979         diffuseColor = 0xFFFFFFFF;
980
981         /* For indexed data, we need to go a few more strides in */
982         if (idxData != NULL) {
983
984             /* Indexed so work out the number of strides to skip */
985             if (idxSize == 2) {
986                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
987                 SkipnStrides = pIdxBufS[startIdx+vx_index];
988             } else {
989                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
990                 SkipnStrides = pIdxBufL[startIdx+vx_index];
991             }
992         }
993
994         /* Position Information ------------------ */
995         if (sd->u.s.position.lpData != NULL) {
996
997             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
998             x = ptrToCoords[0];
999             y = ptrToCoords[1];
1000             z = ptrToCoords[2];
1001             rhw = 1.0;
1002             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1003
1004             /* RHW follows, only if transformed, ie 4 floats were provided */
1005             if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
1006                 rhw = ptrToCoords[3];
1007                 VTRACE(("rhw=%f\n", rhw));
1008             }
1009         }
1010
1011         /* Blending data -------------------------- */
1012         if (sd->u.s.blendWeights.lpData != NULL) {
1013             /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1014             FIXME("Blending not supported yet\n");
1015
1016             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1017                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1018             }
1019         }
1020
1021         /* Vertex Normal Data (untransformed only)- */
1022         if (sd->u.s.normal.lpData != NULL) {
1023
1024             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1025             nx = ptrToCoords[0];
1026             ny = ptrToCoords[1];
1027             nz = ptrToCoords[2];
1028             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1029         }
1030
1031         /* Point Size ----------------------------- */
1032         if (sd->u.s.pSize.lpData != NULL) {
1033
1034             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1035             ptSize = ptrToCoords[0];
1036             VTRACE(("ptSize=%f\n", ptSize));
1037             FIXME("No support for ptSize yet\n");
1038         }
1039
1040         /* Diffuse -------------------------------- */
1041         if (sd->u.s.diffuse.lpData != NULL) {
1042
1043             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1044             diffuseColor = ptrToCoords[0];
1045             VTRACE(("diffuseColor=%lx\n", diffuseColor));
1046         }
1047
1048         /* Specular  -------------------------------- */
1049         if (sd->u.s.specular.lpData != NULL) {
1050
1051             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1052             specularColor = ptrToCoords[0];
1053             VTRACE(("specularColor=%lx\n", specularColor));
1054         }
1055
1056         /* Texture coords --------------------------- */
1057         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1058
1059             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1060                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1061                 continue ;
1062             }
1063
1064             /* Query tex coords */
1065             if (This->StateBlock->textures[textureNo] != NULL) {
1066
1067                 int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
1068                 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1069                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1070
1071                 if (coordIdx > 7) {
1072                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1073                     continue;
1074                 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1075                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1076                     continue;
1077                 } else {
1078
1079                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
1080
1081                     /* The coords to supply depend completely on the fvf / vertex shader */
1082                     switch (coordsToUse) {
1083                     case 4: q = ptrToCoords[3]; /* drop through */
1084                     case 3: r = ptrToCoords[2]; /* drop through */
1085                     case 2: t = ptrToCoords[1]; /* drop through */
1086                     case 1: s = ptrToCoords[0]; 
1087                     }
1088
1089                     /* Projected is more 'fun' - Move the last coord to the 'q'
1090                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1091                     if ((This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1092                         (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1093
1094                         if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1095                             switch (coordsToUse) {
1096                             case 0:  /* Drop Through */
1097                             case 1:
1098                                 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1099                                 break;
1100                             case 2:
1101                                 q = t;
1102                                 t = 0.0;
1103                                 coordsToUse = 4;
1104                                 break;
1105                             case 3:
1106                                 q = r;
1107                                 r = 0.0;
1108                                 coordsToUse = 4;
1109                                 break;
1110                             case 4:  /* Nop here */
1111                                 break;
1112                             default:
1113                                 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", 
1114                                       This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1115                             }
1116                         }
1117                     }
1118
1119                     switch (coordsToUse) {   /* Supply the provided texture coords */
1120                     case D3DTTFF_COUNT1:
1121                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1122                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1123 #if defined(GL_VERSION_1_3)
1124                             glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1125 #else
1126                             glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1127 #endif
1128                         } else {
1129                             glTexCoord1f(s);
1130                         }
1131                         break;
1132                     case D3DTTFF_COUNT2:
1133                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1134                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1135 #if defined(GL_VERSION_1_3)
1136                             glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1137 #else
1138                             glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1139 #endif
1140                         } else {
1141                             glTexCoord2f(s, t);
1142                         }
1143                         break;
1144                     case D3DTTFF_COUNT3:
1145                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1146                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1147 #if defined(GL_VERSION_1_3)
1148                             glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1149 #else
1150                             glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1151 #endif
1152                         } else {
1153                             glTexCoord3f(s, t, r);
1154                         }
1155                         break;
1156                     case D3DTTFF_COUNT4:
1157                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1158                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1159 #if defined(GL_VERSION_1_3)
1160                             glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1161 #else
1162                             glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1163 #endif
1164                         } else {
1165                             glTexCoord4f(s, t, r, q);
1166                         }
1167                         break;
1168                     default:
1169                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1170                     }
1171                 }
1172             }
1173         } /* End of textures */
1174
1175         /* Diffuse -------------------------------- */
1176         if (sd->u.s.diffuse.lpData != NULL) {
1177             glColor4ub((diffuseColor >> 16) & 0xFF,
1178                        (diffuseColor >>  8) & 0xFF,
1179                        (diffuseColor >>  0) & 0xFF,
1180                        (diffuseColor >> 24) & 0xFF);
1181             VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
1182                     ((diffuseColor >> 16) & 0xFF) / 255.0f, 
1183                     ((diffuseColor >>  8) & 0xFF) / 255.0f,
1184                     ((diffuseColor >>  0) & 0xFF) / 255.0f, 
1185                     ((diffuseColor >> 24) & 0xFF) / 255.0f));
1186         } else {
1187             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1188         }
1189
1190 #if 1
1191         /* Specular ------------------------------- */
1192         if (sd->u.s.diffuse.lpData != NULL) {
1193             VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n", 
1194                     ((specularColor >> 16) & 0xFF) / 255.0f, 
1195                     ((specularColor >>  8) & 0xFF) / 255.0f,
1196                     ((specularColor >>  0) & 0xFF) / 255.0f));
1197 #if defined(GL_VERSION_1_4)
1198             glSecondaryColor3ub((specularColor >> 16) & 0xFF,
1199                                 (specularColor >>  8) & 0xFF,
1200                                 (specularColor >>  0) & 0xFF);
1201 #elif defined(GL_EXT_secondary_color)
1202             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1203                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1204                            (specularColor >> 16) & 0xFF,
1205                            (specularColor >>  8) & 0xFF,
1206                            (specularColor >>  0) & 0xFF);
1207             }
1208 #else
1209             /* Do not worry if specular colour missing and disable request */
1210             VTRACE(("Specular color extensions not supplied\n"));
1211 #endif
1212         } else {
1213 #if defined(GL_VERSION_1_4)
1214             if (vx_index == 0) glSecondaryColor3f(0, 0, 0);
1215 #elif defined(GL_EXT_secondary_color)
1216             if (vx_index == 0 && GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1217                 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1218             }
1219 #else
1220             /* Do not worry if specular colour missing and disable request */
1221 #endif
1222         }
1223 #endif
1224
1225         /* Normal -------------------------------- */
1226         if (sd->u.s.normal.lpData != NULL) {
1227             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1228             glNormal3f(nx, ny, nz);
1229         } else {
1230             if (vx_index == 0) glNormal3f(0, 0, 1);
1231         }
1232         
1233         /* Position -------------------------------- */
1234         if (sd->u.s.position.lpData != NULL) {
1235             if (1.0f == rhw || rhw < 0.0001f) {
1236                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1237                 glVertex3f(x, y, z);
1238             } else {
1239                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1240                 /* Disable RHW mode as 'w' coord handling for rhw mode should
1241                    not impact screen position whereas in GL it does. This may 
1242                    result in very slightly distored textures in rhw mode, but
1243                    a very minimal different. In slow mode a possible 'fix' is
1244                    glVertex4f(x*rhw,y*rhw,z*rhw,rhw) but not sure this is right */
1245                 glVertex3f(x,y,z);
1246             }
1247         }
1248
1249         /* For non indexed mode, step onto next parts */
1250         if (idxData == NULL) {
1251             SkipnStrides += 1;
1252         }
1253     }
1254
1255     glEnd();
1256     checkGLcall("glEnd and previous calls");
1257 }
1258
1259 /* 
1260  * Draw with emulated vertex shaders
1261  * Note: strided data is uninitialized, as we need to pass the vertex
1262  *     shader directly as ordering irs yet                             
1263  */
1264 void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
1265                      int PrimitiveType, ULONG NumPrimitives,
1266                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1267
1268     int                        textureNo    = 0;
1269     GLenum                     glPrimType   = GL_POINTS;
1270     int                        NumVertexes  = NumPrimitives;
1271     const short               *pIdxBufS     = NULL;
1272     const long                *pIdxBufL     = NULL;
1273     LONG                       SkipnStrides = 0;
1274     LONG                       vx_index;
1275     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1276     float rhw = 0.0f;                      /* rhw                        */
1277     float ptSize = 0.0f;                   /* Point size                 */
1278     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1279     int   numcoords[8];                    /* Number of coords           */
1280     ICOM_THIS(IDirect3DDevice8Impl,iface);
1281
1282     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1283
1284     TRACE("Using slow software vertex shader code\n");
1285
1286     /* Variable Initialization */
1287     if (idxData != NULL) {
1288         if (idxSize == 2) pIdxBufS = (short *) idxData;
1289         else pIdxBufL = (long *) idxData;
1290     }
1291
1292     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1293     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1294
1295     /* Retrieve the VS information */
1296     vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1297
1298     /* Start drawing in GL */
1299     VTRACE(("glBegin(%x)\n", glPrimType));
1300     glBegin(glPrimType);
1301
1302     /* For each primitive */
1303     for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1304
1305         /* For indexed data, we need to go a few more strides in */
1306         if (idxData != NULL) {
1307
1308             /* Indexed so work out the number of strides to skip */
1309             if (idxSize == 2) {
1310                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1311                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1312             } else {
1313                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1314                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1315             }
1316         }
1317
1318         /* Fill the vertex shader input */
1319         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1320
1321         /* Initialize the output fields to the same defaults as it would normally have */
1322         memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1323         vertex_shader->output.oD[0].x = 1.0;
1324         vertex_shader->output.oD[0].y = 1.0;
1325         vertex_shader->output.oD[0].z = 1.0;
1326         vertex_shader->output.oD[0].w = 1.0; 
1327
1328         /* Now execute the vertex shader */
1329         IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1330
1331         /*
1332         TRACE_VECTOR(vertex_shader->output.oPos);
1333         TRACE_VECTOR(vertex_shader->output.oD[0]);
1334         TRACE_VECTOR(vertex_shader->output.oD[1]);
1335         TRACE_VECTOR(vertex_shader->output.oT[0]);
1336         TRACE_VECTOR(vertex_shader->output.oT[1]);
1337         TRACE_VECTOR(vertex_shader->input.V[0]);
1338         TRACE_VECTOR(vertex_shader->data->C[0]);
1339         TRACE_VECTOR(vertex_shader->data->C[1]);
1340         TRACE_VECTOR(vertex_shader->data->C[2]);
1341         TRACE_VECTOR(vertex_shader->data->C[3]);
1342         TRACE_VECTOR(vertex_shader->data->C[4]);
1343         TRACE_VECTOR(vertex_shader->data->C[5]);
1344         TRACE_VECTOR(vertex_shader->data->C[6]);
1345         TRACE_VECTOR(vertex_shader->data->C[7]);
1346         */
1347
1348         /* Extract out the output */
1349         /*FIXME: Fog coords? */
1350         x = vertex_shader->output.oPos.x;
1351         y = vertex_shader->output.oPos.y;
1352         z = vertex_shader->output.oPos.z;
1353         rhw = vertex_shader->output.oPos.w;
1354         ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1355
1356         /** Update textures coords using vertex_shader->output.oT[0->7] */
1357         memset(texcoords, 0x00, sizeof(texcoords));
1358         memset(numcoords, 0x00, sizeof(numcoords));
1359         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1360             if (This->StateBlock->textures[textureNo] != NULL) {
1361                texcoords[textureNo].x   = vertex_shader->output.oT[textureNo].x;
1362                texcoords[textureNo].y   = vertex_shader->output.oT[textureNo].y;
1363                texcoords[textureNo].z   = vertex_shader->output.oT[textureNo].z;
1364                texcoords[textureNo].w   = vertex_shader->output.oT[textureNo].w;
1365                if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1366                    numcoords[textureNo]    = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1367                } else {
1368                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
1369                    case D3DRTYPE_TEXTURE:       numcoords[textureNo]    = 2; break;
1370                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo]    = 3; break;
1371                    default:                     numcoords[textureNo]    = 4;
1372                    }
1373                }
1374             } else {
1375                 numcoords[textureNo]    = 0;
1376             }
1377         }
1378
1379         /* Draw using this information */
1380         draw_vertex(iface,
1381                     TRUE, x, y, z, rhw, 
1382                     TRUE, 0.0f, 0.0f, 1.0f, 
1383                     TRUE, (float*) &vertex_shader->output.oD[0],  
1384                     TRUE, (float*) &vertex_shader->output.oD[1],  
1385                     FALSE, ptSize,         /* FIXME: Change back when supported */
1386                     texcoords, numcoords);
1387
1388         /* For non indexed mode, step onto next parts */
1389         if (idxData == NULL) {
1390             SkipnStrides += 1;
1391         }
1392
1393     } /* for each vertex */
1394
1395     glEnd();
1396     checkGLcall("glEnd and previous calls");
1397 }
1398
1399 void drawStridedHardwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, 
1400                      int PrimitiveType, ULONG NumPrimitives,
1401                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1402
1403     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1404     int                        i;
1405     int                        NumVertexes;
1406     int                        glPrimType;
1407     int                        maxAttribs;
1408
1409     ICOM_THIS(IDirect3DDevice8Impl,iface);
1410     TRACE("Drawing with hardware vertex shaders\n");
1411
1412     /* Retrieve the VS information */
1413     vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1414
1415     /* Enable the Vertex Shader */
1416     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1417     checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1418     glEnable(GL_VERTEX_PROGRAM_ARB);
1419     checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1420
1421     /* Update the constants */
1422     for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1423         GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->StateBlock->vertexShaderConstant[i]));
1424         checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1425     }
1426
1427     /* Set up the vertex.attr[n] inputs */
1428     IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1429
1430     /* Ok, Work out which primitive is requested and how many vertexes that 
1431        will be                                                              */
1432     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1433
1434     /* Finally do the drawing */
1435     if (idxData != NULL) {
1436
1437         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1438 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1439         glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1440                       (char *)idxData+(idxSize * startIdx));
1441 #else
1442         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
1443                       idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT, 
1444                       (char *)idxData+(idxSize * startIdx));
1445 #endif
1446         checkGLcall("glDrawRangeElements");
1447
1448     } else {
1449
1450         /* Note first is now zero as we shuffled along earlier */
1451         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1452         glDrawArrays(glPrimType, 0, NumVertexes);
1453         checkGLcall("glDrawArrays");
1454
1455     }
1456     
1457     {
1458     GLint errPos;
1459     glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1460     if (errPos != -1)
1461         FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1462     }
1463
1464
1465     /* Leave all the attribs disabled */
1466     glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1467     /* MESA does not support it right not */
1468     if (glGetError() != GL_NO_ERROR)
1469         maxAttribs = 16;
1470     for (i=0; i<maxAttribs; i++) {
1471         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1472         checkGLcall("glDisableVertexAttribArrayARB(reg);");
1473     }
1474
1475     /* Done */
1476     glDisable(GL_VERTEX_PROGRAM_ARB);
1477 }
1478
1479 /* Routine common to the draw primitive and draw indexed primitive routines */
1480 void drawPrimitive(LPDIRECT3DDEVICE8 iface,
1481                     int PrimitiveType, long NumPrimitives,
1482
1483                     /* for Indexed: */
1484                     long  StartVertexIndex,
1485                     long  StartIdx,
1486                     short idxSize,
1487                     const void *idxData,
1488                     int   minIndex) {
1489
1490     BOOL                          rc = FALSE;
1491     DWORD                         fvf = 0;
1492     IDirect3DVertexShaderImpl    *vertex_shader = NULL;
1493     BOOL                          useVertexShaderFunction = FALSE;
1494     BOOL                          isLightingOn = FALSE;
1495     Direct3DVertexStridedData     dataLocations;
1496     ICOM_THIS(IDirect3DDevice8Impl,iface);
1497     int                           i;
1498     int                           useHW = FALSE;
1499
1500     /* Work out what the FVF should look like */
1501     rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1502     if (rc) return;
1503
1504     /* If we will be using a vertex shader, do some initialization for it */
1505     if (useVertexShaderFunction == TRUE) {
1506         vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
1507         memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1508
1509         useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1510                  This->devType != D3DDEVTYPE_REF &&
1511                  !This->StateBlock->renderstate[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1512                  vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1513
1514         /** init Constants */
1515         if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
1516             TRACE_(d3d_shader)("vertex shader initializing constants\n");
1517             IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
1518         }
1519     }
1520
1521     /* Ok, we will be updating the screen from here onwards so grab the lock */
1522     ENTER_GL();
1523
1524     /* Setup transform matrices and sort out */
1525     if (useHW) {
1526         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1527            So make sure lighting is disabled. */
1528         isLightingOn = glIsEnabled(GL_LIGHTING);
1529         glDisable(GL_LIGHTING);
1530         checkGLcall("glDisable(GL_LIGHTING);");
1531         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn); 
1532     } else
1533         isLightingOn = primitiveInitState(iface, 
1534                                           fvf & D3DFVF_XYZRHW, 
1535                                           !(fvf & D3DFVF_NORMAL),
1536                                           useVertexShaderFunction);
1537
1538     /* Initialize all values to null */
1539     if (useVertexShaderFunction == FALSE) {
1540         memset(&dataLocations, 0x00, sizeof(dataLocations));
1541
1542         /* Convert to strided data */
1543         primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex); 
1544
1545         /* Dump out what parts we have supplied */
1546         TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1547         TRACE_STRIDED((&dataLocations), position);
1548         TRACE_STRIDED((&dataLocations), blendWeights);
1549         TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1550         TRACE_STRIDED((&dataLocations), normal);
1551         TRACE_STRIDED((&dataLocations), pSize);
1552         TRACE_STRIDED((&dataLocations), diffuse);
1553         TRACE_STRIDED((&dataLocations), specular);
1554         TRACE_STRIDED((&dataLocations), texCoords[0]);
1555         TRACE_STRIDED((&dataLocations), texCoords[1]);
1556         TRACE_STRIDED((&dataLocations), texCoords[2]);
1557         TRACE_STRIDED((&dataLocations), texCoords[3]);
1558         TRACE_STRIDED((&dataLocations), texCoords[4]);
1559         TRACE_STRIDED((&dataLocations), texCoords[5]);
1560         TRACE_STRIDED((&dataLocations), texCoords[6]);
1561         TRACE_STRIDED((&dataLocations), texCoords[7]);
1562     }
1563
1564     /* Now initialize the materials state */
1565     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1566
1567     /* And re-upload any dirty textures */
1568     for (i=0; i<GL_LIMITS(textures); i++) {
1569         
1570         if ((This->StateBlock->textures[i] != NULL) && 
1571             (IDirect3DBaseTexture8Impl_IsDirty(This->StateBlock->textures[i])))
1572         {
1573             /* Load up the texture now */
1574             IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) This->StateBlock->textures[i]);
1575         }
1576     }
1577
1578     /* Now draw the graphics to the screen */
1579     if  (useVertexShaderFunction == TRUE) {
1580
1581         /* Ideally, we should have software FV and hardware VS, possibly
1582            depending on the device type?                                 */
1583
1584         if (useHW) {
1585             TRACE("Swap HW vertex shader\n");
1586             drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1587                         idxData, idxSize, minIndex, StartIdx);            
1588         } else {
1589             /* We will have to use the very, very slow emulation layer */
1590             TRACE("Swap SW vertex shader\n");
1591             drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1592                         idxData, idxSize, minIndex, StartIdx);            
1593         }
1594
1595     } else if ((dataLocations.u.s.pSize.lpData        != NULL) || 
1596                (dataLocations.u.s.diffuse.lpData      != NULL) || 
1597                (dataLocations.u.s.blendWeights.lpData != NULL)) {
1598
1599         /* Fixme, Ideally, only use the per-vertex code for software HAL 
1600            but until opengl supports all the functions returned to setup 
1601            vertex arrays, we need to drop down to the slow mechanism for  
1602            certain functions                                              */
1603
1604         /* We will have to use the slow version of GL per vertex setup */
1605         drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1606                         idxData, idxSize, minIndex, StartIdx); 
1607
1608     } else {
1609
1610         /* We can use the fast version of GL pointers */
1611         drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives, 
1612                         idxData, idxSize, minIndex, StartIdx);
1613     }
1614
1615     /* If vertex shaders or no normals, restore previous lighting state */
1616     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1617         if (isLightingOn) glEnable(GL_LIGHTING);
1618         else glDisable(GL_LIGHTING);
1619         TRACE("Restored lighting to original state\n");
1620     }
1621
1622     /* Finshed updating the screen, restore lock */
1623     LEAVE_GL();
1624     TRACE("Done all gl drawing\n");
1625
1626     /* Diagnostics */
1627 #if defined(SHOW_FRAME_MAKEUP)
1628     {
1629         if (isDumpingFrames == TRUE) {
1630             D3DLOCKED_RECT r;
1631             char buffer[80];
1632             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->backBuffer, &r, NULL, D3DLOCK_READONLY);
1633             sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1634             TRACE("Saving screenshot %s\n", buffer);
1635             IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->backBuffer, buffer);
1636             IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->backBuffer);
1637
1638 #if defined(SHOW_TEXTURE_MAKEUP)
1639            {
1640             LPDIRECT3DSURFACE8 pSur;
1641             int textureNo;
1642             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1643                 if (This->StateBlock->textures[textureNo] != NULL) {
1644                     sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1645                     TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->StateBlock->textures[textureNo])->format));
1646                     IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->StateBlock->textures[textureNo], 0, &pSur);
1647                     IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1648                     IDirect3DSurface8Impl_Release(pSur);
1649                 }
1650             }
1651            }
1652 #endif
1653            primCounter = primCounter + 1; 
1654         }
1655     }
1656 #endif
1657 }