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