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