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