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