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