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