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