Integrate hardware vertex shaders into the drawing pipeline.
[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  * Copyright 2005 Oliver Stieber
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25 #include "wined3d_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30
31 #if 0 /* TODO */
32 extern IWineD3DVertexShaderImpl*            VertexShaders[64];
33 extern IWineD3DVertexDeclarationImpl*       VertexShaderDeclarations[64];
34 extern IWineD3DPixelShaderImpl*             PixelShaders[64];
35
36 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
37 #endif
38
39 /* Returns bits for what is expected from the fixed function pipeline, and whether
40    a vertex shader will be in use. Note the fvf bits returned may be split over
41    multiple streams only if the vertex shader was created, otherwise it all relates
42    to stream 0                                                                      */
43 static BOOL initializeFVF(IWineD3DDevice *iface, DWORD *FVFbits)
44 {
45
46     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
47
48 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
49     /* The first thing to work out is if we are using the fixed function pipeline
50        which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
51        is the FVF, or with a shader which was created with no function - in which
52        case there is an FVF per declared stream. If this occurs, we also maintain
53        an 'OR' of all the FVF's together so we know what to expect across all the
54        streams                                                                        */
55 #endif
56     *FVFbits = This->stateBlock->fvf;
57 #if 0
58         *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
59 #endif
60     return FALSE;
61 }
62
63 /* Issues the glBegin call for gl given the primitive type and count */
64 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
65                     DWORD            NumPrimitives,
66                     GLenum          *primType)
67 {
68     DWORD   NumVertexes = NumPrimitives;
69
70     switch (PrimitiveType) {
71     case D3DPT_POINTLIST:
72         TRACE("POINTS\n");
73         *primType   = GL_POINTS;
74         NumVertexes = NumPrimitives;
75         break;
76
77     case D3DPT_LINELIST:
78         TRACE("LINES\n");
79         *primType   = GL_LINES;
80         NumVertexes = NumPrimitives * 2;
81         break;
82
83     case D3DPT_LINESTRIP:
84         TRACE("LINE_STRIP\n");
85         *primType   = GL_LINE_STRIP;
86         NumVertexes = NumPrimitives + 1;
87         break;
88
89     case D3DPT_TRIANGLELIST:
90         TRACE("TRIANGLES\n");
91         *primType   = GL_TRIANGLES;
92         NumVertexes = NumPrimitives * 3;
93         break;
94
95     case D3DPT_TRIANGLESTRIP:
96         TRACE("TRIANGLE_STRIP\n");
97         *primType   = GL_TRIANGLE_STRIP;
98         NumVertexes = NumPrimitives + 2;
99         break;
100
101     case D3DPT_TRIANGLEFAN:
102         TRACE("TRIANGLE_FAN\n");
103         *primType   = GL_TRIANGLE_FAN;
104         NumVertexes = NumPrimitives + 2;
105         break;
106
107     default:
108         FIXME("Unhandled primitive\n");
109         *primType    = GL_POINTS;
110         break;
111     }
112     return NumVertexes;
113 }
114
115 /* Ensure the appropriate material states are set up - only change
116    state if really required                                        */
117 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
118
119     BOOL requires_material_reset = FALSE;
120     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
121
122     if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
123         /* If we have not set up the material color tracking, do it now as required */
124         glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
125         checkGLcall("glDisable GL_COLOR_MATERIAL");
126         TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
127         glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
128         checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
129         glEnable(GL_COLOR_MATERIAL);
130         checkGLcall("glEnable GL_COLOR_MATERIAL");
131         This->tracking_color = IS_TRACKING;
132         requires_material_reset = TRUE; /* Restore material settings as will be used */
133
134     } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
135                (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
136         /* If we are tracking the current color but one isn't supplied, don't! */
137         glDisable(GL_COLOR_MATERIAL);
138         checkGLcall("glDisable GL_COLOR_MATERIAL");
139         This->tracking_color = NEEDS_TRACKING;
140         requires_material_reset = TRUE; /* Restore material settings as will be used */
141
142     } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
143         /* No need to reset material colors since no change to gl_color_material */
144         requires_material_reset = FALSE;
145
146     } else if (This->tracking_color == NEEDS_DISABLE) {
147         glDisable(GL_COLOR_MATERIAL);
148         checkGLcall("glDisable GL_COLOR_MATERIAL");
149         This->tracking_color = DISABLED_TRACKING;
150         requires_material_reset = TRUE; /* Restore material settings as will be used */
151     }
152
153     /* Reset the material colors which may have been tracking the color*/
154     if (requires_material_reset) {
155         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
156         checkGLcall("glMaterialfv");
157         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
158         checkGLcall("glMaterialfv");
159         if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
160            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
161            checkGLcall("glMaterialfv");
162         } else {
163            float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
164            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
165            checkGLcall("glMaterialfv");
166         }
167         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
168         checkGLcall("glMaterialfv");
169     }
170
171 }
172
173 static GLfloat invymat[16] = {
174         1.0f, 0.0f, 0.0f, 0.0f,
175         0.0f, -1.0f, 0.0f, 0.0f,
176         0.0f, 0.0f, 1.0f, 0.0f,
177         0.0f, 0.0f, 0.0f, 1.0f};
178
179 /* Setup views - Transformed & lit if RHW, else untransformed.
180        Only unlit if Normals are supplied
181     Returns: Whether to restore lighting afterwards           */
182 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
183
184     BOOL isLightingOn = FALSE;
185     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
186
187     /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
188        set by the appropriate render state. Note Vertex Shader output is already lit */
189     if (vtx_lit || useVS) {
190         isLightingOn = glIsEnabled(GL_LIGHTING);
191         glDisable(GL_LIGHTING);
192         checkGLcall("glDisable(GL_LIGHTING);");
193         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
194     }
195
196     if (!useVS && vtx_transformed) {
197
198         /* If the last draw was transformed as well, no need to reapply all the matrixes */
199         if (!This->last_was_rhw) {
200
201             double X, Y, height, width, minZ, maxZ;
202             This->last_was_rhw = TRUE;
203
204             /* Transformed already into viewport coordinates, so we do not need transform
205                matrices. Reset all matrices to identity and leave the default matrix in world
206                mode.                                                                         */
207             glMatrixMode(GL_MODELVIEW);
208             checkGLcall("glMatrixMode(GL_MODELVIEW)");
209             glLoadIdentity();
210             checkGLcall("glLoadIdentity");
211
212             glMatrixMode(GL_PROJECTION);
213             checkGLcall("glMatrixMode(GL_PROJECTION)");
214             glLoadIdentity();
215             checkGLcall("glLoadIdentity");
216
217             /* Set up the viewport to be full viewport */
218             X      = This->stateBlock->viewport.X;
219             Y      = This->stateBlock->viewport.Y;
220             height = This->stateBlock->viewport.Height;
221             width  = This->stateBlock->viewport.Width;
222             minZ   = This->stateBlock->viewport.MinZ;
223             maxZ   = This->stateBlock->viewport.MaxZ;
224             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
225             glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
226             checkGLcall("glOrtho");
227
228             /* Window Coord 0 is the middle of the first pixel, so translate by half
229                a pixel (See comment above glTranslate below)                         */
230             glTranslatef(0.5, 0.5, 0);
231             checkGLcall("glTranslatef(0.5, 0.5, 0)");
232             if (This->renderUpsideDown) {
233                 glMultMatrixf(invymat);
234                 checkGLcall("glMultMatrixf(invymat)");
235             }
236         }
237
238     } else {
239
240         /* Untransformed, so relies on the view and projection matrices */
241
242         if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
243             /* Only reapply when have to */
244             This->modelview_valid = TRUE;
245             glMatrixMode(GL_MODELVIEW);
246             checkGLcall("glMatrixMode");
247
248             /* In the general case, the view matrix is the identity matrix */
249             if (This->view_ident) {
250                 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
251                 checkGLcall("glLoadMatrixf");
252             } else {
253                 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
254                 checkGLcall("glLoadMatrixf");
255                 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
256                 checkGLcall("glMultMatrixf");
257             }
258         }
259
260         if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
261             /* Only reapply when have to */
262             This->proj_valid = TRUE;
263             glMatrixMode(GL_PROJECTION);
264             checkGLcall("glMatrixMode");
265
266             /* The rule is that the window coordinate 0 does not correspond to the
267                beginning of the first pixel, but the center of the first pixel.
268                As a consequence if you want to correctly draw one line exactly from
269                the left to the right end of the viewport (with all matrices set to
270                be identity), the x coords of both ends of the line would be not
271                -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
272                instead.                                                               */
273             glLoadIdentity();
274
275             glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
276             checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
277
278             if (This->renderUpsideDown) {
279                 glMultMatrixf(invymat);
280                 checkGLcall("glMultMatrixf(invymat)");
281             }
282             glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
283             checkGLcall("glLoadMatrixf");
284         }
285
286         /* Vertex Shader output is already transformed, so set up identity matrices */
287         /* FIXME: Actually, only true for software emulated ones, so when h/w ones
288              come along this needs to take into account whether s/w ones were
289              requested or not                                                       */
290         if (useVS) {
291             glMatrixMode(GL_MODELVIEW);
292             checkGLcall("glMatrixMode");
293             glLoadIdentity();
294             glMatrixMode(GL_PROJECTION);
295             checkGLcall("glMatrixMode");
296             glLoadIdentity();
297             /* Window Coord 0 is the middle of the first pixel, so translate by half
298                a pixel (See comment above glTranslate above)                         */
299             glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
300             checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
301             if (This->renderUpsideDown) {
302                 glMultMatrixf(invymat);
303                 checkGLcall("glMultMatrixf(invymat)");
304             }
305             This->modelview_valid = FALSE;
306             This->proj_valid = FALSE;
307         }
308         This->last_was_rhw = FALSE;
309     }
310     return isLightingOn;
311 }
312
313 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
314      /* We need to deal with frequency data!*/
315
316     int           textureNo =0;
317     BYTE  *data    = NULL;
318     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
319     IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
320     int i;
321     D3DVERTEXELEMENT9 *element;
322     DWORD stride;
323     for (i = 0 ; i < vertexDeclaration->declaration9NumElements - 1; ++i) {
324
325         element = vertexDeclaration->pDeclaration9 + i;
326         TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclaration9, element,  i, vertexDeclaration->declaration9NumElements);
327         if (This->stateBlock->streamIsUP) {
328             TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
329             data    = (BYTE *)This->stateBlock->streamSource[element->Stream];
330         } else {
331             TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
332             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
333         }
334         stride  = This->stateBlock->streamStride[element->Stream];
335         data += (BaseVertexIndex * stride);
336         data += element->Offset;
337         /* Why can't I just use a lookup table instead of a switch statment? */
338         switch (element->Usage) {
339         case D3DDECLUSAGE_POSITION:
340                 switch (element->UsageIndex) {
341                 case 0: /* N-patch */
342                     strided->u.s.position.lpData    = data;
343                     strided->u.s.position.dwType    = element->Type;
344                     strided->u.s.position.dwStride  = stride;
345                 break;
346                 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
347                     TRACE("Tweened positions\n");
348                     strided->u.s.position2.lpData    = data;
349                     strided->u.s.position2.dwType    = element->Type;
350                     strided->u.s.position2.dwStride  = stride;
351                 break;
352                 }
353         break;
354         case D3DDECLUSAGE_NORMAL:
355                 switch (element->UsageIndex) {
356                 case 0: /* N-patch */
357                     strided->u.s.normal.lpData    = data;
358                     strided->u.s.normal.dwType    = element->Type;
359                     strided->u.s.normal.dwStride  = stride;
360                 break;
361                 case 1: /* skinning */
362                     TRACE("Skinning / tween normals\n");
363                     strided->u.s.normal2.lpData    = data;
364                     strided->u.s.normal2.dwType    = element->Type;
365                     strided->u.s.normal2.dwStride  = stride;
366                 break;
367                 }
368                 *fvf |=  D3DFVF_NORMAL;
369         break;
370         case D3DDECLUSAGE_BLENDINDICES:
371         /* demo @http://www.ati.com/developer/vertexblend.html
372             and http://www.flipcode.com/articles/article_dx8shaders.shtml
373         */
374             strided->u.s.blendMatrixIndices.lpData  = data;
375             strided->u.s.blendMatrixIndices.dwType  = element->Type;
376             strided->u.s.blendMatrixIndices.dwStride= stride;
377         break;
378         case D3DDECLUSAGE_BLENDWEIGHT:
379             strided->u.s.blendWeights.lpData        = data;
380             strided->u.s.blendWeights.dwType        = element->Type;
381             strided->u.s.blendWeights.dwStride      = stride;
382         break;
383         case D3DDECLUSAGE_PSIZE:
384             strided->u.s.pSize.lpData               = data;
385             strided->u.s.pSize.dwType               = element->Type;
386             strided->u.s.pSize.dwStride             = stride;
387         break;
388         case D3DDECLUSAGE_COLOR:
389         switch (element->UsageIndex) {
390         case 0:/* diffuse */
391             strided->u.s.diffuse.lpData             = data;
392             strided->u.s.diffuse.dwType             = element->Type;
393             strided->u.s.diffuse.dwStride           = stride;
394         break;
395         case 1: /* specular */
396             strided->u.s.specular.lpData            = data;
397             strided->u.s.specular.dwType            = element->Type;
398             strided->u.s.specular.dwStride          = stride;
399         }
400
401         break;
402         case D3DDECLUSAGE_TEXCOORD:
403         /* For some odd reason Microsoft decided to sum usage accross all the streams,
404         which means we need to do a count and not just use the usage number */
405
406             strided->u.s.texCoords[textureNo].lpData    = data;
407             strided->u.s.texCoords[textureNo].dwType    = element->Type;
408             strided->u.s.texCoords[textureNo].dwStride  = stride;
409
410             ++textureNo;
411         break;
412         case D3DDECLUSAGE_TANGENT:
413         /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
414         this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
415         normal using tangents where no normal data has been provided */
416             TRACE("Tangents\n");
417             strided->u.s.tangent.lpData   = data;
418             strided->u.s.tangent.dwType   = element->Type;
419             strided->u.s.tangent.dwStride = stride;
420         break;
421         case D3DDECLUSAGE_BINORMAL:
422         /* Binormals are really bitangents perpendicular to the normal but s-aligned to the tangent, basically they are the vectors of any two lines on the plain at right angles to the normal and at right angles to each other, like the x,y,z axis.
423         tangent data makes it easier to perform some calculations (a bit like using 2d graph paper instead of the normal of the piece of paper)
424         The only thing they are useful for in fixed function would be working out normals when none are given.
425         */
426             TRACE("BI-Normal\n");
427             strided->u.s.binormal.lpData   = data;
428             strided->u.s.binormal.dwType   = element->Type;
429             strided->u.s.binormal.dwStride = stride;
430         break;
431         case D3DDECLUSAGE_TESSFACTOR:
432         /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
433         */
434             TRACE("Tess Factor\n");
435             strided->u.s.tessFactor.lpData   = data;
436             strided->u.s.tessFactor.dwType   = element->Type;
437             strided->u.s.tessFactor.dwStride = stride;
438         break;
439         case D3DDECLUSAGE_POSITIONT:
440
441                switch (element->UsageIndex) {
442                 case 0: /* N-patch */
443                     strided->u.s.position.lpData    = data;
444                     strided->u.s.position.dwType    = element->Type;
445                     strided->u.s.position.dwStride  = stride;
446                 break;
447                 case 1: /* skinning */
448                         /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
449                         http://xface.blogspot.com/2004_08_01_xface_archive.html
450                         */
451                     TRACE("Skinning positionsT\n");
452                     strided->u.s.position2.lpData    = data;
453                     strided->u.s.position2.dwType    = element->Type;
454                     strided->u.s.position2.dwStride  = stride;
455                 break;
456                 }
457                 /* TODO: change fvf usage to a plain boolean flag */
458                 *fvf |= D3DFVF_XYZRHW;
459             /* FIXME: were faking this flag so that we don't transform the data again */
460         break;
461         case D3DDECLUSAGE_FOG:
462         /* maybe GL_EXT_fog_coord ?
463         * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
464         * This extension allows specifying an explicit per-vertex fog
465         * coordinate to be used in fog computations, rather than using a
466         * fragment depth-based fog equation.
467         *
468         * */
469             TRACE("Fog\n");
470             strided->u.s.fog.lpData   = data;
471             strided->u.s.fog.dwType   = element->Type;
472             strided->u.s.fog.dwStride = stride;
473         break;
474         case D3DDECLUSAGE_DEPTH:
475             TRACE("depth\n");
476             strided->u.s.depth.lpData   = data;
477             strided->u.s.depth.dwType   = element->Type;
478             strided->u.s.depth.dwStride = stride;
479             break;
480         case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
481             TRACE("depth\n");
482             strided->u.s.sample.lpData   = data;
483             strided->u.s.sample.dwType   = element->Type;
484             strided->u.s.sample.dwStride = stride;
485         break;
486         };
487
488     };
489
490 }
491
492 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
493
494     short         LoopThroughTo = 0;
495     short         nStream;
496     int           numBlends;
497     int           numTextures;
498     int           textureNo;
499     int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
500     int           numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
501
502     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
503
504     /* OK, Now to setup the data locations
505        For the non-created vertex shaders, the VertexShader var holds the real
506           FVF and only stream 0 matters
507        For the created vertex shaders, there is an FVF per stream              */
508     if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
509         LoopThroughTo = MAX_STREAMS;
510     } else {
511         LoopThroughTo = 1;
512     }
513
514     /* Work through stream by stream */
515     for (nStream=0; nStream<LoopThroughTo; ++nStream) {
516         DWORD  stride  = This->stateBlock->streamStride[nStream];
517         BYTE  *data    = NULL;
518         DWORD  thisFVF = 0;
519
520         /* Skip empty streams */
521         if (This->stateBlock->streamSource[nStream] == NULL) continue;
522
523         /* Retrieve appropriate FVF */
524         if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
525             thisFVF = This->stateBlock->fvf;
526             /* Handle memory passed directly as well as vertex buffers */
527             if (This->stateBlock->streamIsUP) {
528                 data    = (BYTE *)This->stateBlock->streamSource[nStream];
529             } else {
530                 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
531             }
532         } else {
533 #if 0 /* TODO: Vertex shader support */
534             thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
535             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
536 #endif
537         }
538         VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
539         if (thisFVF == 0) continue;
540
541         /* Now convert the stream into pointers */
542
543         /* Shuffle to the beginning of the vertexes to render and index from there */
544         data = data + (BaseVertexIndex * stride);
545
546         /* Either 3 or 4 floats depending on the FVF */
547         /* FIXME: Can blending data be in a different stream to the position data?
548               and if so using the fixed pipeline how do we handle it               */
549         if (thisFVF & D3DFVF_POSITION_MASK) {
550             strided->u.s.position.lpData    = data;
551             strided->u.s.position.dwType    = D3DDECLTYPE_FLOAT3;
552             strided->u.s.position.dwStride  = stride;
553             data += 3 * sizeof(float);
554             if (thisFVF & D3DFVF_XYZRHW) {
555                 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
556                 data += sizeof(float);
557             }
558         }
559
560         /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
561         /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
562         numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
563         if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
564
565         if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
566             TRACE("Setting blend Weights to %p \n", data);
567             strided->u.s.blendWeights.lpData    = data;
568             strided->u.s.blendWeights.dwType    = D3DDECLTYPE_FLOAT1 + numBlends - 1;
569             strided->u.s.blendWeights.dwStride  = stride;
570             data += numBlends * sizeof(FLOAT);
571
572             if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
573                 strided->u.s.blendMatrixIndices.lpData = data;
574                 strided->u.s.blendMatrixIndices.dwType  = D3DDECLTYPE_UBYTE4;
575                 strided->u.s.blendMatrixIndices.dwStride= stride;
576                 data += sizeof(DWORD);
577             }
578         }
579
580         /* Normal is always 3 floats */
581         if (thisFVF & D3DFVF_NORMAL) {
582             strided->u.s.normal.lpData    = data;
583             strided->u.s.normal.dwType    = D3DDECLTYPE_FLOAT3;
584             strided->u.s.normal.dwStride  = stride;
585             data += 3 * sizeof(FLOAT);
586         }
587
588         /* Pointsize is a single float */
589         if (thisFVF & D3DFVF_PSIZE) {
590             strided->u.s.pSize.lpData    = data;
591             strided->u.s.pSize.dwType    = D3DDECLTYPE_FLOAT1;
592             strided->u.s.pSize.dwStride  = stride;
593             data += sizeof(FLOAT);
594         }
595
596         /* Diffuse is 4 unsigned bytes */
597         if (thisFVF & D3DFVF_DIFFUSE) {
598             strided->u.s.diffuse.lpData    = data;
599             strided->u.s.diffuse.dwType    = D3DDECLTYPE_SHORT4;
600             strided->u.s.diffuse.dwStride  = stride;
601             data += sizeof(DWORD);
602         }
603
604         /* Specular is 4 unsigned bytes */
605         if (thisFVF & D3DFVF_SPECULAR) {
606             strided->u.s.specular.lpData    = data;
607             strided->u.s.specular.dwType    = D3DDECLTYPE_SHORT4;
608             strided->u.s.specular.dwStride  = stride;
609             data += sizeof(DWORD);
610         }
611
612         /* Texture coords */
613         numTextures   = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
614         coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
615
616         /* numTextures indicates the number of texture coordinates supplied */
617         /* However, the first set may not be for stage 0 texture - it all   */
618         /*   depends on D3DTSS_TEXCOORDINDEX.                               */
619         /* The number of bytes for each coordinate set is based off         */
620         /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
621
622         /* So, for each supplied texture extract the coords */
623         for (textureNo = 0; textureNo < numTextures; ++textureNo) {
624
625             strided->u.s.texCoords[textureNo].lpData    = data;
626             strided->u.s.texCoords[textureNo].dwType    = D3DDECLTYPE_FLOAT1;
627             strided->u.s.texCoords[textureNo].dwStride  = stride;
628             numCoords[textureNo] = coordIdxInfo & 0x03;
629
630             /* Always one set */
631             data += sizeof(float);
632             if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
633                 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
634                 data += sizeof(float);
635                 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
636                     strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
637                     data += sizeof(float);
638                     if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
639                         strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
640                         data += sizeof(float);
641                     }
642                 }
643             }
644             coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
645         }
646     }
647 }
648
649 #if 0 /* TODO: Software Shaders */
650 /* Draw a single vertex using this information */
651 static void draw_vertex(IWineD3DDevice *iface,                         /* interface    */
652                  BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
653                  BOOL isNormal, float nx, float ny, float nz,          /* normal       */
654                  BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
655                  BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
656                  BOOL isPtSize, float ptSize,                       /* pointSize    */
657                  WINED3DVECTOR_4 *texcoords, int *numcoords)        /* texture info */
658 {
659     unsigned int textureNo;
660     float s, t, r, q;
661     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
662
663     /* Diffuse -------------------------------- */
664     if (isDiffuse) {
665         glColor4fv(dRGBA);
666         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
667     }
668
669     /* Specular Colour ------------------------------------------*/
670     if (isSpecular) {
671         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
672           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
673           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
674         } else {
675           VTRACE(("Specular color extensions not supplied\n"));
676         }
677     }
678
679     /* Normal -------------------------------- */
680     if (isNormal) {
681         VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
682         glNormal3f(nx, ny, nz);
683     }
684
685     /* Point Size ----------------------------------------------*/
686     if (isPtSize) {
687
688         /* no such functionality in the fixed function GL pipeline */
689         FIXME("Cannot change ptSize here in openGl\n");
690     }
691
692     /* Texture coords --------------------------- */
693     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
694
695         if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
696             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
697             continue ;
698         }
699
700         /* Query tex coords */
701         if (This->stateBlock->textures[textureNo] != NULL) {
702
703             int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
704             if (coordIdx >= MAX_TEXTURES) {
705                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
706                 continue;
707             } else if (numcoords[coordIdx] == 0) {
708                 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
709                 continue;
710             } else {
711
712                 /* Initialize vars */
713                 s = 0.0f;
714                 t = 0.0f;
715                 r = 0.0f;
716                 q = 0.0f;
717
718                 switch (numcoords[coordIdx]) {
719                 case 4: q = texcoords[coordIdx].w; /* drop through */
720                 case 3: r = texcoords[coordIdx].z; /* drop through */
721                 case 2: t = texcoords[coordIdx].y; /* drop through */
722                 case 1: s = texcoords[coordIdx].x;
723                 }
724
725                 switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
726                 case D3DTTFF_COUNT1:
727                     VTRACE(("tex:%d, s=%f\n", textureNo, s));
728                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
729                         GLMULTITEXCOORD1F(textureNo, s);
730                     } else {
731                         glTexCoord1f(s);
732                     }
733                     break;
734                 case D3DTTFF_COUNT2:
735                     VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
736                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
737                         GLMULTITEXCOORD2F(textureNo, s, t);
738                     } else {
739                         glTexCoord2f(s, t);
740                     }
741                     break;
742                 case D3DTTFF_COUNT3:
743                     VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
744                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
745                         GLMULTITEXCOORD3F(textureNo, s, t, r);
746                     } else {
747                         glTexCoord3f(s, t, r);
748                     }
749                     break;
750                 case D3DTTFF_COUNT4:
751                     VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
752                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
753                         GLMULTITEXCOORD4F(textureNo, s, t, r, q);
754                     } else {
755                         glTexCoord4f(s, t, r, q);
756                     }
757                     break;
758                 default:
759                     FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
760                 }
761             }
762         }
763     } /* End of textures */
764
765     /* Position -------------------------------- */
766     if (isXYZ) {
767         if (1.0f == rhw || rhw < 0.00001f) {
768             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
769             glVertex3f(x, y, z);
770         } else {
771             /* Cannot optimize by dividing through by rhw as rhw is required
772                later for perspective in the GL pipeline for vertex shaders   */
773             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
774             glVertex4f(x,y,z,rhw);
775         }
776     }
777 }
778 #endif /* TODO: Software shaders */
779
780 void loadNumberedArrays(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
781     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
782
783 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
784     if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
785        TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
786        GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
787                         WINED3D_ATR_SIZE(_arrayName), \
788                         WINED3D_ATR_GLTYPE(_arrayName), \
789                         WINED3D_ATR_NORMALIZED(_arrayName), \
790                         sd->u.s._arrayName.dwStride, \
791                         sd->u.s._arrayName.lpData)); \
792         GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
793     }
794
795
796 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
797     if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
798        FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
799        GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
800                         WINED3D_ATR_SIZE(position2), \
801                         WINED3D_ATR_GLTYPE(position2), \
802                         WINED3D_ATR_NORMALIZED(position2), \
803                         sd->u.s.position2.dwStride, \
804                         ((char *)sd->u.s.position2.lpData) + \
805                         WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
806         GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
807     }
808
809 /* Generate some lookup tables */
810     /* drop the RHW coord, there must be a nicer way of doing this. */
811     sd->u.s.position.dwType  = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
812     sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
813
814     LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
815     LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
816     LOAD_NUMBERED_ARRAY(position,POSITION);
817     LOAD_NUMBERED_ARRAY(normal,NORMAL);
818     LOAD_NUMBERED_ARRAY(pSize,PSIZE);
819     LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
820     LOAD_NUMBERED_ARRAY(specular,SPECULAR);
821     LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
822     LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
823     LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
824     LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
825     LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
826     LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
827     LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
828     LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
829 #if 0   /* TODO: Samplers may allow for more texture coords */
830     LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
831     LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
832     LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
833     LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
834     LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
835     LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
836     LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
837     LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
838 #endif
839     LOAD_NUMBERED_ARRAY(position,POSITIONT);
840     /* d3d9 types */
841     LOAD_NUMBERED_ARRAY(tangent,TANGENT);
842     LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
843     LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
844     LOAD_NUMBERED_ARRAY(position2,POSITION2);
845     /* there can be lots of position arrays */
846     LOAD_NUMBERED_POSITION_ARRAY(0);
847     LOAD_NUMBERED_POSITION_ARRAY(1);
848     LOAD_NUMBERED_POSITION_ARRAY(2);
849     LOAD_NUMBERED_POSITION_ARRAY(3);
850     LOAD_NUMBERED_POSITION_ARRAY(4);
851     LOAD_NUMBERED_POSITION_ARRAY(5);
852     LOAD_NUMBERED_POSITION_ARRAY(6);
853     LOAD_NUMBERED_POSITION_ARRAY(7);
854     LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
855     LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
856     LOAD_NUMBERED_ARRAY(fog,FOG);
857     LOAD_NUMBERED_ARRAY(depth,DEPTH);
858     LOAD_NUMBERED_ARRAY(sample,SAMPLE);
859
860 #undef LOAD_NUMBERED_ARRAY
861 }
862
863 static void loadVertexData(IWineD3DDevice *iface, Direct3DVertexStridedData *sd) {
864     unsigned int textureNo   = 0;
865     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
866
867     TRACE("Using fast vertex array code\n");
868     /* Blend Data ---------------------------------------------- */
869     if ((sd->u.s.blendWeights.lpData != NULL) ||
870         (sd->u.s.blendMatrixIndices.lpData != NULL)) {
871
872
873         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
874
875 #if 1
876             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
877             checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
878 #endif
879
880             TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
881             /* FIXME("TODO\n");*/
882             /* Note dwType == float3 or float4 == 2 or 3 */
883
884 #if 0
885             /* with this on, the normals appear to be being modified,
886                but the vertices aren't being translated as they should be
887                Maybe the world matrix aren't being setup properly? */
888             glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
889 #endif
890
891
892             VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
893                 WINED3D_ATR_SIZE(blendWeights) ,
894                 sd->u.s.blendWeights.dwStride,
895                 sd->u.s.blendWeights.lpData));
896
897             GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
898                             sd->u.s.blendWeights.dwStride,
899                             sd->u.s.blendWeights.lpData);
900
901             checkGLcall("glWeightPointerARB");
902
903             if(sd->u.s.blendMatrixIndices.lpData != NULL){
904                 static BOOL showfixme = TRUE;
905                 if(showfixme){
906                     FIXME("blendMatrixIndices support\n");
907                     showfixme = FALSE;
908                 }
909             }
910
911
912
913         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
914             /* FIXME("TODO\n");*/
915 #if 0
916
917             GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
918                                                 sd->u.s.blendWeights.dwStride,
919                                                 sd->u.s.blendWeights.lpData);
920             checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
921             glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
922             checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
923 #endif
924
925         } else {
926             /* TODO: support blends in fixupVertices */
927             FIXME("unsupported blending in openGl\n");
928         }
929     } else {
930         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
931 #if 0    /* TODO: Vertex blending */
932             glDisable(GL_VERTEX_BLEND_ARB);
933 #endif
934             TRACE("ARB_VERTEX_BLEND \n");
935         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
936             TRACE(" EXT_VERTEX_WEIGHTING\n");
937             glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
938             checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
939
940         }
941     }
942
943 #if 0 /* FOG  ----------------------------------------------*/
944     if (sd->u.s.fog.lpData != NULL) {
945         /* TODO: fog*/
946     if (GL_SUPPORT(EXT_FOG_COORD) {
947              glEnableClientState(GL_FOG_COORD_EXT);
948             (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
949                         sd->u.s.fog.dwStride,
950                         sd->u.s.fog.lpData);
951         } else {
952             /* don't bother falling back to 'slow' as we don't support software FOG yet. */
953             /* FIXME: fixme once */
954             TRACE("Hardware support for FOG is not avaiable, FOG disabled. \n");
955         }
956     } else {
957         if (GL_SUPPRT(EXT_FOR_COORD) {
958              /* make sure fog is disabled */
959              glDisableClientState(GL_FOG_COORD_EXT);
960         }
961     }
962 #endif
963
964 #if 0 /* tangents  ----------------------------------------------*/
965     if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
966         /* TODO: tangents*/
967         if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
968             if (sd->u.s.tangent.lpData != NULL) {
969                 glEnable(GL_TANGENT_ARRAY_EXT);
970                 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
971                             sd->u.s.tangent.dwStride,
972                             sd->u.s.tangent.lpData);
973             } else {
974                     glDisable(GL_TANGENT_ARRAY_EXT);
975             }
976             if (sd->u.s.binormal.lpData != NULL) {
977                     glEnable(GL_BINORMAL_ARRAY_EXT);
978                     (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
979                                                 sd->u.s.binormal.dwStride,
980                                                 sd->u.s.binormal.lpData);
981             } else{
982                     glDisable(GL_BINORMAL_ARRAY_EXT);
983             }
984
985         } else {
986             /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
987             /* FIXME: fixme once */
988             TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled. \n");
989         }
990     } else {
991         if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
992              /* make sure fog is disabled */
993              glDisable(GL_TANGENT_ARRAY_EXT);
994              glDisable(GL_BINORMAL_ARRAY_EXT);
995         }
996     }
997 #endif
998
999     /* Point Size ----------------------------------------------*/
1000     if (sd->u.s.pSize.lpData != NULL) {
1001
1002         /* no such functionality in the fixed function GL pipeline */
1003         TRACE("Cannot change ptSize here in openGl\n");
1004         /* TODO: Implement this function in using shaders if they are available */
1005
1006     }
1007
1008     /* Vertex Pointers -----------------------------------------*/
1009     if (sd->u.s.position.lpData != NULL) {
1010         /* Note dwType == float3 or float4 == 2 or 3 */
1011         VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1012                 sd->u.s.position.dwStride,
1013                 sd->u.s.position.dwType + 1,
1014                 sd->u.s.position.lpData));
1015
1016         /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1017            handling for rhw mode should not impact screen position whereas in GL it does.
1018            This may  result in very slightly distored textures in rhw mode, but
1019            a very minimal different. There's always the other option of
1020            fixing the view matrix to prevent w from having any effect  */
1021         glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1022                         sd->u.s.position.dwStride, sd->u.s.position.lpData);
1023         checkGLcall("glVertexPointer(...)");
1024         glEnableClientState(GL_VERTEX_ARRAY);
1025         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1026
1027     } else {
1028         glDisableClientState(GL_VERTEX_ARRAY);
1029         checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1030     }
1031
1032     /* Normals -------------------------------------------------*/
1033     if (sd->u.s.normal.lpData != NULL) {
1034         /* Note dwType == float3 or float4 == 2 or 3 */
1035         VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1036                 sd->u.s.normal.dwStride,
1037                 sd->u.s.normal.lpData));
1038         glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1039                         sd->u.s.normal.dwStride,
1040                         sd->u.s.normal.lpData);
1041         checkGLcall("glNormalPointer(...)");
1042         glEnableClientState(GL_NORMAL_ARRAY);
1043         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1044
1045     } else {
1046         glDisableClientState(GL_NORMAL_ARRAY);
1047         checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1048         glNormal3f(0, 0, 1);
1049         checkGLcall("glNormal3f(0, 0, 1)");
1050     }
1051
1052     /* Diffuse Colour --------------------------------------------*/
1053     /*  WARNING: Data here MUST be in RGBA format, so cannot      */
1054     /*     go directly into fast mode from app pgm, because       */
1055     /*     directx requires data in BGRA format.                  */
1056     /* currently fixupVertices swizels the format, but this isn't */
1057     /* very practical when using VBOS                             */
1058     /* NOTE: Unless we write a vertex shader to swizel the colour */
1059     /* , or the user doesn't care and wants the speed advantage   */
1060
1061     if (sd->u.s.diffuse.lpData != NULL) {
1062         /* Note dwType == float3 or float4 == 2 or 3 */
1063         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1064                 sd->u.s.diffuse.dwStride,
1065                 sd->u.s.diffuse.lpData));
1066
1067         glColorPointer(4, GL_UNSIGNED_BYTE,
1068                        sd->u.s.diffuse.dwStride,
1069                        sd->u.s.diffuse.lpData);
1070         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1071         glEnableClientState(GL_COLOR_ARRAY);
1072         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1073
1074     } else {
1075         glDisableClientState(GL_COLOR_ARRAY);
1076         checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1077         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1078         checkGLcall("glColor4f(1, 1, 1, 1)");
1079     }
1080
1081     /* Specular Colour ------------------------------------------*/
1082     if (sd->u.s.specular.lpData != NULL) {
1083         TRACE("setting specular colour\n");
1084         /* Note dwType == float3 or float4 == 2 or 3 */
1085         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1086                 sd->u.s.specular.dwStride,
1087                 sd->u.s.specular.lpData));
1088         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1089             GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1090                                                    sd->u.s.specular.dwStride,
1091                                                    sd->u.s.specular.lpData);
1092             vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1093             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1094             vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1095         } else {
1096
1097         /* Missing specular color is not critical, no warnings */
1098         VTRACE(("Specular colour is not supported in this GL implementation\n"));
1099         }
1100
1101     } else {
1102         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1103
1104             glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1105             checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1106             GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1107             checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1108         } else {
1109
1110             /* Missing specular color is not critical, no warnings */
1111             VTRACE(("Specular colour is not supported in this GL implementation\n"));
1112         }
1113     }
1114
1115     /* Texture coords -------------------------------------------*/
1116
1117     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1118
1119         /* Select the correct texture stage */
1120         GLCLIENTACTIVETEXTURE(textureNo);
1121         if (This->stateBlock->textures[textureNo] != NULL) {
1122             int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1123             TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1124             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1125                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1126                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1127                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1128                 continue;
1129             }
1130
1131             if (coordIdx >= MAX_TEXTURES) {
1132                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1133                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1134                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1135
1136             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1137                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1138                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1139                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1140
1141             } else {
1142
1143                 /* The coords to supply depend completely on the fvf / vertex shader */
1144                 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1145                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1146             }
1147
1148         } else {
1149             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1150             GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1151         }
1152     }
1153 }
1154
1155 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1156                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1157     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1158
1159     if (idxData != NULL /* This crashes sometimes!*/) {
1160         TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1161         idxData = idxData == (void *)-1 ? NULL : idxData;
1162 #if 1
1163 #if 0
1164         glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1165         glEnableClientState(GL_INDEX_ARRAY);
1166 #endif
1167         glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1168                      (const char *)idxData+(idxSize * startIdx));
1169 #else /* using drawRangeElements may be faster */
1170
1171         glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1172                       idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1173                       (const char *)idxData+(idxSize * startIdx));
1174 #endif
1175         checkGLcall("glDrawRangeElements");
1176
1177     } else {
1178
1179         /* Note first is now zero as we shuffled along earlier */
1180         TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1181         glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1182         checkGLcall("glDrawArrays");
1183
1184     }
1185
1186     return;
1187 }
1188
1189 /*
1190  * Actually draw using the supplied information.
1191  * Slower GL version which extracts info about each vertex in turn
1192  */
1193         
1194 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1195                      UINT NumVertexes, GLenum glPrimType,
1196                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1197
1198     unsigned int               textureNo    = 0;
1199     const short               *pIdxBufS     = NULL;
1200     const long                *pIdxBufL     = NULL;
1201     LONG                       SkipnStrides = 0;
1202     LONG                       vx_index;
1203     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1204     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
1205     float rhw = 0.0f;                      /* rhw                        */
1206     float ptSize = 0.0f;                   /* Point size                 */
1207     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
1208     DWORD specularColor = 0;               /* Specular Color             */
1209     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1210
1211     TRACE("Using slow vertex array code\n");
1212
1213     /* Variable Initialization */
1214     if (idxData != NULL) {
1215         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1216         else pIdxBufL = (const long *) idxData;
1217     }
1218
1219     /* Start drawing in GL */
1220     VTRACE(("glBegin(%x)\n", glPrimType));
1221     glBegin(glPrimType);
1222
1223     /* For each primitive */
1224     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1225
1226         /* Initialize diffuse color */
1227         diffuseColor = 0xFFFFFFFF;
1228
1229         /* For indexed data, we need to go a few more strides in */
1230         if (idxData != NULL) {
1231
1232             /* Indexed so work out the number of strides to skip */
1233             if (idxSize == 2) {
1234                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1235                 SkipnStrides = pIdxBufS[startIdx + vx_index];
1236             } else {
1237                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1238                 SkipnStrides = pIdxBufL[startIdx + vx_index];
1239             }
1240         }
1241
1242         /* Position Information ------------------ */
1243         if (sd->u.s.position.lpData != NULL) {
1244
1245             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1246             x = ptrToCoords[0];
1247             y = ptrToCoords[1];
1248             z = ptrToCoords[2];
1249             rhw = 1.0;
1250             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1251
1252             /* RHW follows, only if transformed, ie 4 floats were provided */
1253             if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1254                 rhw = ptrToCoords[3];
1255                 VTRACE(("rhw=%f\n", rhw));
1256             }
1257         }
1258
1259         /* Blending data -------------------------- */
1260         if (sd->u.s.blendWeights.lpData != NULL) {
1261             /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1262             FIXME("Blending not supported yet\n");
1263
1264             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1265                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1266             }
1267         }
1268
1269         /* Vertex Normal Data (untransformed only)- */
1270         if (sd->u.s.normal.lpData != NULL) {
1271
1272             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1273             nx = ptrToCoords[0];
1274             ny = ptrToCoords[1];
1275             nz = ptrToCoords[2];
1276             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1277         }
1278
1279         /* Point Size ----------------------------- */
1280         if (sd->u.s.pSize.lpData != NULL) {
1281
1282             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1283             ptSize = ptrToCoords[0];
1284             VTRACE(("ptSize=%f\n", ptSize));
1285             FIXME("No support for ptSize yet\n");
1286         }
1287
1288         /* Diffuse -------------------------------- */
1289         if (sd->u.s.diffuse.lpData != NULL) {
1290
1291             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1292             diffuseColor = ptrToCoords[0];
1293             VTRACE(("diffuseColor=%lx\n", diffuseColor));
1294         }
1295
1296         /* Specular  -------------------------------- */
1297         if (sd->u.s.specular.lpData != NULL) {
1298
1299             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1300             specularColor = ptrToCoords[0];
1301             VTRACE(("specularColor=%lx\n", specularColor));
1302         }
1303
1304         /* Texture coords --------------------------- */
1305         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1306
1307             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1308                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1309                 continue ;
1310             }
1311
1312             /* Query tex coords */
1313             if (This->stateBlock->textures[textureNo] != NULL) {
1314
1315                 int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1316                 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1317                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1318
1319                 if (coordIdx > 7) {
1320                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1321                     continue;
1322                 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1323                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1324                     continue;
1325                 } else {
1326
1327                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1328
1329                     /* The coords to supply depend completely on the fvf / vertex shader */
1330                     switch (coordsToUse) {
1331                     case 4: q = ptrToCoords[3]; /* drop through */
1332                     case 3: r = ptrToCoords[2]; /* drop through */
1333                     case 2: t = ptrToCoords[1]; /* drop through */
1334                     case 1: s = ptrToCoords[0];
1335                     }
1336
1337                     /* Projected is more 'fun' - Move the last coord to the 'q'
1338                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1339                     if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1340                         (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1341
1342                         if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1343                             switch (coordsToUse) {
1344                             case 0:  /* Drop Through */
1345                             case 1:
1346                                 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1347                                 break;
1348                             case 2:
1349                                 q = t;
1350                                 t = 0.0;
1351                                 coordsToUse = 4;
1352                                 break;
1353                             case 3:
1354                                 q = r;
1355                                 r = 0.0;
1356                                 coordsToUse = 4;
1357                                 break;
1358                             case 4:  /* Nop here */
1359                                 break;
1360                             default:
1361                                 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1362                                       This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1363                             }
1364                         }
1365                     }
1366
1367                     switch (coordsToUse) {   /* Supply the provided texture coords */
1368                     case D3DTTFF_COUNT1:
1369                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1370                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1371                             GLMULTITEXCOORD1F(textureNo, s);
1372                         } else {
1373                             glTexCoord1f(s);
1374                         }
1375                         break;
1376                     case D3DTTFF_COUNT2:
1377                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1378                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1379                             GLMULTITEXCOORD2F(textureNo, s, t);
1380                         } else {
1381                             glTexCoord2f(s, t);
1382                         }
1383                         break;
1384                     case D3DTTFF_COUNT3:
1385                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1386                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1387                             GLMULTITEXCOORD3F(textureNo, s, t, r);
1388                         } else {
1389                             glTexCoord3f(s, t, r);
1390                         }
1391                         break;
1392                     case D3DTTFF_COUNT4:
1393                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1394                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1395                             GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1396                         } else {
1397                             glTexCoord4f(s, t, r, q);
1398                         }
1399                         break;
1400                     default:
1401                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1402                     }
1403                 }
1404             }
1405         } /* End of textures */
1406
1407         /* Diffuse -------------------------------- */
1408         if (sd->u.s.diffuse.lpData != NULL) {
1409             glColor4ub((diffuseColor >> 16) & 0xFF,
1410                        (diffuseColor >>  8) & 0xFF,
1411                        (diffuseColor >>  0) & 0xFF,
1412                        (diffuseColor >> 24) & 0xFF);
1413             VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1414                     ((diffuseColor >> 16) & 0xFF) / 255.0f,
1415                     ((diffuseColor >>  8) & 0xFF) / 255.0f,
1416                     ((diffuseColor >>  0) & 0xFF) / 255.0f,
1417                     ((diffuseColor >> 24) & 0xFF) / 255.0f));
1418         } else {
1419             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1420         }
1421
1422         /* Specular ------------------------------- */
1423         if (sd->u.s.diffuse.lpData != NULL) {
1424             VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1425                     ((specularColor >> 16) & 0xFF) / 255.0f,
1426                     ((specularColor >>  8) & 0xFF) / 255.0f,
1427                     ((specularColor >>  0) & 0xFF) / 255.0f));
1428             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1429                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1430                            (specularColor >> 16) & 0xFF,
1431                            (specularColor >>  8) & 0xFF,
1432                            (specularColor >>  0) & 0xFF);
1433             } else {
1434                 /* Do not worry if specular colour missing and disable request */
1435                 VTRACE(("Specular color extensions not supplied\n"));
1436             }
1437         } else {
1438             if (vx_index == 0) {
1439                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1440                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1441                 } else {
1442                     /* Do not worry if specular colour missing and disable request */
1443                     VTRACE(("Specular color extensions not supplied\n"));
1444                 }
1445             }
1446         }
1447
1448         /* Normal -------------------------------- */
1449         if (sd->u.s.normal.lpData != NULL) {
1450             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1451             glNormal3f(nx, ny, nz);
1452         } else {
1453             if (vx_index == 0) glNormal3f(0, 0, 1);
1454         }
1455
1456         /* Position -------------------------------- */
1457         if (sd->u.s.position.lpData != NULL) {
1458             if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1459                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1460                 glVertex3f(x, y, z);
1461             } else {
1462                 GLfloat w = 1.0 / rhw;
1463                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1464                 glVertex4f(x*w, y*w, z*w, w);
1465             }
1466         }
1467
1468         /* For non indexed mode, step onto next parts */
1469         if (idxData == NULL) {
1470             ++SkipnStrides;
1471         }
1472     }
1473
1474     glEnd();
1475     checkGLcall("glEnd and previous calls");
1476 }
1477
1478 #if 0 /* TODO: Software/Hardware vertex blending support */
1479 /*
1480  * Draw with emulated vertex shaders
1481  * Note: strided data is uninitialized, as we need to pass the vertex
1482  *     shader directly as ordering irs yet
1483  */
1484 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1485                      int PrimitiveType, ULONG NumPrimitives,
1486                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1487
1488     unsigned int               textureNo    = 0;
1489     GLenum                     glPrimType   = GL_POINTS;
1490     int                        NumVertexes  = NumPrimitives;
1491     const short               *pIdxBufS     = NULL;
1492     const long                *pIdxBufL     = NULL;
1493     LONG                       SkipnStrides = 0;
1494     LONG                       vx_index;
1495     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1496     float rhw = 0.0f;                      /* rhw                        */
1497     float ptSize = 0.0f;                   /* Point size                 */
1498     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1499     int   numcoords[8];                    /* Number of coords           */
1500     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1501
1502     IDirect3DVertexShaderImpl* vertexShader = NULL;
1503
1504     TRACE("Using slow software vertex shader code\n");
1505
1506     /* Variable Initialization */
1507     if (idxData != NULL) {
1508         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1509         else pIdxBufL = (const long *) idxData;
1510     }
1511
1512     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1513     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1514
1515     /* Retrieve the VS information */
1516     vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1517
1518     /* Start drawing in GL */
1519     VTRACE(("glBegin(%x)\n", glPrimType));
1520     glBegin(glPrimType);
1521
1522     /* For each primitive */
1523     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1524
1525         /* For indexed data, we need to go a few more strides in */
1526         if (idxData != NULL) {
1527
1528             /* Indexed so work out the number of strides to skip */
1529             if (idxSize == 2) {
1530                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1531                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1532             } else {
1533                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1534                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1535             }
1536         }
1537
1538         /* Fill the vertex shader input */
1539         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1540
1541         /* Initialize the output fields to the same defaults as it would normally have */
1542         memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1543         vertexShader->output.oD[0].x = 1.0;
1544         vertexShader->output.oD[0].y = 1.0;
1545         vertexShader->output.oD[0].z = 1.0;
1546         vertexShader->output.oD[0].w = 1.0;
1547
1548         /* Now execute the vertex shader */
1549         IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1550
1551         /*
1552         TRACE_VECTOR(vertexShader->output.oPos);
1553         TRACE_VECTOR(vertexShader->output.oD[0]);
1554         TRACE_VECTOR(vertexShader->output.oD[1]);
1555         TRACE_VECTOR(vertexShader->output.oT[0]);
1556         TRACE_VECTOR(vertexShader->output.oT[1]);
1557         TRACE_VECTOR(vertexShader->input.V[0]);
1558         TRACE_VECTOR(vertexShader->data->C[0]);
1559         TRACE_VECTOR(vertexShader->data->C[1]);
1560         TRACE_VECTOR(vertexShader->data->C[2]);
1561         TRACE_VECTOR(vertexShader->data->C[3]);
1562         TRACE_VECTOR(vertexShader->data->C[4]);
1563         TRACE_VECTOR(vertexShader->data->C[5]);
1564         TRACE_VECTOR(vertexShader->data->C[6]);
1565         TRACE_VECTOR(vertexShader->data->C[7]);
1566         */
1567
1568         /* Extract out the output */
1569         /* FIXME: Fog coords? */
1570         x = vertexShader->output.oPos.x;
1571         y = vertexShader->output.oPos.y;
1572         z = vertexShader->output.oPos.z;
1573         rhw = vertexShader->output.oPos.w;
1574         ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1575
1576         /** Update textures coords using vertexShader->output.oT[0->7] */
1577         memset(texcoords, 0x00, sizeof(texcoords));
1578         memset(numcoords, 0x00, sizeof(numcoords));
1579         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1580             if (This->stateBlock->textures[textureNo] != NULL) {
1581                texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1582                texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1583                texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1584                texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1585                if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1586                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1587                } else {
1588                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1589                    case D3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1590                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1591                    default:                     numcoords[textureNo] = 4;
1592                    }
1593                }
1594             } else {
1595                 numcoords[textureNo] = 0;
1596             }
1597         }
1598
1599         /* Draw using this information */
1600         draw_vertex(iface,
1601                     TRUE, x, y, z, rhw,
1602                     TRUE, 0.0f, 0.0f, 1.0f,
1603                     TRUE, (float*) &vertexShader->output.oD[0],
1604                     TRUE, (float*) &vertexShader->output.oD[1],
1605                     FALSE, ptSize,         /* FIXME: Change back when supported */
1606                     texcoords, numcoords);
1607
1608         /* For non indexed mode, step onto next parts */
1609         if (idxData == NULL) {
1610            ++SkipnStrides;
1611         }
1612
1613     } /* for each vertex */
1614
1615     glEnd();
1616     checkGLcall("glEnd and previous calls");
1617 }
1618
1619 #endif
1620
1621 void inline  drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1622 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1623     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1624
1625     /* Now draw the graphics to the screen */
1626     if  (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1627         FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1628         /* Ideally, we should have software FV and hardware VS, possibly
1629            depending on the device type? */
1630 #if 0 /* TODO: vertex and pixel shaders */
1631         drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1632                     idxData, idxSize, minIndex, StartIdx);
1633 #endif
1634
1635     } else {
1636
1637         /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1638         int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1639         int endStride = startStride;
1640         TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1641
1642 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1643         if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1644             int t;
1645             if (idxSize == 2) {
1646                 unsigned short *index = (unsigned short *)idxData;
1647                 index += StartIdx;
1648                 for (t = 0 ; t < numberOfIndicies; t++) {
1649                     if (startStride >  *index)
1650                         startStride = *index;
1651                     if (endStride < *index)
1652                         endStride = *index;
1653                     index++;
1654                 }
1655             } else {  /* idxSize == 4 */
1656                 unsigned int *index = (unsigned int *)idxData;
1657                 index += StartIdx;
1658                 for (t = 0 ; t < numberOfIndicies; t++) {
1659                     if (startStride > *index)
1660                         startStride = *index;
1661                     if (endStride < *index)
1662                         endStride = *index;
1663                     index++;
1664                 }
1665             }
1666         } else {
1667             endStride += numberOfvertices -1;
1668         }
1669 #endif
1670         TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1671         /* pre-transform verticex */
1672         /* TODO: Caching, VBO's etc.. */
1673
1674 /* Generate some fixme's if unsupported functionality is being used */
1675 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1676     /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1677     if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1678         FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1679     }
1680     if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1681         FIXME("Tweening is only valid with vertex shaders\n");
1682     }
1683     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1684         FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1685     }
1686     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1687         FIXME("Extended attributes are only valid with vertex shaders\n");
1688     }
1689 #undef BUFFER_OR_DATA
1690
1691 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1692         fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1693 #endif
1694
1695          /* vertex shaders */
1696
1697         /* If the only vertex data used by the shader is supported by OpenGL then*/
1698         if ((!useVertexShaderFunction  && dataLocations->u.s.pSize.lpData == NULL
1699                 && dataLocations->u.s.diffuse.lpData == NULL  && dataLocations->u.s.specular.lpData == NULL) 
1700                 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1701
1702             /* Load the vertex data using named arrays */
1703             TRACE("(%p) Loading vertex data\n", This);
1704             loadVertexData(iface, dataLocations);
1705
1706         } else /* Otherwise */
1707             if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1708
1709             /* load the array data using ordinal mapping */
1710             loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1711
1712         } else { /* If this happens we must drawStridedSlow later on */ 
1713                 TRACE("Not loading vertex data\n");
1714         }
1715
1716         TRACE("Loaded arrays\n");
1717
1718         if (useVertexShaderFunction) {
1719             int i;
1720             GLint errPos;
1721
1722             FIXME("Using vertex shader\n");
1723
1724             /* Bind the vertex program */
1725             GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
1726             checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1727
1728             /* and enable gl vertex shaders */
1729             glEnable(GL_VERTEX_PROGRAM_ARB);
1730             checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1731             TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
1732
1733             /* Update the constants */
1734             for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1735                 /* TODO: add support for Integer and Boolean constants */
1736                 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1737                 TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->vertexShaderConstantF[i *4 ], This->stateBlock->vertexShaderConstantF[i * 4 + 1], This->stateBlock->vertexShaderConstantF[i *4 + 2], This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
1738                 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1739             }
1740             /* TODO: Vertex Shader 8 constants*/
1741
1742             /* always draw strided fast if a vertex shader is being used */
1743             drawStridedFast(iface, numberOfIndicies, glPrimType,
1744                         idxData, idxSize, minIndex, StartIdx);
1745
1746             /* check for any errors */
1747             glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1748             if (errPos != -1) {
1749                 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1750             }
1751
1752             /* disable any attribs */
1753             if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1754                 GLint maxAttribs;
1755                 int i;
1756                 /* Leave all the attribs disabled */
1757                 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1758                 /* MESA does not support it right not */
1759                 if (glGetError() != GL_NO_ERROR)
1760                 maxAttribs = 16;
1761                 for (i = 0; i < maxAttribs; i++) {
1762                     GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1763                     checkGLcall("glDisableVertexAttribArrayARB(reg);");
1764                 }
1765             }
1766
1767             /* Done */
1768             glDisable(GL_VERTEX_PROGRAM_ARB);
1769         } else {
1770
1771             /* DirectX colours are in a different format to opengl colours
1772             so if diffuse or specular are used then we need to use drawStridedSlow 
1773             to correct the colours */
1774             if ((dataLocations->u.s.pSize.lpData           != NULL)
1775                || (dataLocations->u.s.diffuse.lpData      != NULL)
1776                || (dataLocations->u.s.specular.lpData      != NULL)) {
1777                 /* TODO: replace drawStridedSlow with veretx fixups */
1778 #if 1
1779
1780                 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1781                                 idxData, idxSize, minIndex,  StartIdx) ;
1782                             
1783 /*
1784  *                drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1785  *                            idxData, idxSize, minIndex, StartIdx);
1786  */
1787 #endif
1788             } else {
1789                 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1790                 drawStridedFast(iface, numberOfIndicies, glPrimType,
1791                     idxData, idxSize, minIndex, StartIdx);
1792             }
1793         }
1794     }
1795 }
1796
1797 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1798
1799     /* Dump out what parts we have supplied */
1800     TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1801     TRACE_STRIDED((dataLocations), position);
1802     TRACE_STRIDED((dataLocations), blendWeights);
1803     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1804     TRACE_STRIDED((dataLocations), normal);
1805     TRACE_STRIDED((dataLocations), pSize);
1806     TRACE_STRIDED((dataLocations), diffuse);
1807     TRACE_STRIDED((dataLocations), specular);
1808     TRACE_STRIDED((dataLocations), texCoords[0]);
1809     TRACE_STRIDED((dataLocations), texCoords[1]);
1810     TRACE_STRIDED((dataLocations), texCoords[2]);
1811     TRACE_STRIDED((dataLocations), texCoords[3]);
1812     TRACE_STRIDED((dataLocations), texCoords[4]);
1813     TRACE_STRIDED((dataLocations), texCoords[5]);
1814     TRACE_STRIDED((dataLocations), texCoords[6]);
1815     TRACE_STRIDED((dataLocations), texCoords[7]);
1816     TRACE_STRIDED((dataLocations), position2);
1817     TRACE_STRIDED((dataLocations), normal2);
1818     TRACE_STRIDED((dataLocations), tangent);
1819     TRACE_STRIDED((dataLocations), binormal);
1820     TRACE_STRIDED((dataLocations), tessFactor);
1821     TRACE_STRIDED((dataLocations), fog);
1822     TRACE_STRIDED((dataLocations), depth);
1823     TRACE_STRIDED((dataLocations), sample);
1824
1825     return;
1826
1827 }
1828
1829 /* uploads textures and setup texture states ready for rendering */
1830 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1831
1832     unsigned int i;
1833 /**
1834 * OK, here we clear down any old junk iect in the context
1835 * enable the new texture and apply any state changes:
1836 *
1837 * Loop through all textures
1838 * select texture unit
1839 * if there is a texture bound to that unit then..
1840 * disable all textures types on that unit
1841 * enable and bind the texture that is bound to that unit.
1842 * otherwise disable all texture types on that unit.
1843 **/
1844     /* upload the textures */
1845     for (i = 0; i< GL_LIMITS(textures); ++i) {
1846         /* Bind the texture to the stage here */
1847         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1848             GLACTIVETEXTURE(i);
1849         } else if (0 < i) {
1850             /* This isn't so much a warn as a message to the user about lack of hardware support */
1851             WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1852         }
1853
1854         /* don't bother with textures that have a colorop of disable */
1855         if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1856             if (This->stateBlock->textures[i] != NULL) {
1857
1858                 glDisable(GL_TEXTURE_1D);
1859                 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1860                 /* disable all texture states that aren't the selected textures' dimension */
1861                 switch(This->stateBlock->textureDimensions[i]) {
1862                 case GL_TEXTURE_2D:
1863                     glDisable(GL_TEXTURE_3D);
1864                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1865                 break;
1866                 case GL_TEXTURE_3D:
1867                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1868                     glDisable(GL_TEXTURE_2D);
1869                 break;
1870                 case GLTEXTURECUBEMAP:
1871                     glDisable(GL_TEXTURE_2D);
1872                     glDisable(GL_TEXTURE_3D);
1873                 break;
1874                 }
1875                 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1876                 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1877                     glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1878                 } else {
1879                     glEnable(This->stateBlock->textureDimensions[i]);
1880                 }
1881                   /* Load up the texture now */
1882                 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1883                 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1884                 /* this is a stub function representing the state blocks
1885                  * being separated here we are only updating the texture
1886                  * state changes, other objects and units get updated when
1887                  * they change (or need to be updated), e.g. states that
1888                  * relate to a context member line the texture unit are
1889                  * only updated when the context needs updating
1890                  */
1891                 /* Tell the abse texture to sync it's states */
1892                 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1893
1894               }
1895             /* Bind a default texture if no texture has been set, but colour-op is enabled */
1896             else {
1897                 glDisable(GL_TEXTURE_2D);
1898                 glDisable(GL_TEXTURE_3D);
1899                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1900                 glEnable(GL_TEXTURE_1D);
1901                 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1902                 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1903             }
1904 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1905         dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1906             set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1907                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1908                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1909                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1910             /* alphaop */
1911             set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1912                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1913                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1914                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1915         } else {
1916
1917             /* no colorop so disable all the texture states */
1918             glDisable(GL_TEXTURE_1D);
1919             glDisable(GL_TEXTURE_2D);
1920             glDisable(GL_TEXTURE_3D);
1921             glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1922           }
1923
1924       }
1925
1926 }
1927
1928 /* Routine common to the draw primitive and draw indexed primitive routines */
1929 void drawPrimitive(IWineD3DDevice *iface,
1930                     int PrimitiveType,
1931                     long NumPrimitives,
1932                     /* for Indexed: */
1933                     long  StartVertexIndex,
1934                     UINT  numberOfVertices,
1935                     long  StartIdx,
1936                     short idxSize,
1937                     const void *idxData,
1938                     int   minIndex) {
1939
1940     BOOL                          rc = FALSE;
1941     DWORD                         fvf = 0;
1942     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1943     BOOL                          useVertexShaderFunction = FALSE;
1944     BOOL                          isLightingOn = FALSE;
1945     Direct3DVertexStridedData     dataLocations;
1946     int                           useHW = FALSE;
1947
1948     useVertexShaderFunction = This->stateBlock->vertexShader != NULL ? wined3d_settings.vs_mode != VS_NONE ? ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->function != NULL ? TRUE: FALSE : FALSE : FALSE;
1949
1950     if (This->stateBlock->vertexDecl == NULL) {
1951         /* Work out what the FVF should look like */
1952         rc = initializeFVF(iface, &fvf);
1953         if (rc) return;
1954     } else {
1955         TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1956     }
1957
1958     /* Ok, we will be updating the screen from here onwards so grab the lock */
1959     ENTER_GL();
1960
1961 #if 0 /* TODO: vertex and pixel shaders */
1962     /* If we will be using a pixel, do some initialization for it */
1963     if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1964         TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1965         memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1966
1967         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1968         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1969         glEnable(GL_FRAGMENT_PROGRAM_ARB);
1970         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1971
1972         /* init Constants */
1973         if (This->stateBlock->Changed.pixelShaderConstant) {
1974             TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1975             IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1976         }
1977         /* Update the constants */
1978         for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1979             GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1980             checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1981         }
1982     }
1983 #endif /* TODO: vertex and pixel shaders */
1984
1985     /* Initialize all values to null */
1986     memset(&dataLocations, 0x00, sizeof(dataLocations));
1987     /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
1988
1989     if (This->stateBlock->vertexDecl != NULL) {
1990         TRACE("================ Vertex Declaration  ===================\n");
1991         primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1992     } else {
1993         TRACE("================ FVF ===================\n");
1994         primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1995     }
1996
1997     /* write out some debug information*/
1998     drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1999
2000     /* Setup transform matrices and sort out */
2001     if (useHW) {
2002         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2003         So make sure lighting is disabled. */
2004         isLightingOn = glIsEnabled(GL_LIGHTING);
2005         glDisable(GL_LIGHTING);
2006         checkGLcall("glDisable(GL_LIGHTING);");
2007         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2008     } else {
2009         isLightingOn = primitiveInitState(iface,
2010                                           fvf & D3DFVF_XYZRHW,
2011                                           !(fvf & D3DFVF_NORMAL),
2012                                           useVertexShaderFunction);
2013     }
2014
2015     /* Now initialize the materials state */
2016     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2017
2018     drawPrimitiveUploadTextures(This);
2019
2020
2021     {
2022         GLenum glPrimType;
2023         /* Ok, Work out which primitive is requested and how many vertexes that
2024            will be                                                              */
2025         UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2026 #if 0 /* debugging code... just information not an error */
2027         if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2028             FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2029         }
2030 #endif
2031         if (numberOfVertices == 0 )
2032             numberOfVertices = calculatedNumberOfindices;
2033         drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2034     }
2035
2036     /* If vertex shaders or no normals, restore previous lighting state */
2037     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2038         if (isLightingOn) glEnable(GL_LIGHTING);
2039         else glDisable(GL_LIGHTING);
2040         TRACE("Restored lighting to original state\n");
2041     }
2042
2043 #if 0 /* TODO: vertex and pixel shaders */
2044     if (pixel_shader)
2045     {
2046 #if 0
2047       GLint errPos;
2048       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2049       if (errPos != -1)
2050         FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2051 #endif
2052       glDisable(GL_FRAGMENT_PROGRAM_ARB);
2053     }
2054 #endif
2055
2056     /* Finshed updating the screen, restore lock */
2057     LEAVE_GL();
2058     TRACE("Done all gl drawing\n");
2059
2060     /* Diagnostics */
2061 #if defined(SHOW_FRAME_MAKEUP)
2062     {
2063         if (isDumpingFrames) {
2064             D3DLOCKED_RECT r;
2065             char buffer[80];
2066             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
2067             sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
2068             TRACE("Saving screenshot %s\n", buffer);
2069             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2070             IWineD3DSurface_UnlockRect(This->renderTarget);
2071
2072 #if defined(SHOW_TEXTURE_MAKEUP)
2073            {
2074             IWineD3DSurface *pSur;
2075             int textureNo;
2076             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2077                 if (This->stateBlock->textures[textureNo] != NULL) {
2078                     sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
2079                     TRACE("Saving texture %s\n", buffer);
2080                     IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur);
2081                     IWineD3DSurface_SaveSnapshot(pSur, buffer);
2082                     IWineD3DSurface_Release(pSur);
2083                 }
2084             }
2085            }
2086 #endif
2087            ++primCounter;
2088         }
2089     }
2090 #endif
2091 }