Added Dutch translations.
[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 = NULL;
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 (coordIdx < 0) {
1327                     FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1328                     continue;
1329                 }
1330
1331                 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1332                 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1333                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1334                     continue;
1335                 } else {
1336
1337                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1338
1339                     /* The coords to supply depend completely on the fvf / vertex shader */
1340                     switch (coordsToUse) {
1341                     case 4: q = ptrToCoords[3]; /* drop through */
1342                     case 3: r = ptrToCoords[2]; /* drop through */
1343                     case 2: t = ptrToCoords[1]; /* drop through */
1344                     case 1: s = ptrToCoords[0];
1345                     }
1346
1347                     /* Projected is more 'fun' - Move the last coord to the 'q'
1348                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1349                     if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1350                         (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1351
1352                         if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1353                             switch (coordsToUse) {
1354                             case 0:  /* Drop Through */
1355                             case 1:
1356                                 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1357                                 break;
1358                             case 2:
1359                                 q = t;
1360                                 t = 0.0;
1361                                 coordsToUse = 4;
1362                                 break;
1363                             case 3:
1364                                 q = r;
1365                                 r = 0.0;
1366                                 coordsToUse = 4;
1367                                 break;
1368                             case 4:  /* Nop here */
1369                                 break;
1370                             default:
1371                                 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1372                                       This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1373                             }
1374                         }
1375                     }
1376
1377                     switch (coordsToUse) {   /* Supply the provided texture coords */
1378                     case D3DTTFF_COUNT1:
1379                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1380                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1381                             GLMULTITEXCOORD1F(textureNo, s);
1382                         } else {
1383                             glTexCoord1f(s);
1384                         }
1385                         break;
1386                     case D3DTTFF_COUNT2:
1387                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1388                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1389                             GLMULTITEXCOORD2F(textureNo, s, t);
1390                         } else {
1391                             glTexCoord2f(s, t);
1392                         }
1393                         break;
1394                     case D3DTTFF_COUNT3:
1395                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1396                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1397                             GLMULTITEXCOORD3F(textureNo, s, t, r);
1398                         } else {
1399                             glTexCoord3f(s, t, r);
1400                         }
1401                         break;
1402                     case D3DTTFF_COUNT4:
1403                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1404                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1405                             GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1406                         } else {
1407                             glTexCoord4f(s, t, r, q);
1408                         }
1409                         break;
1410                     default:
1411                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1412                     }
1413                 }
1414             }
1415         } /* End of textures */
1416
1417         /* Diffuse -------------------------------- */
1418         if (sd->u.s.diffuse.lpData != NULL) {
1419           glColor4ub(D3DCOLOR_B_R(diffuseColor),
1420                      D3DCOLOR_B_G(diffuseColor),
1421                      D3DCOLOR_B_B(diffuseColor),
1422                      D3DCOLOR_B_A(diffuseColor));
1423             VTRACE(("glColor4ub: r,g,b,a=%u,%u,%u,%u\n", 
1424                     D3DCOLOR_B_R(diffuseColor),
1425                     D3DCOLOR_B_G(diffuseColor),
1426                     D3DCOLOR_B_B(diffuseColor),
1427                     D3DCOLOR_B_A(diffuseColor)));
1428         } else {
1429             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1430         }
1431
1432         /* Specular ------------------------------- */
1433         if (sd->u.s.specular.lpData != NULL) {
1434             VTRACE(("glSecondaryColor4ub: r,g,b=%u,%u,%u\n", 
1435                     D3DCOLOR_B_R(specularColor), 
1436                     D3DCOLOR_B_G(specularColor), 
1437                     D3DCOLOR_B_B(specularColor)));
1438             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1439                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1440                            D3DCOLOR_B_R(specularColor),
1441                            D3DCOLOR_B_G(specularColor),
1442                            D3DCOLOR_B_B(specularColor));
1443             } else {
1444                 /* Do not worry if specular colour missing and disable request */
1445                 VTRACE(("Specular color extensions not supplied\n"));
1446             }
1447         } else {
1448             if (vx_index == 0) {
1449                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1450                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1451                 } else {
1452                     /* Do not worry if specular colour missing and disable request */
1453                     VTRACE(("Specular color extensions not supplied\n"));
1454                 }
1455             }
1456         }
1457
1458         /* Normal -------------------------------- */
1459         if (sd->u.s.normal.lpData != NULL) {
1460             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1461             glNormal3f(nx, ny, nz);
1462         } else {
1463             if (vx_index == 0) glNormal3f(0, 0, 1);
1464         }
1465
1466         /* Position -------------------------------- */
1467         if (sd->u.s.position.lpData != NULL) {
1468             if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1469                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1470                 glVertex3f(x, y, z);
1471             } else {
1472                 GLfloat w = 1.0 / rhw;
1473                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1474                 glVertex4f(x*w, y*w, z*w, w);
1475             }
1476         }
1477
1478         /* For non indexed mode, step onto next parts */
1479         if (idxData == NULL) {
1480             ++SkipnStrides;
1481         }
1482     }
1483
1484     glEnd();
1485     checkGLcall("glEnd and previous calls");
1486 }
1487
1488 #if 0 /* TODO: Software/Hardware vertex blending support */
1489 /*
1490  * Draw with emulated vertex shaders
1491  * Note: strided data is uninitialized, as we need to pass the vertex
1492  *     shader directly as ordering irs yet
1493  */
1494 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1495                      int PrimitiveType, ULONG NumPrimitives,
1496                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1497
1498     unsigned int               textureNo    = 0;
1499     GLenum                     glPrimType   = GL_POINTS;
1500     int                        NumVertexes  = NumPrimitives;
1501     const short               *pIdxBufS     = NULL;
1502     const long                *pIdxBufL     = NULL;
1503     LONG                       SkipnStrides = 0;
1504     LONG                       vx_index;
1505     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1506     float rhw = 0.0f;                      /* rhw                        */
1507     float ptSize = 0.0f;                   /* Point size                 */
1508     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1509     int   numcoords[8];                    /* Number of coords           */
1510     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1511
1512     IDirect3DVertexShaderImpl* vertexShader = NULL;
1513
1514     TRACE("Using slow software vertex shader code\n");
1515
1516     /* Variable Initialization */
1517     if (idxData != NULL) {
1518         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1519         else pIdxBufL = (const long *) idxData;
1520     }
1521
1522     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1523     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1524
1525     /* Retrieve the VS information */
1526     vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1527
1528     /* Start drawing in GL */
1529     VTRACE(("glBegin(%x)\n", glPrimType));
1530     glBegin(glPrimType);
1531
1532     /* For each primitive */
1533     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1534
1535         /* For indexed data, we need to go a few more strides in */
1536         if (idxData != NULL) {
1537
1538             /* Indexed so work out the number of strides to skip */
1539             if (idxSize == 2) {
1540                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1541                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1542             } else {
1543                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1544                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1545             }
1546         }
1547
1548         /* Fill the vertex shader input */
1549         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1550
1551         /* Initialize the output fields to the same defaults as it would normally have */
1552         memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1553         vertexShader->output.oD[0].x = 1.0;
1554         vertexShader->output.oD[0].y = 1.0;
1555         vertexShader->output.oD[0].z = 1.0;
1556         vertexShader->output.oD[0].w = 1.0;
1557
1558         /* Now execute the vertex shader */
1559         IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1560
1561         /*
1562         TRACE_VECTOR(vertexShader->output.oPos);
1563         TRACE_VECTOR(vertexShader->output.oD[0]);
1564         TRACE_VECTOR(vertexShader->output.oD[1]);
1565         TRACE_VECTOR(vertexShader->output.oT[0]);
1566         TRACE_VECTOR(vertexShader->output.oT[1]);
1567         TRACE_VECTOR(vertexShader->input.V[0]);
1568         TRACE_VECTOR(vertexShader->data->C[0]);
1569         TRACE_VECTOR(vertexShader->data->C[1]);
1570         TRACE_VECTOR(vertexShader->data->C[2]);
1571         TRACE_VECTOR(vertexShader->data->C[3]);
1572         TRACE_VECTOR(vertexShader->data->C[4]);
1573         TRACE_VECTOR(vertexShader->data->C[5]);
1574         TRACE_VECTOR(vertexShader->data->C[6]);
1575         TRACE_VECTOR(vertexShader->data->C[7]);
1576         */
1577
1578         /* Extract out the output */
1579         /* FIXME: Fog coords? */
1580         x = vertexShader->output.oPos.x;
1581         y = vertexShader->output.oPos.y;
1582         z = vertexShader->output.oPos.z;
1583         rhw = vertexShader->output.oPos.w;
1584         ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1585
1586         /** Update textures coords using vertexShader->output.oT[0->7] */
1587         memset(texcoords, 0x00, sizeof(texcoords));
1588         memset(numcoords, 0x00, sizeof(numcoords));
1589         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1590             if (This->stateBlock->textures[textureNo] != NULL) {
1591                texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1592                texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1593                texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1594                texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1595                if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1596                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1597                } else {
1598                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1599                    case D3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1600                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1601                    default:                     numcoords[textureNo] = 4;
1602                    }
1603                }
1604             } else {
1605                 numcoords[textureNo] = 0;
1606             }
1607         }
1608
1609         /* Draw using this information */
1610         draw_vertex(iface,
1611                     TRUE, x, y, z, rhw,
1612                     TRUE, 0.0f, 0.0f, 1.0f,
1613                     TRUE, (float*) &vertexShader->output.oD[0],
1614                     TRUE, (float*) &vertexShader->output.oD[1],
1615                     FALSE, ptSize,         /* FIXME: Change back when supported */
1616                     texcoords, numcoords);
1617
1618         /* For non indexed mode, step onto next parts */
1619         if (idxData == NULL) {
1620            ++SkipnStrides;
1621         }
1622
1623     } /* for each vertex */
1624
1625     glEnd();
1626     checkGLcall("glEnd and previous calls");
1627 }
1628
1629 #endif
1630
1631 void inline  drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1632 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1633     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1634
1635     /* Now draw the graphics to the screen */
1636     if  (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1637         FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1638         /* Ideally, we should have software FV and hardware VS, possibly
1639            depending on the device type? */
1640 #if 0 /* TODO: vertex and pixel shaders */
1641         drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1642                     idxData, idxSize, minIndex, StartIdx);
1643 #endif
1644
1645     } else {
1646
1647         /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1648         int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1649         int endStride = startStride;
1650         TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1651
1652 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1653         if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1654             int t;
1655             if (idxSize == 2) {
1656                 unsigned short *index = (unsigned short *)idxData;
1657                 index += StartIdx;
1658                 for (t = 0 ; t < numberOfIndicies; t++) {
1659                     if (startStride >  *index)
1660                         startStride = *index;
1661                     if (endStride < *index)
1662                         endStride = *index;
1663                     index++;
1664                 }
1665             } else {  /* idxSize == 4 */
1666                 unsigned int *index = (unsigned int *)idxData;
1667                 index += StartIdx;
1668                 for (t = 0 ; t < numberOfIndicies; t++) {
1669                     if (startStride > *index)
1670                         startStride = *index;
1671                     if (endStride < *index)
1672                         endStride = *index;
1673                     index++;
1674                 }
1675             }
1676         } else {
1677             endStride += numberOfvertices -1;
1678         }
1679 #endif
1680         TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1681         /* pre-transform verticex */
1682         /* TODO: Caching, VBO's etc.. */
1683
1684 /* Generate some fixme's if unsupported functionality is being used */
1685 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1686     /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1687     if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1688         FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1689     }
1690     if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1691         FIXME("Tweening is only valid with vertex shaders\n");
1692     }
1693     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1694         FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1695     }
1696     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1697         FIXME("Extended attributes are only valid with vertex shaders\n");
1698     }
1699 #undef BUFFER_OR_DATA
1700
1701 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1702         fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1703 #endif
1704
1705          /* vertex shaders */
1706
1707         /* If the only vertex data used by the shader is supported by OpenGL then*/
1708         if ((!useVertexShaderFunction  && dataLocations->u.s.pSize.lpData == NULL
1709                 && dataLocations->u.s.diffuse.lpData == NULL  && dataLocations->u.s.specular.lpData == NULL) 
1710                 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1711
1712             /* Load the vertex data using named arrays */
1713             TRACE("(%p) Loading vertex data\n", This);
1714             loadVertexData(iface, dataLocations);
1715
1716         } else /* Otherwise */
1717             if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1718
1719             /* load the array data using ordinal mapping */
1720             loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1721
1722         } else { /* If this happens we must drawStridedSlow later on */ 
1723                 TRACE("Not loading vertex data\n");
1724         }
1725
1726         TRACE("Loaded arrays\n");
1727
1728         if (useVertexShaderFunction) {
1729             int i;
1730             GLint errPos;
1731
1732             FIXME("Using vertex shader\n");
1733
1734             /* Bind the vertex program */
1735             GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
1736             checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1737
1738             /* and enable gl vertex shaders */
1739             glEnable(GL_VERTEX_PROGRAM_ARB);
1740             checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1741             TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
1742
1743             /* Update the constants */
1744             for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1745                 /* TODO: add support for Integer and Boolean constants */
1746                 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1747                 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]);
1748                 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1749             }
1750             /* TODO: Vertex Shader 8 constants*/
1751
1752             /* always draw strided fast if a vertex shader is being used */
1753             drawStridedFast(iface, numberOfIndicies, glPrimType,
1754                         idxData, idxSize, minIndex, StartIdx);
1755
1756             /* check for any errors */
1757             glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1758             if (errPos != -1) {
1759                 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1760             }
1761
1762             /* disable any attribs */
1763             if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1764                 GLint maxAttribs;
1765                 int i;
1766                 /* Leave all the attribs disabled */
1767                 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1768                 /* MESA does not support it right not */
1769                 if (glGetError() != GL_NO_ERROR)
1770                 maxAttribs = 16;
1771                 for (i = 0; i < maxAttribs; i++) {
1772                     GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1773                     checkGLcall("glDisableVertexAttribArrayARB(reg);");
1774                 }
1775             }
1776
1777             /* Done */
1778             glDisable(GL_VERTEX_PROGRAM_ARB);
1779         } else {
1780
1781             /* DirectX colours are in a different format to opengl colours
1782             so if diffuse or specular are used then we need to use drawStridedSlow 
1783             to correct the colours */
1784             if ((dataLocations->u.s.pSize.lpData           != NULL)
1785                || (dataLocations->u.s.diffuse.lpData      != NULL)
1786                || (dataLocations->u.s.specular.lpData      != NULL)) {
1787                 /* TODO: replace drawStridedSlow with veretx fixups */
1788 #if 1
1789
1790                 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1791                                 idxData, idxSize, minIndex,  StartIdx) ;
1792                             
1793 /*
1794  *                drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1795  *                            idxData, idxSize, minIndex, StartIdx);
1796  */
1797 #endif
1798             } else {
1799                 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1800                 drawStridedFast(iface, numberOfIndicies, glPrimType,
1801                     idxData, idxSize, minIndex, StartIdx);
1802             }
1803         }
1804     }
1805 }
1806
1807 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1808
1809     /* Dump out what parts we have supplied */
1810     TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1811     TRACE_STRIDED((dataLocations), position);
1812     TRACE_STRIDED((dataLocations), blendWeights);
1813     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1814     TRACE_STRIDED((dataLocations), normal);
1815     TRACE_STRIDED((dataLocations), pSize);
1816     TRACE_STRIDED((dataLocations), diffuse);
1817     TRACE_STRIDED((dataLocations), specular);
1818     TRACE_STRIDED((dataLocations), texCoords[0]);
1819     TRACE_STRIDED((dataLocations), texCoords[1]);
1820     TRACE_STRIDED((dataLocations), texCoords[2]);
1821     TRACE_STRIDED((dataLocations), texCoords[3]);
1822     TRACE_STRIDED((dataLocations), texCoords[4]);
1823     TRACE_STRIDED((dataLocations), texCoords[5]);
1824     TRACE_STRIDED((dataLocations), texCoords[6]);
1825     TRACE_STRIDED((dataLocations), texCoords[7]);
1826     TRACE_STRIDED((dataLocations), position2);
1827     TRACE_STRIDED((dataLocations), normal2);
1828     TRACE_STRIDED((dataLocations), tangent);
1829     TRACE_STRIDED((dataLocations), binormal);
1830     TRACE_STRIDED((dataLocations), tessFactor);
1831     TRACE_STRIDED((dataLocations), fog);
1832     TRACE_STRIDED((dataLocations), depth);
1833     TRACE_STRIDED((dataLocations), sample);
1834
1835     return;
1836
1837 }
1838
1839 /* uploads textures and setup texture states ready for rendering */
1840 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1841
1842     unsigned int i;
1843 /**
1844 * OK, here we clear down any old junk iect in the context
1845 * enable the new texture and apply any state changes:
1846 *
1847 * Loop through all textures
1848 * select texture unit
1849 * if there is a texture bound to that unit then..
1850 * disable all textures types on that unit
1851 * enable and bind the texture that is bound to that unit.
1852 * otherwise disable all texture types on that unit.
1853 **/
1854     /* upload the textures */
1855     for (i = 0; i< GL_LIMITS(textures); ++i) {
1856         /* Bind the texture to the stage here */
1857         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1858             GLACTIVETEXTURE(i);
1859         } else if (0 < i) {
1860             /* This isn't so much a warn as a message to the user about lack of hardware support */
1861             WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1862         }
1863
1864         /* don't bother with textures that have a colorop of disable */
1865         if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1866             if (This->stateBlock->textures[i] != NULL) {
1867
1868                 glDisable(GL_TEXTURE_1D);
1869                 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1870                 /* disable all texture states that aren't the selected textures' dimension */
1871                 switch(This->stateBlock->textureDimensions[i]) {
1872                 case GL_TEXTURE_2D:
1873                     glDisable(GL_TEXTURE_3D);
1874                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1875                 break;
1876                 case GL_TEXTURE_3D:
1877                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1878                     glDisable(GL_TEXTURE_2D);
1879                 break;
1880                 case GLTEXTURECUBEMAP:
1881                     glDisable(GL_TEXTURE_2D);
1882                     glDisable(GL_TEXTURE_3D);
1883                 break;
1884                 }
1885                 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1886                 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1887                     glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1888                 } else {
1889                     glEnable(This->stateBlock->textureDimensions[i]);
1890                 }
1891                   /* Load up the texture now */
1892                 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1893                 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1894                 /* this is a stub function representing the state blocks
1895                  * being separated here we are only updating the texture
1896                  * state changes, other objects and units get updated when
1897                  * they change (or need to be updated), e.g. states that
1898                  * relate to a context member line the texture unit are
1899                  * only updated when the context needs updating
1900                  */
1901                 /* Tell the abse texture to sync it's states */
1902                 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1903
1904               }
1905             /* Bind a default texture if no texture has been set, but colour-op is enabled */
1906             else {
1907                 glDisable(GL_TEXTURE_2D);
1908                 glDisable(GL_TEXTURE_3D);
1909                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1910                 glEnable(GL_TEXTURE_1D);
1911                 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1912                 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1913             }
1914 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1915         dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1916             set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1917                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1918                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1919                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1920             /* alphaop */
1921             set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1922                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1923                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1924                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1925         } else {
1926
1927             /* no colorop so disable all the texture states */
1928             glDisable(GL_TEXTURE_1D);
1929             glDisable(GL_TEXTURE_2D);
1930             glDisable(GL_TEXTURE_3D);
1931             glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1932           }
1933
1934       }
1935
1936 }
1937
1938 /* Routine common to the draw primitive and draw indexed primitive routines */
1939 void drawPrimitive(IWineD3DDevice *iface,
1940                     int PrimitiveType,
1941                     long NumPrimitives,
1942                     /* for Indexed: */
1943                     long  StartVertexIndex,
1944                     UINT  numberOfVertices,
1945                     long  StartIdx,
1946                     short idxSize,
1947                     const void *idxData,
1948                     int   minIndex) {
1949
1950     BOOL                          rc = FALSE;
1951     DWORD                         fvf = 0;
1952     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1953     BOOL                          useVertexShaderFunction = FALSE;
1954     BOOL                          isLightingOn = FALSE;
1955     Direct3DVertexStridedData     dataLocations;
1956     int                           useHW = FALSE;
1957
1958     if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE 
1959             &&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->function != NULL 
1960             && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
1961         useVertexShaderFunction = TRUE;
1962     } else {
1963         useVertexShaderFunction = FALSE;
1964     }
1965
1966     if (This->stateBlock->vertexDecl == NULL) {
1967         /* Work out what the FVF should look like */
1968         rc = initializeFVF(iface, &fvf);
1969         if (rc) return;
1970     } else {
1971         TRACE("(%p) : using vertex declaration %p\n", iface, This->stateBlock->vertexDecl);
1972     }
1973
1974     /* Ok, we will be updating the screen from here onwards so grab the lock */
1975     ENTER_GL();
1976
1977 #if 0 /* TODO: vertex and pixel shaders */
1978     /* If we will be using a pixel, do some initialization for it */
1979     if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1980         TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1981         memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1982
1983         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1984         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1985         glEnable(GL_FRAGMENT_PROGRAM_ARB);
1986         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1987
1988         /* init Constants */
1989         if (This->stateBlock->Changed.pixelShaderConstant) {
1990             TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1991             IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1992         }
1993         /* Update the constants */
1994         for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1995             GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1996             checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1997         }
1998     }
1999 #endif /* TODO: vertex and pixel shaders */
2000
2001     /* Initialize all values to null */
2002     memset(&dataLocations, 0x00, sizeof(dataLocations));
2003     /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2004
2005     if (This->stateBlock->vertexDecl != NULL) {
2006         TRACE("================ Vertex Declaration  ===================\n");
2007         primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
2008     } else {
2009         TRACE("================ FVF ===================\n");
2010         primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
2011     }
2012
2013     /* write out some debug information*/
2014     drawPrimitiveTraceDataLocations(&dataLocations, fvf);
2015
2016     /* Setup transform matrices and sort out */
2017     if (useHW) {
2018         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2019         So make sure lighting is disabled. */
2020         isLightingOn = glIsEnabled(GL_LIGHTING);
2021         glDisable(GL_LIGHTING);
2022         checkGLcall("glDisable(GL_LIGHTING);");
2023         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2024     } else {
2025         isLightingOn = primitiveInitState(iface,
2026                                           fvf & D3DFVF_XYZRHW,
2027                                           !(fvf & D3DFVF_NORMAL),
2028                                           useVertexShaderFunction);
2029     }
2030
2031     /* Now initialize the materials state */
2032     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2033
2034     drawPrimitiveUploadTextures(This);
2035
2036
2037     {
2038         GLenum glPrimType;
2039         /* Ok, Work out which primitive is requested and how many vertexes that
2040            will be                                                              */
2041         UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2042 #if 0 /* debugging code... just information not an error */
2043         if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2044             FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2045         }
2046 #endif
2047         if (numberOfVertices == 0 )
2048             numberOfVertices = calculatedNumberOfindices;
2049         drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2050     }
2051
2052     /* If vertex shaders or no normals, restore previous lighting state */
2053     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2054         if (isLightingOn) glEnable(GL_LIGHTING);
2055         else glDisable(GL_LIGHTING);
2056         TRACE("Restored lighting to original state\n");
2057     }
2058
2059 #if 0 /* TODO: vertex and pixel shaders */
2060     if (pixel_shader)
2061     {
2062 #if 0
2063       GLint errPos;
2064       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2065       if (errPos != -1)
2066         FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2067 #endif
2068       glDisable(GL_FRAGMENT_PROGRAM_ARB);
2069     }
2070 #endif
2071
2072     /* Finshed updating the screen, restore lock */
2073     LEAVE_GL();
2074     TRACE("Done all gl drawing\n");
2075
2076     /* Diagnostics */
2077 #ifdef SHOW_FRAME_MAKEUP
2078     {
2079         static long int primCounter = 0;
2080         /* NOTE: set primCounter to the value reported by drawprim 
2081            before you want to to write frame makeup to /tmp */
2082         if (primCounter >= 0) {
2083             D3DLOCKED_RECT r;
2084             char buffer[80];
2085             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
2086             sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2087             TRACE("Saving screenshot %s\n", buffer);
2088             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2089             IWineD3DSurface_UnlockRect(This->renderTarget);
2090
2091 #ifdef SHOW_TEXTURE_MAKEUP
2092            {
2093             IWineD3DSurface *pSur;
2094             int textureNo;
2095             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2096                 if (This->stateBlock->textures[textureNo] != NULL) {
2097                     sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2098                     TRACE("Saving texture %s\n", buffer);
2099                     if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == D3DRTYPE_TEXTURE) {
2100                             IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2101                             IWineD3DSurface_SaveSnapshot(pSur, buffer);
2102                             IWineD3DSurface_Release(pSur);
2103                     } else  {
2104                         FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2105                     }
2106                 }
2107             }
2108            }
2109 #endif
2110         }
2111         TRACE("drawprim #%ld\n", primCounter);
2112         ++primCounter;
2113     }
2114 #endif
2115 }