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