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