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