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