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