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