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