wined3d: Allow use of pixel shaders with drawStridedSlow.
[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, WineDirect3DVertexStridedData *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 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *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, WineDirect3DVertexStridedData *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, WineDirect3DVertexStridedData *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, WineDirect3DVertexStridedData *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 < eps) && (rhw > -eps))) {
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, WineDirect3DVertexStridedData *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, WineDirect3DVertexStridedData *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) {
1793             IWineD3DVertexDeclarationImpl *vertexDeclaration;
1794             int i;
1795
1796             TRACE("Using vertex shader\n");
1797
1798             /* Bind the vertex program */
1799             GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
1800                 ((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",
1807                 This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
1808
1809             /* Vertex Shader 8 constants */
1810             vertexDeclaration = (IWineD3DVertexDeclarationImpl *)
1811                 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
1812             if (vertexDeclaration != NULL) {
1813                 float *constants = vertexDeclaration->constants;
1814                 if (constants != NULL) {
1815                     for (i = 0; i <=  WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
1816                         TRACE_(d3d_shader)("Not loading constants %u = %f %f %f %f\n", i,
1817                         constants[i * 4], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]);
1818                         GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
1819                     }
1820                 }
1821             }
1822
1823             /* Update the constants */
1824             for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
1825                 /* TODO: add support for Integer and Boolean constants */
1826                 if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
1827
1828                     GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i,
1829                         &This->stateBlock->vertexShaderConstantF[i * 4]));
1830
1831                     TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n", i,
1832                         This->stateBlock->vertexShaderConstantF[i * 4],
1833                         This->stateBlock->vertexShaderConstantF[i * 4 + 1],
1834                         This->stateBlock->vertexShaderConstantF[i * 4 + 2],
1835                         This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
1836                         checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1837                 }
1838             }
1839         }
1840
1841         if (usePixelShaderFunction) {
1842             int i;
1843
1844             TRACE("Using pixel shader\n");
1845
1846              /* Bind the fragment program */
1847              GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
1848                  ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
1849              checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
1850
1851              /* Enable OpenGL fragment programs */
1852              glEnable(GL_FRAGMENT_PROGRAM_ARB);
1853              checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1854              TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
1855                  This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
1856
1857              /* Update the constants */
1858              for (i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; ++i) {
1859                  /* TODO: add support for Integer and Boolean constants */
1860                  if (WINESHADERCNST_FLOAT == This->stateBlock->pixelShaderConstantT[i]) {
1861                      GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i,
1862                         &This->stateBlock->pixelShaderConstantF[i * 4]));
1863                      TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n", i,
1864                         This->stateBlock->pixelShaderConstantF[i * 4],
1865                         This->stateBlock->pixelShaderConstantF[i * 4 + 1],
1866                         This->stateBlock->pixelShaderConstantF[i * 4 + 2],
1867                         This->stateBlock->pixelShaderConstantF[i * 4 + 3]);
1868                      checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1869                  }
1870             }
1871         }
1872
1873         /* DirectX colours are in a different format to opengl colours
1874          * so if diffuse or specular are used then we need to use drawStridedSlow
1875          * to correct the colours */
1876         if (!useVertexShaderFunction &&
1877               ((dataLocations->u.s.pSize.lpData        != NULL)
1878            || (dataLocations->u.s.diffuse.lpData      != NULL)
1879            || (dataLocations->u.s.specular.lpData     != NULL))) {
1880             /* TODO: replace drawStridedSlow with veretx fixups */
1881
1882             drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1883                             idxData, idxSize, minIndex,  StartIdx);
1884
1885         } else {
1886             /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1887             drawStridedFast(iface, numberOfIndicies, glPrimType,
1888                 idxData, idxSize, minIndex, StartIdx);
1889         }
1890
1891         /* Cleanup vertex program */
1892         if (useVertexShaderFunction) {
1893             /* disable any attribs */
1894             if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1895                 GLint maxAttribs;
1896                 int i;
1897                 /* Leave all the attribs disabled */
1898                 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1899                 /* MESA does not support it right not */
1900                 if (glGetError() != GL_NO_ERROR)
1901                 maxAttribs = 16;
1902                 for (i = 0; i < maxAttribs; ++i) {
1903                     GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1904                     checkGLcall("glDisableVertexAttribArrayARB(reg);");
1905                 }
1906             }
1907
1908             glDisable(GL_VERTEX_PROGRAM_ARB);
1909         }
1910
1911         /* Cleanup fragment program */
1912         if (usePixelShaderFunction) {
1913             glDisable(GL_FRAGMENT_PROGRAM_ARB);
1914         }
1915     }
1916 }
1917
1918 void inline drawPrimitiveTraceDataLocations(WineDirect3DVertexStridedData *dataLocations,DWORD fvf) {
1919
1920     /* Dump out what parts we have supplied */
1921     TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1922     TRACE_STRIDED((dataLocations), position);
1923     TRACE_STRIDED((dataLocations), blendWeights);
1924     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1925     TRACE_STRIDED((dataLocations), normal);
1926     TRACE_STRIDED((dataLocations), pSize);
1927     TRACE_STRIDED((dataLocations), diffuse);
1928     TRACE_STRIDED((dataLocations), specular);
1929     TRACE_STRIDED((dataLocations), texCoords[0]);
1930     TRACE_STRIDED((dataLocations), texCoords[1]);
1931     TRACE_STRIDED((dataLocations), texCoords[2]);
1932     TRACE_STRIDED((dataLocations), texCoords[3]);
1933     TRACE_STRIDED((dataLocations), texCoords[4]);
1934     TRACE_STRIDED((dataLocations), texCoords[5]);
1935     TRACE_STRIDED((dataLocations), texCoords[6]);
1936     TRACE_STRIDED((dataLocations), texCoords[7]);
1937     TRACE_STRIDED((dataLocations), position2);
1938     TRACE_STRIDED((dataLocations), normal2);
1939     TRACE_STRIDED((dataLocations), tangent);
1940     TRACE_STRIDED((dataLocations), binormal);
1941     TRACE_STRIDED((dataLocations), tessFactor);
1942     TRACE_STRIDED((dataLocations), fog);
1943     TRACE_STRIDED((dataLocations), depth);
1944     TRACE_STRIDED((dataLocations), sample);
1945
1946     return;
1947
1948 }
1949
1950 /* uploads textures and setup texture states ready for rendering */
1951 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1952
1953     unsigned int i;
1954 /**
1955 * OK, here we clear down any old junk iect in the context
1956 * enable the new texture and apply any state changes:
1957 *
1958 * Loop through all textures
1959 * select texture unit
1960 * if there is a texture bound to that unit then..
1961 * disable all textures types on that unit
1962 * enable and bind the texture that is bound to that unit.
1963 * otherwise disable all texture types on that unit.
1964 **/
1965     /* upload the textures */
1966     for (i = 0; i< GL_LIMITS(textures); ++i) {
1967         /* Bind the texture to the stage here */
1968         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1969             GLACTIVETEXTURE(i);
1970         } else if (0 < i) {
1971             /* This isn't so much a warn as a message to the user about lack of hardware support */
1972             WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1973         }
1974
1975         /* don't bother with textures that have a colorop of disable */
1976         if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1977             if (This->stateBlock->textures[i] != NULL) {
1978
1979                 glDisable(GL_TEXTURE_1D);
1980                 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1981                 /* disable all texture states that aren't the selected textures' dimension */
1982                 switch(This->stateBlock->textureDimensions[i]) {
1983                 case GL_TEXTURE_2D:
1984                     glDisable(GL_TEXTURE_3D);
1985                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1986                 break;
1987                 case GL_TEXTURE_3D:
1988                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1989                     glDisable(GL_TEXTURE_2D);
1990                 break;
1991                 case GLTEXTURECUBEMAP:
1992                     glDisable(GL_TEXTURE_2D);
1993                     glDisable(GL_TEXTURE_3D);
1994                 break;
1995                 }
1996                 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1997                 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1998                     glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1999                 } else {
2000                     glEnable(This->stateBlock->textureDimensions[i]);
2001                 }
2002                   /* Load up the texture now */
2003                 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
2004                 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
2005                 /* this is a stub function representing the state blocks
2006                  * being separated here we are only updating the texture
2007                  * state changes, other objects and units get updated when
2008                  * they change (or need to be updated), e.g. states that
2009                  * relate to a context member line the texture unit are
2010                  * only updated when the context needs updating
2011                  */
2012                 /* Tell the abse texture to sync it's states */
2013                 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
2014
2015               }
2016             /* Bind a default texture if no texture has been set, but colour-op is enabled */
2017             else {
2018                 glDisable(GL_TEXTURE_2D);
2019                 glDisable(GL_TEXTURE_3D);
2020                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2021                 glEnable(GL_TEXTURE_1D);
2022                 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
2023                 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
2024             }
2025 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
2026         dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
2027             set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
2028                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
2029                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
2030                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
2031             /* alphaop */
2032             set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
2033                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
2034                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
2035                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
2036         } else {
2037
2038             /* no colorop so disable all the texture states */
2039             glDisable(GL_TEXTURE_1D);
2040             glDisable(GL_TEXTURE_2D);
2041             glDisable(GL_TEXTURE_3D);
2042             glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2043           }
2044
2045       }
2046
2047 }
2048
2049 /* Routine common to the draw primitive and draw indexed primitive routines */
2050 void drawPrimitive(IWineD3DDevice *iface,
2051                    int PrimitiveType,
2052                    long NumPrimitives,
2053                    /* for Indexed: */
2054                    long  StartVertexIndex,
2055                    UINT  numberOfVertices,
2056                    long  StartIdx,
2057                    short idxSize,
2058                    const void *idxData,
2059                    int   minIndex,
2060                    WineDirect3DVertexStridedData *DrawPrimStrideData) {
2061
2062     BOOL                          rc = FALSE;
2063     DWORD                         fvf = 0;
2064     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
2065     BOOL                          useVertexShaderFunction = FALSE;
2066     BOOL                          usePixelShaderFunction = FALSE;
2067     BOOL                          isLightingOn = FALSE;
2068     WineDirect3DVertexStridedData *dataLocations;
2069     int                           useHW = FALSE;
2070
2071     if (This->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE 
2072             &&((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL
2073             && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
2074         useVertexShaderFunction = TRUE;
2075     } else {
2076         useVertexShaderFunction = FALSE;
2077     }
2078
2079     if (wined3d_settings.ps_mode != PS_NONE && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)
2080             && This->stateBlock->pixelShader
2081             && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function) {
2082         usePixelShaderFunction = TRUE;
2083     }
2084
2085     if (This->stateBlock->vertexDecl == NULL) {
2086         /* Work out what the FVF should look like */
2087         rc = initializeFVF(iface, &fvf);
2088         if (rc) return;
2089     } else {
2090         TRACE("(%p) : using vertex declaration %p\n", iface, This->stateBlock->vertexDecl);
2091     }
2092
2093     /* Ok, we will be updating the screen from here onwards so grab the lock */
2094     ENTER_GL();
2095
2096     /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
2097
2098     if(DrawPrimStrideData) {
2099         TRACE("================ Strided Input ===================\n");
2100         dataLocations = DrawPrimStrideData;
2101     }
2102     else if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction  && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
2103         BOOL storeArrays = useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays == FALSE && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays == FALSE;
2104
2105         TRACE("================ Vertex Declaration  ===================\n");
2106         dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2107         if(!dataLocations) {
2108             ERR("Out of memory!\n");
2109             return;
2110         }
2111         primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fvf, storeArrays,
2112         ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
2113     } else {
2114         TRACE("================ FVF ===================\n");
2115         dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
2116         if(!dataLocations) {
2117             ERR("Out of memory!\n");
2118             return;
2119         }
2120         primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex);
2121     }
2122
2123     /* write out some debug information*/
2124     drawPrimitiveTraceDataLocations(dataLocations, fvf);
2125
2126     /* Setup transform matrices and sort out */
2127     if (useHW) {
2128         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2129         So make sure lighting is disabled. */
2130         isLightingOn = glIsEnabled(GL_LIGHTING);
2131         glDisable(GL_LIGHTING);
2132         checkGLcall("glDisable(GL_LIGHTING);");
2133         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2134     } else {
2135         isLightingOn = primitiveInitState(iface,
2136                                           fvf & D3DFVF_XYZRHW,
2137                                           !(fvf & D3DFVF_NORMAL),
2138                                           useVertexShaderFunction);
2139     }
2140
2141     /* Now initialize the materials state */
2142     init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL));
2143
2144     drawPrimitiveUploadTextures(This);
2145
2146
2147     {
2148         GLenum glPrimType;
2149         /* Ok, Work out which primitive is requested and how many vertexes that
2150            will be                                                              */
2151         UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2152 #if 0 /* debugging code... just information not an error */
2153         if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2154             FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2155         }
2156 #endif
2157         if (numberOfVertices == 0 )
2158             numberOfVertices = calculatedNumberOfindices;
2159         drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction, useHW, dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2160     }
2161
2162     if(!DrawPrimStrideData) HeapFree(GetProcessHeap(), 0, dataLocations);
2163
2164     /* If vertex shaders or no normals, restore previous lighting state */
2165     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2166         if (isLightingOn) glEnable(GL_LIGHTING);
2167         else glDisable(GL_LIGHTING);
2168         TRACE("Restored lighting to original state\n");
2169     }
2170
2171     /* Finshed updating the screen, restore lock */
2172     LEAVE_GL();
2173     TRACE("Done all gl drawing\n");
2174
2175     /* Diagnostics */
2176 #ifdef SHOW_FRAME_MAKEUP
2177     {
2178         static long int primCounter = 0;
2179         /* NOTE: set primCounter to the value reported by drawprim 
2180            before you want to to write frame makeup to /tmp */
2181         if (primCounter >= 0) {
2182             WINED3DLOCKED_RECT r;
2183             char buffer[80];
2184             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
2185             sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2186             TRACE("Saving screenshot %s\n", buffer);
2187             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2188             IWineD3DSurface_UnlockRect(This->renderTarget);
2189
2190 #ifdef SHOW_TEXTURE_MAKEUP
2191            {
2192             IWineD3DSurface *pSur;
2193             int textureNo;
2194             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2195                 if (This->stateBlock->textures[textureNo] != NULL) {
2196                     sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2197                     TRACE("Saving texture %s\n", buffer);
2198                     if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
2199                             IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2200                             IWineD3DSurface_SaveSnapshot(pSur, buffer);
2201                             IWineD3DSurface_Release(pSur);
2202                     } else  {
2203                         FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2204                     }
2205                 }
2206             }
2207            }
2208 #endif
2209         }
2210         TRACE("drawprim #%ld\n", primCounter);
2211         ++primCounter;
2212     }
2213 #endif
2214 }