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