Enhance uxtheme to store the themed system metrics in the registry and
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 #if 0 /* TODO */
32 extern IDirect3DVertexShaderImpl*            VertexShaders[64];
33 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
34 extern IDirect3DPixelShaderImpl*             PixelShaders[64];
35
36 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
37 #endif
38
39 /* Returns bits for what is expected from the fixed function pipeline, and whether
40    a vertex shader will be in use. Note the fvf bits returned may be split over
41    multiple streams only if the vertex shader was created, otherwise it all relates
42    to stream 0                                                                      */
43 static BOOL initializeFVF(IWineD3DDevice *iface, DWORD *FVFbits)
44 {
45
46     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
47
48 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
49     /* The first thing to work out is if we are using the fixed function pipeline
50        which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
51        is the FVF, or with a shader which was created with no function - in which
52        case there is an FVF per declared stream. If this occurs, we also maintain
53        an 'OR' of all the FVF's together so we know what to expect across all the
54        streams                                                                        */
55 #endif
56     *FVFbits = This->stateBlock->fvf;
57 #if 0
58         *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
59 #endif
60     return FALSE;
61 }
62
63 /* Issues the glBegin call for gl given the primitive type and count */
64 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
65                     DWORD            NumPrimitives,
66                     GLenum          *primType)
67 {
68     DWORD   NumVertexes = NumPrimitives;
69
70     switch (PrimitiveType) {
71     case D3DPT_POINTLIST:
72         TRACE("POINTS\n");
73         *primType   = GL_POINTS;
74         NumVertexes = NumPrimitives;
75         break;
76
77     case D3DPT_LINELIST:
78         TRACE("LINES\n");
79         *primType   = GL_LINES;
80         NumVertexes = NumPrimitives * 2;
81         break;
82
83     case D3DPT_LINESTRIP:
84         TRACE("LINE_STRIP\n");
85         *primType   = GL_LINE_STRIP;
86         NumVertexes = NumPrimitives + 1;
87         break;
88
89     case D3DPT_TRIANGLELIST:
90         TRACE("TRIANGLES\n");
91         *primType   = GL_TRIANGLES;
92         NumVertexes = NumPrimitives * 3;
93         break;
94
95     case D3DPT_TRIANGLESTRIP:
96         TRACE("TRIANGLE_STRIP\n");
97         *primType   = GL_TRIANGLE_STRIP;
98         NumVertexes = NumPrimitives + 2;
99         break;
100
101     case D3DPT_TRIANGLEFAN:
102         TRACE("TRIANGLE_FAN\n");
103         *primType   = GL_TRIANGLE_FAN;
104         NumVertexes = NumPrimitives + 2;
105         break;
106
107     default:
108         FIXME("Unhandled primitive\n");
109         *primType    = GL_POINTS;
110         break;
111     }
112     return NumVertexes;
113 }
114
115 /* Ensure the appropriate material states are set up - only change
116    state if really required                                        */
117 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
118
119     BOOL requires_material_reset = FALSE;
120     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
121
122     if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
123         /* If we have not set up the material color tracking, do it now as required */
124         glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
125         checkGLcall("glDisable GL_COLOR_MATERIAL");
126         TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
127         glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
128         checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
129         glEnable(GL_COLOR_MATERIAL);
130         checkGLcall("glEnable GL_COLOR_MATERIAL");
131         This->tracking_color = IS_TRACKING;
132         requires_material_reset = TRUE; /* Restore material settings as will be used */
133
134     } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
135                (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
136         /* If we are tracking the current color but one isn't supplied, don't! */
137         glDisable(GL_COLOR_MATERIAL);
138         checkGLcall("glDisable GL_COLOR_MATERIAL");
139         This->tracking_color = NEEDS_TRACKING;
140         requires_material_reset = TRUE; /* Restore material settings as will be used */
141
142     } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
143         /* No need to reset material colors since no change to gl_color_material */
144         requires_material_reset = FALSE;
145
146     } else if (This->tracking_color == NEEDS_DISABLE) {
147         glDisable(GL_COLOR_MATERIAL);
148         checkGLcall("glDisable GL_COLOR_MATERIAL");
149         This->tracking_color = DISABLED_TRACKING;
150         requires_material_reset = TRUE; /* Restore material settings as will be used */
151     }
152
153     /* Reset the material colors which may have been tracking the color*/
154     if (requires_material_reset) {
155         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
156         checkGLcall("glMaterialfv");
157         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
158         checkGLcall("glMaterialfv");
159         if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
160            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
161            checkGLcall("glMaterialfv");
162         } else {
163            float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
164            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
165            checkGLcall("glMaterialfv");
166         }
167         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
168         checkGLcall("glMaterialfv");
169     }
170
171 }
172
173 static GLfloat invymat[16] = {
174         1.0f, 0.0f, 0.0f, 0.0f,
175         0.0f, -1.0f, 0.0f, 0.0f,
176         0.0f, 0.0f, 1.0f, 0.0f,
177         0.0f, 0.0f, 0.0f, 1.0f};
178
179 /* Setup views - Transformed & lit if RHW, else untransformed.
180        Only unlit if Normals are supplied
181     Returns: Whether to restore lighting afterwards           */
182 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
183
184     BOOL isLightingOn = FALSE;
185     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
186
187     /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
188        set by the appropriate render state. Note Vertex Shader output is already lit */
189     if (vtx_lit || useVS) {
190         isLightingOn = glIsEnabled(GL_LIGHTING);
191         glDisable(GL_LIGHTING);
192         checkGLcall("glDisable(GL_LIGHTING);");
193         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
194     }
195
196     if (!useVS && vtx_transformed) {
197
198         /* If the last draw was transformed as well, no need to reapply all the matrixes */
199         if (!This->last_was_rhw) {
200
201             double X, Y, height, width, minZ, maxZ;
202             This->last_was_rhw = TRUE;
203
204             /* Transformed already into viewport coordinates, so we do not need transform
205                matrices. Reset all matrices to identity and leave the default matrix in world
206                mode.                                                                         */
207             glMatrixMode(GL_MODELVIEW);
208             checkGLcall("glMatrixMode(GL_MODELVIEW)");
209             glLoadIdentity();
210             checkGLcall("glLoadIdentity");
211
212             glMatrixMode(GL_PROJECTION);
213             checkGLcall("glMatrixMode(GL_PROJECTION)");
214             glLoadIdentity();
215             checkGLcall("glLoadIdentity");
216
217             /* Set up the viewport to be full viewport */
218             X      = This->stateBlock->viewport.X;
219             Y      = This->stateBlock->viewport.Y;
220             height = This->stateBlock->viewport.Height;
221             width  = This->stateBlock->viewport.Width;
222             minZ   = This->stateBlock->viewport.MinZ;
223             maxZ   = This->stateBlock->viewport.MaxZ;
224             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
225             glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
226             checkGLcall("glOrtho");
227
228             /* Window Coord 0 is the middle of the first pixel, so translate by half
229                a pixel (See comment above glTranslate below)                         */
230             glTranslatef(0.5, 0.5, 0);
231             checkGLcall("glTranslatef(0.5, 0.5, 0)");
232             if (This->renderUpsideDown) {
233                 glMultMatrixf(invymat);
234                 checkGLcall("glMultMatrixf(invymat)");
235             }
236         }
237
238     } else {
239
240         /* Untransformed, so relies on the view and projection matrices */
241
242         if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
243             /* Only reapply when have to */
244             This->modelview_valid = TRUE;
245             glMatrixMode(GL_MODELVIEW);
246             checkGLcall("glMatrixMode");
247
248             /* In the general case, the view matrix is the identity matrix */
249             if (This->view_ident) {
250                 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
251                 checkGLcall("glLoadMatrixf");
252             } else {
253                 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
254                 checkGLcall("glLoadMatrixf");
255                 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
256                 checkGLcall("glMultMatrixf");
257             }
258         }
259
260         if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
261             /* Only reapply when have to */
262             This->proj_valid = TRUE;
263             glMatrixMode(GL_PROJECTION);
264             checkGLcall("glMatrixMode");
265
266             /* The rule is that the window coordinate 0 does not correspond to the
267                beginning of the first pixel, but the center of the first pixel.
268                As a consequence if you want to correctly draw one line exactly from
269                the left to the right end of the viewport (with all matrices set to
270                be identity), the x coords of both ends of the line would be not
271                -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
272                instead.                                                               */
273             glLoadIdentity();
274
275             glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
276             checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
277
278             if (This->renderUpsideDown) {
279                 glMultMatrixf(invymat);
280                 checkGLcall("glMultMatrixf(invymat)");
281             }
282             glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
283             checkGLcall("glLoadMatrixf");
284         }
285
286         /* Vertex Shader output is already transformed, so set up identity matrices */
287         /* FIXME: Actually, only true for software emulated ones, so when h/w ones
288              come along this needs to take into account whether s/w ones were
289              requested or not                                                       */
290         if (useVS) {
291             glMatrixMode(GL_MODELVIEW);
292             checkGLcall("glMatrixMode");
293             glLoadIdentity();
294             glMatrixMode(GL_PROJECTION);
295             checkGLcall("glMatrixMode");
296             glLoadIdentity();
297             /* Window Coord 0 is the middle of the first pixel, so translate by half
298                a pixel (See comment above glTranslate above)                         */
299             glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
300             checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
301             if (This->renderUpsideDown) {
302                 glMultMatrixf(invymat);
303                 checkGLcall("glMultMatrixf(invymat)");
304             }
305             This->modelview_valid = FALSE;
306             This->proj_valid = FALSE;
307         }
308         This->last_was_rhw = FALSE;
309     }
310     return isLightingOn;
311 }
312
313 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
314      /* We need to deal with frequency data!*/
315
316     int           textureNo =0;
317     BYTE  *data    = NULL;
318     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
319     IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
320     int i;
321     D3DVERTEXELEMENT9 *element;
322     DWORD stride;
323     for (i = 0 ; i < vertexDeclaration->declaration9NumElements - 1; ++i) {
324
325         element = vertexDeclaration->pDeclaration9 + i;
326         TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclaration9, element,  i, vertexDeclaration->declaration9NumElements);
327         if (This->stateBlock->streamIsUP) {
328             TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
329             data    = (BYTE *)This->stateBlock->streamSource[element->Stream];
330         } else {
331             TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
332             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
333         }
334         stride  = This->stateBlock->streamStride[element->Stream];
335         data += (BaseVertexIndex * stride);
336         data += element->Offset;
337         /* Why can't I just use a lookup table instead of a switch statment? */
338         switch (element->Usage) {
339         case D3DDECLUSAGE_POSITION:
340                 switch (element->UsageIndex) {
341                 case 0: /* N-patch */
342                     strided->u.s.position.lpData    = data;
343                     strided->u.s.position.dwType    = element->Type;
344                     strided->u.s.position.dwStride  = stride;
345                 break;
346                 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
347                     TRACE("Tweened positions\n");
348                     strided->u.s.position2.lpData    = data;
349                     strided->u.s.position2.dwType    = element->Type;
350                     strided->u.s.position2.dwStride  = stride;
351                 break;
352                 }
353         break;
354         case D3DDECLUSAGE_NORMAL:
355                 switch (element->UsageIndex) {
356                 case 0: /* N-patch */
357                     strided->u.s.normal.lpData    = data;
358                     strided->u.s.normal.dwType    = element->Type;
359                     strided->u.s.normal.dwStride  = stride;
360                 break;
361                 case 1: /* skinning */
362                     TRACE("Skinning / tween normals\n");
363                     strided->u.s.normal2.lpData    = data;
364                     strided->u.s.normal2.dwType    = element->Type;
365                     strided->u.s.normal2.dwStride  = stride;
366                 break;
367                 }
368                 *fvf |=  D3DFVF_NORMAL;
369         break;
370         case D3DDECLUSAGE_BLENDINDICES:
371         /* demo @http://www.ati.com/developer/vertexblend.html
372             and http://www.flipcode.com/articles/article_dx8shaders.shtml
373         */
374             strided->u.s.blendMatrixIndices.lpData  = data;
375             strided->u.s.blendMatrixIndices.dwType  = element->Type;
376             strided->u.s.blendMatrixIndices.dwStride= stride;
377         break;
378         case D3DDECLUSAGE_BLENDWEIGHT:
379             strided->u.s.blendWeights.lpData        = data;
380             strided->u.s.blendWeights.dwType        = element->Type;
381             strided->u.s.blendWeights.dwStride      = stride;
382         break;
383         case D3DDECLUSAGE_PSIZE:
384             strided->u.s.pSize.lpData               = data;
385             strided->u.s.pSize.dwType               = element->Type;
386             strided->u.s.pSize.dwStride             = stride;
387         break;
388         case D3DDECLUSAGE_COLOR:
389         switch (element->UsageIndex) {
390         case 0:/* diffuse */
391             strided->u.s.diffuse.lpData             = data;
392             strided->u.s.diffuse.dwType             = element->Type;
393             strided->u.s.diffuse.dwStride           = stride;
394         break;
395         case 1: /* specular */
396             strided->u.s.specular.lpData            = data;
397             strided->u.s.specular.dwType            = element->Type;
398             strided->u.s.specular.dwStride          = stride;
399         }
400
401         break;
402         case D3DDECLUSAGE_TEXCOORD:
403         /* For some odd reason Microsoft decided to sum usage accross all the streams,
404         which means we need to do a count and not just use the usage number */
405
406             strided->u.s.texCoords[textureNo].lpData    = data;
407             strided->u.s.texCoords[textureNo].dwType    = element->Type;
408             strided->u.s.texCoords[textureNo].dwStride  = stride;
409
410             ++textureNo;
411         break;
412         case D3DDECLUSAGE_TANGENT:
413         /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
414         this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
415         normal using tangents where no normal data has been provided */
416             TRACE("Tangents\n");
417             strided->u.s.tangent.lpData   = data;
418             strided->u.s.tangent.dwType   = element->Type;
419             strided->u.s.tangent.dwStride = stride;
420         break;
421         case D3DDECLUSAGE_BINORMAL:
422         /* Binormals are really bitangents perpendicular to the normal but s-aligned to the tangent, basically they are the vectors of any two lines on the plain at right angles to the normal and at right angles to each other, like the x,y,z axis.
423         tangent data makes it easier to perform some calculations (a bit like using 2d graph paper instead of the normal of the piece of paper)
424         The only thing they are useful for in fixed function would be working out normals when none are given.
425         */
426             TRACE("BI-Normal\n");
427             strided->u.s.binormal.lpData   = data;
428             strided->u.s.binormal.dwType   = element->Type;
429             strided->u.s.binormal.dwStride = stride;
430         break;
431         case D3DDECLUSAGE_TESSFACTOR:
432         /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
433         */
434             TRACE("Tess Factor\n");
435             strided->u.s.tessFactor.lpData   = data;
436             strided->u.s.tessFactor.dwType   = element->Type;
437             strided->u.s.tessFactor.dwStride = stride;
438         break;
439         case D3DDECLUSAGE_POSITIONT:
440
441                switch (element->UsageIndex) {
442                 case 0: /* N-patch */
443                     strided->u.s.position.lpData    = data;
444                     strided->u.s.position.dwType    = element->Type;
445                     strided->u.s.position.dwStride  = stride;
446                 break;
447                 case 1: /* skinning */
448                         /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
449                         http://xface.blogspot.com/2004_08_01_xface_archive.html
450                         */
451                     TRACE("Skinning positionsT\n");
452                     strided->u.s.position2.lpData    = data;
453                     strided->u.s.position2.dwType    = element->Type;
454                     strided->u.s.position2.dwStride  = stride;
455                 break;
456                 }
457                 /* TODO: change fvf usage to a plain boolean flag */
458                 *fvf |= D3DFVF_XYZRHW;
459             /* FIXME: were faking this flag so that we don't transform the data again */
460         break;
461         case D3DDECLUSAGE_FOG:
462         /* maybe GL_EXT_fog_coord ?
463         * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
464         * This extension allows specifying an explicit per-vertex fog
465         * coordinate to be used in fog computations, rather than using a
466         * fragment depth-based fog equation.
467         *
468         * */
469             TRACE("Fog\n");
470             strided->u.s.fog.lpData   = data;
471             strided->u.s.fog.dwType   = element->Type;
472             strided->u.s.fog.dwStride = stride;
473         break;
474         case D3DDECLUSAGE_DEPTH:
475             TRACE("depth\n");
476             strided->u.s.depth.lpData   = data;
477             strided->u.s.depth.dwType   = element->Type;
478             strided->u.s.depth.dwStride = stride;
479             break;
480         case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
481             TRACE("depth\n");
482             strided->u.s.sample.lpData   = data;
483             strided->u.s.sample.dwType   = element->Type;
484             strided->u.s.sample.dwStride = stride;
485         break;
486         };
487
488     };
489
490 }
491
492 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
493
494     short         LoopThroughTo = 0;
495     short         nStream;
496     int           numBlends;
497     int           numTextures;
498     int           textureNo;
499     int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
500     int           numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
501
502     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
503
504     /* OK, Now to setup the data locations
505        For the non-created vertex shaders, the VertexShader var holds the real
506           FVF and only stream 0 matters
507        For the created vertex shaders, there is an FVF per stream              */
508     if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
509         LoopThroughTo = MAX_STREAMS;
510     } else {
511         LoopThroughTo = 1;
512     }
513
514     /* Work through stream by stream */
515     for (nStream=0; nStream<LoopThroughTo; ++nStream) {
516         DWORD  stride  = This->stateBlock->streamStride[nStream];
517         BYTE  *data    = NULL;
518         DWORD  thisFVF = 0;
519
520         /* Skip empty streams */
521         if (This->stateBlock->streamSource[nStream] == NULL) continue;
522
523         /* Retrieve appropriate FVF */
524         if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
525             thisFVF = This->stateBlock->fvf;
526             /* Handle memory passed directly as well as vertex buffers */
527             if (This->stateBlock->streamIsUP) {
528                 data    = (BYTE *)This->stateBlock->streamSource[nStream];
529             } else {
530                 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
531             }
532         } else {
533 #if 0 /* TODO: Vertex shader support */
534             thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
535             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
536 #endif
537         }
538         VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
539         if (thisFVF == 0) continue;
540
541         /* Now convert the stream into pointers */
542
543         /* Shuffle to the beginning of the vertexes to render and index from there */
544         data = data + (BaseVertexIndex * stride);
545
546         /* Either 3 or 4 floats depending on the FVF */
547         /* FIXME: Can blending data be in a different stream to the position data?
548               and if so using the fixed pipeline how do we handle it               */
549         if (thisFVF & D3DFVF_POSITION_MASK) {
550             strided->u.s.position.lpData    = data;
551             strided->u.s.position.dwType    = D3DDECLTYPE_FLOAT3;
552             strided->u.s.position.dwStride  = stride;
553             data += 3 * sizeof(float);
554             if (thisFVF & D3DFVF_XYZRHW) {
555                 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
556                 data += sizeof(float);
557             }
558         }
559
560         /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
561         /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
562         numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
563         if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
564
565         if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
566             TRACE("Setting blend Weights to %p \n", data);
567             strided->u.s.blendWeights.lpData    = data;
568             strided->u.s.blendWeights.dwType    = D3DDECLTYPE_FLOAT1 + numBlends - 1;
569             strided->u.s.blendWeights.dwStride  = stride;
570             data += numBlends * sizeof(FLOAT);
571
572             if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
573                 strided->u.s.blendMatrixIndices.lpData = data;
574                 strided->u.s.blendMatrixIndices.dwType  = D3DDECLTYPE_UBYTE4;
575                 strided->u.s.blendMatrixIndices.dwStride= stride;
576                 data += sizeof(DWORD);
577             }
578         }
579
580         /* Normal is always 3 floats */
581         if (thisFVF & D3DFVF_NORMAL) {
582             strided->u.s.normal.lpData    = data;
583             strided->u.s.normal.dwType    = D3DDECLTYPE_FLOAT3;
584             strided->u.s.normal.dwStride  = stride;
585             data += 3 * sizeof(FLOAT);
586         }
587
588         /* Pointsize is a single float */
589         if (thisFVF & D3DFVF_PSIZE) {
590             strided->u.s.pSize.lpData    = data;
591             strided->u.s.pSize.dwType    = D3DDECLTYPE_FLOAT1;
592             strided->u.s.pSize.dwStride  = stride;
593             data += sizeof(FLOAT);
594         }
595
596         /* Diffuse is 4 unsigned bytes */
597         if (thisFVF & D3DFVF_DIFFUSE) {
598             strided->u.s.diffuse.lpData    = data;
599             strided->u.s.diffuse.dwType    = D3DDECLTYPE_SHORT4;
600             strided->u.s.diffuse.dwStride  = stride;
601             data += sizeof(DWORD);
602         }
603
604         /* Specular is 4 unsigned bytes */
605         if (thisFVF & D3DFVF_SPECULAR) {
606             strided->u.s.specular.lpData    = data;
607             strided->u.s.specular.dwType    = D3DDECLTYPE_SHORT4;
608             strided->u.s.specular.dwStride  = stride;
609             data += sizeof(DWORD);
610         }
611
612         /* Texture coords */
613         numTextures   = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
614         coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
615
616         /* numTextures indicates the number of texture coordinates supplied */
617         /* However, the first set may not be for stage 0 texture - it all   */
618         /*   depends on D3DTSS_TEXCOORDINDEX.                               */
619         /* The number of bytes for each coordinate set is based off         */
620         /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
621
622         /* So, for each supplied texture extract the coords */
623         for (textureNo = 0; textureNo < numTextures; ++textureNo) {
624
625             strided->u.s.texCoords[textureNo].lpData    = data;
626             strided->u.s.texCoords[textureNo].dwType    = D3DDECLTYPE_FLOAT1;
627             strided->u.s.texCoords[textureNo].dwStride  = stride;
628             numCoords[textureNo] = coordIdxInfo & 0x03;
629
630             /* Always one set */
631             data += sizeof(float);
632             if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
633                 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
634                 data += sizeof(float);
635                 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
636                     strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
637                     data += sizeof(float);
638                     if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
639                         strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
640                         data += sizeof(float);
641                     }
642                 }
643             }
644             coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
645         }
646     }
647 }
648
649 #if 0 /* TODO: Software Shaders */
650 /* Draw a single vertex using this information */
651 static void draw_vertex(IWineD3DDevice *iface,                         /* interface    */
652                  BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
653                  BOOL isNormal, float nx, float ny, float nz,          /* normal       */
654                  BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
655                  BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
656                  BOOL isPtSize, float ptSize,                       /* pointSize    */
657                  WINED3DVECTOR_4 *texcoords, int *numcoords)        /* texture info */
658 {
659     unsigned int textureNo;
660     float s, t, r, q;
661     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
662
663     /* Diffuse -------------------------------- */
664     if (isDiffuse) {
665         glColor4fv(dRGBA);
666         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
667     }
668
669     /* Specular Colour ------------------------------------------*/
670     if (isSpecular) {
671         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
672           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
673           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
674         } else {
675           VTRACE(("Specular color extensions not supplied\n"));
676         }
677     }
678
679     /* Normal -------------------------------- */
680     if (isNormal) {
681         VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
682         glNormal3f(nx, ny, nz);
683     }
684
685     /* Point Size ----------------------------------------------*/
686     if (isPtSize) {
687
688         /* no such functionality in the fixed function GL pipeline */
689         FIXME("Cannot change ptSize here in openGl\n");
690     }
691
692     /* Texture coords --------------------------- */
693     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
694
695         if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
696             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
697             continue ;
698         }
699
700         /* Query tex coords */
701         if (This->stateBlock->textures[textureNo] != NULL) {
702
703             int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
704             if (coordIdx >= MAX_TEXTURES) {
705                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
706                 continue;
707             } else if (numcoords[coordIdx] == 0) {
708                 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
709                 continue;
710             } else {
711
712                 /* Initialize vars */
713                 s = 0.0f;
714                 t = 0.0f;
715                 r = 0.0f;
716                 q = 0.0f;
717
718                 switch (numcoords[coordIdx]) {
719                 case 4: q = texcoords[coordIdx].w; /* drop through */
720                 case 3: r = texcoords[coordIdx].z; /* drop through */
721                 case 2: t = texcoords[coordIdx].y; /* drop through */
722                 case 1: s = texcoords[coordIdx].x;
723                 }
724
725                 switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
726                 case D3DTTFF_COUNT1:
727                     VTRACE(("tex:%d, s=%f\n", textureNo, s));
728                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
729                         GLMULTITEXCOORD1F(textureNo, s);
730                     } else {
731                         glTexCoord1f(s);
732                     }
733                     break;
734                 case D3DTTFF_COUNT2:
735                     VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
736                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
737                         GLMULTITEXCOORD2F(textureNo, s, t);
738                     } else {
739                         glTexCoord2f(s, t);
740                     }
741                     break;
742                 case D3DTTFF_COUNT3:
743                     VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
744                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
745                         GLMULTITEXCOORD3F(textureNo, s, t, r);
746                     } else {
747                         glTexCoord3f(s, t, r);
748                     }
749                     break;
750                 case D3DTTFF_COUNT4:
751                     VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
752                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
753                         GLMULTITEXCOORD4F(textureNo, s, t, r, q);
754                     } else {
755                         glTexCoord4f(s, t, r, q);
756                     }
757                     break;
758                 default:
759                     FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
760                 }
761             }
762         }
763     } /* End of textures */
764
765     /* Position -------------------------------- */
766     if (isXYZ) {
767         if (1.0f == rhw || rhw < 0.00001f) {
768             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
769             glVertex3f(x, y, z);
770         } else {
771             /* Cannot optimize by dividing through by rhw as rhw is required
772                later for perspective in the GL pipeline for vertex shaders   */
773             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
774             glVertex4f(x,y,z,rhw);
775         }
776     }
777 }
778 #endif /* TODO: Software shaders */
779
780 /*
781  * Actually draw using the supplied information.
782  * Faster GL version using pointers to data, harder to debug though
783  * Note does not handle vertex shaders yet
784  */
785 static void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
786                      int PrimitiveType, ULONG NumPrimitives,
787                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
788     unsigned int textureNo   = 0;
789     GLenum       glPrimType  = GL_POINTS;
790     int          NumVertexes = NumPrimitives;
791     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
792
793     TRACE("Using fast vertex array code\n");
794
795     /* Vertex Pointers -----------------------------------------*/
796     if (sd->u.s.position.lpData != NULL) {
797
798         /* Note dwType == float3 or float4 == 2 or 3 */
799         VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
800                 sd->u.s.position.dwStride,
801                 sd->u.s.position.dwType + 1,
802                 sd->u.s.position.lpData));
803
804         /* Disable RHW mode as 'w' coord handling for rhw mode should
805            not impact screen position whereas in GL it does. This may
806            result in very slightly distored textures in rhw mode, but
807            a very minimal different                                   */
808         glVertexPointer(3, GL_FLOAT,  /* RHW: Was 'sd->u.s.position.dwType + 1' */
809                         sd->u.s.position.dwStride,
810                         sd->u.s.position.lpData);
811         checkGLcall("glVertexPointer(...)");
812         glEnableClientState(GL_VERTEX_ARRAY);
813         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
814
815     } else {
816
817         glDisableClientState(GL_VERTEX_ARRAY);
818         checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
819     }
820
821     /* Blend Data ----------------------------------------------*/
822     if ((sd->u.s.blendWeights.lpData != NULL) ||
823         (sd->u.s.blendMatrixIndices.lpData != NULL)) {
824 #if 1 /* Vertex blend support needs to be added */
825         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
826             DWORD fvf = (sd->u.s.blendWeights.dwType - D3DDECLTYPE_FLOAT1) + 1;
827             int numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == (fvf & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);
828
829             /* Note dwType == float3 or float4 == 2 or 3 */
830             VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
831                     numBlends,
832                     sd->u.s.blendWeights.dwStride,
833                     sd->u.s.blendWeights.lpData));
834             GL_EXTCALL(glWeightPointerARB)(numBlends, GL_FLOAT,
835                                            sd->u.s.blendWeights.dwStride,
836                                            sd->u.s.blendWeights.lpData);
837             checkGLcall("glWeightPointerARB(...)");
838             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
839             checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
840         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
841             /*FIXME("TODO\n");*/
842             /*
843             GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
844             checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
845             glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
846             checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
847             */
848         } else {
849             FIXME("unsupported blending in openGl\n");
850         }
851     } else {
852         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
853             TRACE("TODO ARB_VERTEX_BLEND\n");
854         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
855             TRACE("TODO EXT_VERTEX_WEIGHTING\n");
856             /*
857             glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
858             checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
859             */
860         }
861 #else
862         /* FIXME: Won't get here as will drop to slow method        */
863         FIXME("Blending not supported in fast draw routine\n");
864 #endif
865     }
866
867     /* Normals -------------------------------------------------*/
868     if (sd->u.s.normal.lpData != NULL) {
869
870         /* Note dwType == float3 or float4 == 2 or 3 */
871         VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
872                 sd->u.s.normal.dwStride,
873                 sd->u.s.normal.lpData));
874         glNormalPointer(GL_FLOAT,
875                         sd->u.s.normal.dwStride,
876                         sd->u.s.normal.lpData);
877         checkGLcall("glNormalPointer(...)");
878         glEnableClientState(GL_NORMAL_ARRAY);
879         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
880
881     } else {
882
883         glDisableClientState(GL_NORMAL_ARRAY);
884         checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
885         glNormal3f(0, 0, 1);
886         checkGLcall("glNormal3f(0, 0, 1)");
887     }
888
889     /* Point Size ----------------------------------------------*/
890     if (sd->u.s.pSize.lpData != NULL) {
891
892         /* no such functionality in the fixed function GL pipeline */
893         /* FIXME: Won't get here as will drop to slow method        */
894         FIXME("Cannot change ptSize here in openGl\n");
895     }
896
897     /* Diffuse Colour ------------------------------------------*/
898     /*  WARNING: Data here MUST be in RGBA format, so cannot    */
899     /*     go directly into fast mode from app pgm, because     */
900     /*     directx requires data in BGRA format.                */
901     if (sd->u.s.diffuse.lpData != NULL) {
902
903         /* Note dwType == float3 or float4 == 2 or 3 */
904         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
905                 sd->u.s.diffuse.dwStride,
906                 sd->u.s.diffuse.lpData));
907         glColorPointer(4, GL_UNSIGNED_BYTE,
908                        sd->u.s.diffuse.dwStride,
909                        sd->u.s.diffuse.lpData);
910         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
911         glEnableClientState(GL_COLOR_ARRAY);
912         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
913
914     } else {
915
916         glDisableClientState(GL_COLOR_ARRAY);
917         checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
918         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
919         checkGLcall("glColor4f(1, 1, 1, 1)");
920     }
921
922     /* Specular Colour ------------------------------------------*/
923     if (sd->u.s.specular.lpData != NULL) {
924
925         /* Note dwType == float3 or float4 == 2 or 3 */
926         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
927                 sd->u.s.specular.dwStride,
928                 sd->u.s.specular.lpData));
929
930         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
931             GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
932                                                    sd->u.s.specular.dwStride,
933                                                    sd->u.s.specular.lpData);
934             vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
935             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
936             vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
937         } else {
938           /* Missing specular color is not critical, no warnings */
939           VTRACE(("Specular colour is not supported in this GL implementation\n"));
940         }
941
942     } else {
943
944       if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
945         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
946         checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
947         GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
948         checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
949       } else {
950         /* Missing specular color is not critical, no warnings */
951         VTRACE(("Specular colour is not supported in this GL implementation\n"));
952       }
953     }
954
955     /* Texture coords -------------------------------------------*/
956     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
957
958         /* Select the correct texture stage */
959         GLCLIENTACTIVETEXTURE(textureNo);
960
961         /* Query tex coords */
962         if (This->stateBlock->textures[textureNo] != NULL) {
963             int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
964
965             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
966                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
967                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
968                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
969                 continue;
970             }
971
972             if (coordIdx > 7) {
973                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
974                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
975                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
976
977             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
978                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
979                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
980                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
981
982             } else {
983
984                 /* The coords to supply depend completely on the fvf / vertex shader */
985                 GLint size;
986                 GLenum type;
987
988                 switch (sd->u.s.texCoords[coordIdx].dwType) {
989                 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
990                 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
991                 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
992                 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
993                 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
994                 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
995                 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
996                 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
997                       size = 4; type = GL_UNSIGNED_BYTE;
998                 }
999
1000                 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1001                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1002             }
1003         } else {
1004             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1005             GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1006         }
1007     }
1008
1009     /* Ok, Work out which primitive is requested and how many vertexes that
1010        will be                                                              */
1011     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1012
1013     /* Finally do the drawing */
1014     if (idxData != NULL) {
1015
1016         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1017 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1018         glDrawElements(glPrimType, NumVertexes, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1019                       (const char *)idxData + (idxSize * startIdx));
1020 #else
1021         glDrawRangeElements(glPrimType, minIndex, minIndex + NumVertexes - 1, NumVertexes,
1022                       idxSize == 2 ? GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1023                       (const char *)idxData + (idxSize * startIdx));
1024 #endif
1025         checkGLcall("glDrawRangeElements");
1026
1027     } else {
1028
1029         /* Note first is now zero as we shuffled along earlier */
1030         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1031         glDrawArrays(glPrimType, 0, NumVertexes);
1032         checkGLcall("glDrawArrays");
1033
1034     }
1035 }
1036
1037 /*
1038  * Actually draw using the supplied information.
1039  * Slower GL version which extracts info about each vertex in turn
1040  */
1041 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1042                      int PrimitiveType, ULONG NumPrimitives,
1043                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1044
1045     unsigned int               textureNo    = 0;
1046     GLenum                     glPrimType   = GL_POINTS;
1047     int                        NumVertexes  = NumPrimitives;
1048     const short               *pIdxBufS     = NULL;
1049     const long                *pIdxBufL     = NULL;
1050     LONG                       SkipnStrides = 0;
1051     LONG                       vx_index;
1052     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1053     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
1054     float rhw = 0.0f;                      /* rhw                        */
1055     float ptSize = 0.0f;                   /* Point size                 */
1056     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
1057     DWORD specularColor = 0;               /* Specular Color             */
1058     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1059
1060     TRACE("Using slow vertex array code\n");
1061
1062     /* Variable Initialization */
1063     if (idxData != NULL) {
1064         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1065         else pIdxBufL = (const long *) idxData;
1066     }
1067
1068     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1069     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1070
1071     /* Start drawing in GL */
1072     VTRACE(("glBegin(%x)\n", glPrimType));
1073     glBegin(glPrimType);
1074
1075     /* For each primitive */
1076     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1077
1078         /* Initialize diffuse color */
1079         diffuseColor = 0xFFFFFFFF;
1080
1081         /* For indexed data, we need to go a few more strides in */
1082         if (idxData != NULL) {
1083
1084             /* Indexed so work out the number of strides to skip */
1085             if (idxSize == 2) {
1086                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1087                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1088             } else {
1089                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1090                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1091             }
1092         }
1093
1094         /* Position Information ------------------ */
1095         if (sd->u.s.position.lpData != NULL) {
1096
1097             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1098             x = ptrToCoords[0];
1099             y = ptrToCoords[1];
1100             z = ptrToCoords[2];
1101             rhw = 1.0;
1102             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1103
1104             /* RHW follows, only if transformed, ie 4 floats were provided */
1105             if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1106                 rhw = ptrToCoords[3];
1107                 VTRACE(("rhw=%f\n", rhw));
1108             }
1109         }
1110
1111         /* Blending data -------------------------- */
1112         if (sd->u.s.blendWeights.lpData != NULL) {
1113             /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1114             FIXME("Blending not supported yet\n");
1115
1116             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1117                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1118             }
1119         }
1120
1121         /* Vertex Normal Data (untransformed only)- */
1122         if (sd->u.s.normal.lpData != NULL) {
1123
1124             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1125             nx = ptrToCoords[0];
1126             ny = ptrToCoords[1];
1127             nz = ptrToCoords[2];
1128             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1129         }
1130
1131         /* Point Size ----------------------------- */
1132         if (sd->u.s.pSize.lpData != NULL) {
1133
1134             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1135             ptSize = ptrToCoords[0];
1136             VTRACE(("ptSize=%f\n", ptSize));
1137             FIXME("No support for ptSize yet\n");
1138         }
1139
1140         /* Diffuse -------------------------------- */
1141         if (sd->u.s.diffuse.lpData != NULL) {
1142
1143             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1144             diffuseColor = ptrToCoords[0];
1145             VTRACE(("diffuseColor=%lx\n", diffuseColor));
1146         }
1147
1148         /* Specular  -------------------------------- */
1149         if (sd->u.s.specular.lpData != NULL) {
1150
1151             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1152             specularColor = ptrToCoords[0];
1153             VTRACE(("specularColor=%lx\n", specularColor));
1154         }
1155
1156         /* Texture coords --------------------------- */
1157         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1158
1159             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1160                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1161                 continue ;
1162             }
1163
1164             /* Query tex coords */
1165             if (This->stateBlock->textures[textureNo] != NULL) {
1166
1167                 int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1168                 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1169                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1170
1171                 if (coordIdx > 7) {
1172                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1173                     continue;
1174                 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1175                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1176                     continue;
1177                 } else {
1178
1179                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1180
1181                     /* The coords to supply depend completely on the fvf / vertex shader */
1182                     switch (coordsToUse) {
1183                     case 4: q = ptrToCoords[3]; /* drop through */
1184                     case 3: r = ptrToCoords[2]; /* drop through */
1185                     case 2: t = ptrToCoords[1]; /* drop through */
1186                     case 1: s = ptrToCoords[0];
1187                     }
1188
1189                     /* Projected is more 'fun' - Move the last coord to the 'q'
1190                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1191                     if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1192                         (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1193
1194                         if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1195                             switch (coordsToUse) {
1196                             case 0:  /* Drop Through */
1197                             case 1:
1198                                 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1199                                 break;
1200                             case 2:
1201                                 q = t;
1202                                 t = 0.0;
1203                                 coordsToUse = 4;
1204                                 break;
1205                             case 3:
1206                                 q = r;
1207                                 r = 0.0;
1208                                 coordsToUse = 4;
1209                                 break;
1210                             case 4:  /* Nop here */
1211                                 break;
1212                             default:
1213                                 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1214                                       This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1215                             }
1216                         }
1217                     }
1218
1219                     switch (coordsToUse) {   /* Supply the provided texture coords */
1220                     case D3DTTFF_COUNT1:
1221                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1222                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1223                             GLMULTITEXCOORD1F(textureNo, s);
1224                         } else {
1225                             glTexCoord1f(s);
1226                         }
1227                         break;
1228                     case D3DTTFF_COUNT2:
1229                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1230                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1231                             GLMULTITEXCOORD2F(textureNo, s, t);
1232                         } else {
1233                             glTexCoord2f(s, t);
1234                         }
1235                         break;
1236                     case D3DTTFF_COUNT3:
1237                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1238                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1239                             GLMULTITEXCOORD3F(textureNo, s, t, r);
1240                         } else {
1241                             glTexCoord3f(s, t, r);
1242                         }
1243                         break;
1244                     case D3DTTFF_COUNT4:
1245                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1246                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1247                             GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1248                         } else {
1249                             glTexCoord4f(s, t, r, q);
1250                         }
1251                         break;
1252                     default:
1253                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1254                     }
1255                 }
1256             }
1257         } /* End of textures */
1258
1259         /* Diffuse -------------------------------- */
1260         if (sd->u.s.diffuse.lpData != NULL) {
1261             glColor4ub((diffuseColor >> 16) & 0xFF,
1262                        (diffuseColor >>  8) & 0xFF,
1263                        (diffuseColor >>  0) & 0xFF,
1264                        (diffuseColor >> 24) & 0xFF);
1265             VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1266                     ((diffuseColor >> 16) & 0xFF) / 255.0f,
1267                     ((diffuseColor >>  8) & 0xFF) / 255.0f,
1268                     ((diffuseColor >>  0) & 0xFF) / 255.0f,
1269                     ((diffuseColor >> 24) & 0xFF) / 255.0f));
1270         } else {
1271             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1272         }
1273
1274         /* Specular ------------------------------- */
1275         if (sd->u.s.diffuse.lpData != NULL) {
1276             VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1277                     ((specularColor >> 16) & 0xFF) / 255.0f,
1278                     ((specularColor >>  8) & 0xFF) / 255.0f,
1279                     ((specularColor >>  0) & 0xFF) / 255.0f));
1280             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1281                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1282                            (specularColor >> 16) & 0xFF,
1283                            (specularColor >>  8) & 0xFF,
1284                            (specularColor >>  0) & 0xFF);
1285             } else {
1286                 /* Do not worry if specular colour missing and disable request */
1287                 VTRACE(("Specular color extensions not supplied\n"));
1288             }
1289         } else {
1290             if (vx_index == 0) {
1291                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1292                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1293                 } else {
1294                     /* Do not worry if specular colour missing and disable request */
1295                     VTRACE(("Specular color extensions not supplied\n"));
1296                 }
1297             }
1298         }
1299
1300         /* Normal -------------------------------- */
1301         if (sd->u.s.normal.lpData != NULL) {
1302             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1303             glNormal3f(nx, ny, nz);
1304         } else {
1305             if (vx_index == 0) glNormal3f(0, 0, 1);
1306         }
1307
1308         /* Position -------------------------------- */
1309         if (sd->u.s.position.lpData != NULL) {
1310             if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1311                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1312                 glVertex3f(x, y, z);
1313             } else {
1314                 GLfloat w = 1.0 / rhw;
1315                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1316                 glVertex4f(x*w, y*w, z*w, w);
1317             }
1318         }
1319
1320         /* For non indexed mode, step onto next parts */
1321         if (idxData == NULL) {
1322             ++SkipnStrides;
1323         }
1324     }
1325
1326     glEnd();
1327     checkGLcall("glEnd and previous calls");
1328 }
1329
1330 #if 0 /* TODO: Software/Hardware vertex blending support */
1331 /*
1332  * Draw with emulated vertex shaders
1333  * Note: strided data is uninitialized, as we need to pass the vertex
1334  *     shader directly as ordering irs yet
1335  */
1336 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1337                      int PrimitiveType, ULONG NumPrimitives,
1338                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1339
1340     unsigned int               textureNo    = 0;
1341     GLenum                     glPrimType   = GL_POINTS;
1342     int                        NumVertexes  = NumPrimitives;
1343     const short               *pIdxBufS     = NULL;
1344     const long                *pIdxBufL     = NULL;
1345     LONG                       SkipnStrides = 0;
1346     LONG                       vx_index;
1347     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1348     float rhw = 0.0f;                      /* rhw                        */
1349     float ptSize = 0.0f;                   /* Point size                 */
1350     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1351     int   numcoords[8];                    /* Number of coords           */
1352     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1353
1354     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1355
1356     TRACE("Using slow software vertex shader code\n");
1357
1358     /* Variable Initialization */
1359     if (idxData != NULL) {
1360         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1361         else pIdxBufL = (const long *) idxData;
1362     }
1363
1364     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1365     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1366
1367     /* Retrieve the VS information */
1368     vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1369
1370     /* Start drawing in GL */
1371     VTRACE(("glBegin(%x)\n", glPrimType));
1372     glBegin(glPrimType);
1373
1374     /* For each primitive */
1375     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1376
1377         /* For indexed data, we need to go a few more strides in */
1378         if (idxData != NULL) {
1379
1380             /* Indexed so work out the number of strides to skip */
1381             if (idxSize == 2) {
1382                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1383                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1384             } else {
1385                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1386                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1387             }
1388         }
1389
1390         /* Fill the vertex shader input */
1391         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1392
1393         /* Initialize the output fields to the same defaults as it would normally have */
1394         memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1395         vertex_shader->output.oD[0].x = 1.0;
1396         vertex_shader->output.oD[0].y = 1.0;
1397         vertex_shader->output.oD[0].z = 1.0;
1398         vertex_shader->output.oD[0].w = 1.0;
1399
1400         /* Now execute the vertex shader */
1401         IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1402
1403         /*
1404         TRACE_VECTOR(vertex_shader->output.oPos);
1405         TRACE_VECTOR(vertex_shader->output.oD[0]);
1406         TRACE_VECTOR(vertex_shader->output.oD[1]);
1407         TRACE_VECTOR(vertex_shader->output.oT[0]);
1408         TRACE_VECTOR(vertex_shader->output.oT[1]);
1409         TRACE_VECTOR(vertex_shader->input.V[0]);
1410         TRACE_VECTOR(vertex_shader->data->C[0]);
1411         TRACE_VECTOR(vertex_shader->data->C[1]);
1412         TRACE_VECTOR(vertex_shader->data->C[2]);
1413         TRACE_VECTOR(vertex_shader->data->C[3]);
1414         TRACE_VECTOR(vertex_shader->data->C[4]);
1415         TRACE_VECTOR(vertex_shader->data->C[5]);
1416         TRACE_VECTOR(vertex_shader->data->C[6]);
1417         TRACE_VECTOR(vertex_shader->data->C[7]);
1418         */
1419
1420         /* Extract out the output */
1421         /*FIXME: Fog coords? */
1422         x = vertex_shader->output.oPos.x;
1423         y = vertex_shader->output.oPos.y;
1424         z = vertex_shader->output.oPos.z;
1425         rhw = vertex_shader->output.oPos.w;
1426         ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1427
1428         /** Update textures coords using vertex_shader->output.oT[0->7] */
1429         memset(texcoords, 0x00, sizeof(texcoords));
1430         memset(numcoords, 0x00, sizeof(numcoords));
1431         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1432             if (This->stateBlock->textures[textureNo] != NULL) {
1433                texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1434                texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1435                texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1436                texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1437                if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1438                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1439                } else {
1440                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1441                    case D3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1442                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1443                    default:                     numcoords[textureNo] = 4;
1444                    }
1445                }
1446             } else {
1447                 numcoords[textureNo] = 0;
1448             }
1449         }
1450
1451         /* Draw using this information */
1452         draw_vertex(iface,
1453                     TRUE, x, y, z, rhw,
1454                     TRUE, 0.0f, 0.0f, 1.0f,
1455                     TRUE, (float*) &vertex_shader->output.oD[0],
1456                     TRUE, (float*) &vertex_shader->output.oD[1],
1457                     FALSE, ptSize,         /* FIXME: Change back when supported */
1458                     texcoords, numcoords);
1459
1460         /* For non indexed mode, step onto next parts */
1461         if (idxData == NULL) {
1462            ++SkipnStrides;
1463         }
1464
1465     } /* for each vertex */
1466
1467     glEnd();
1468     checkGLcall("glEnd and previous calls");
1469 }
1470
1471 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1472                      int PrimitiveType, ULONG NumPrimitives,
1473                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1474
1475     IDirect3DVertexShaderImpl *vertex_shader = NULL;
1476     int                        i;
1477     int                        NumVertexes;
1478     int                        glPrimType;
1479     int                        maxAttribs;
1480
1481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1482     TRACE("Drawing with hardware vertex shaders\n");
1483
1484     /* Retrieve the VS information */
1485     vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1486
1487     /* Enable the Vertex Shader */
1488     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1489     checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1490     glEnable(GL_VERTEX_PROGRAM_ARB);
1491     checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1492
1493     /* Update the constants */
1494     for (i = 0; i < D3D8_VSHADER_MAX_CONSTANTS; ++i) {
1495         GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1496         checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1497     }
1498
1499     /* Set up the vertex.attr[n] inputs */
1500     IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1501
1502     /* Ok, Work out which primitive is requested and how many vertexes that
1503        will be                                                              */
1504     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1505
1506     /* Finally do the drawing */
1507     if (idxData != NULL) {
1508
1509         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1510 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1511         glDrawElements(glPrimType, NumVertexes, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1512                       (const char *)idxData + (idxSize * startIdx));
1513 #else
1514         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes - 1, NumVertexes,
1515                       idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1516                       (const char *)idxData + (idxSize * startIdx));
1517 #endif
1518         checkGLcall("glDrawRangeElements");
1519
1520     } else {
1521
1522         /* Note first is now zero as we shuffled along earlier */
1523         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1524         glDrawArrays(glPrimType, 0, NumVertexes);
1525         checkGLcall("glDrawArrays");
1526
1527     }
1528
1529     {
1530     GLint errPos;
1531     glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1532     if (errPos != -1)
1533         FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1534     }
1535
1536
1537     /* Leave all the attribs disabled */
1538     glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1539     /* MESA does not support it right not */
1540     if (glGetError() != GL_NO_ERROR)
1541         maxAttribs = 16;
1542     for (i = 0; i < maxAttribs; ++i) {
1543         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1544         checkGLcall("glDisableVertexAttribArrayARB(reg);");
1545     }
1546
1547     /* Done */
1548     glDisable(GL_VERTEX_PROGRAM_ARB);
1549 }
1550 #endif
1551
1552 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1553
1554     /* Dump out what parts we have supplied */
1555     TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1556     TRACE_STRIDED((dataLocations), position);
1557     TRACE_STRIDED((dataLocations), blendWeights);
1558     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1559     TRACE_STRIDED((dataLocations), normal);
1560     TRACE_STRIDED((dataLocations), pSize);
1561     TRACE_STRIDED((dataLocations), diffuse);
1562     TRACE_STRIDED((dataLocations), specular);
1563     TRACE_STRIDED((dataLocations), texCoords[0]);
1564     TRACE_STRIDED((dataLocations), texCoords[1]);
1565     TRACE_STRIDED((dataLocations), texCoords[2]);
1566     TRACE_STRIDED((dataLocations), texCoords[3]);
1567     TRACE_STRIDED((dataLocations), texCoords[4]);
1568     TRACE_STRIDED((dataLocations), texCoords[5]);
1569     TRACE_STRIDED((dataLocations), texCoords[6]);
1570     TRACE_STRIDED((dataLocations), texCoords[7]);
1571     return;
1572
1573 }
1574
1575 /* uploads textures and setup texture states ready for rendering */
1576 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1577
1578     unsigned int i;
1579 /**
1580 * OK, here we clear down any old junk iect in the context
1581 * enable the new texture and apply any state changes:
1582 *
1583 * Loop through all textures
1584 * select texture unit
1585 * if there is a texture bound to that unit then..
1586 * disable all textures types on that unit
1587 * enable and bind the texture that is bound to that unit.
1588 * otherwise dissable all texture types on that unit.
1589 **/
1590     /* upload the textures */
1591     for (i = 0; i< GL_LIMITS(textures); ++i) {
1592         /* Bind the texture to the stage here */
1593         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1594             GLACTIVETEXTURE(i);
1595         } else if (0 < i) {
1596             /* This isn't so much a warn as a message to the user about lack of hardware support */
1597             WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1598         }
1599
1600         /* don't bother with textures that have a colorop of disable */
1601         if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1602             if (This->stateBlock->textures[i] != NULL) {
1603
1604                 glDisable(GL_TEXTURE_1D);
1605                 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1606                 /* disable all texture states that aren't the selected textures' dimension */
1607                 switch(This->stateBlock->textureDimensions[i]) {
1608                 case GL_TEXTURE_2D:
1609                     glDisable(GL_TEXTURE_3D);
1610                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1611                 break;
1612                 case GL_TEXTURE_3D:
1613                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1614                     glDisable(GL_TEXTURE_2D);
1615                 break;
1616                 case GLTEXTURECUBEMAP:
1617                     glDisable(GL_TEXTURE_2D);
1618                     glDisable(GL_TEXTURE_3D);
1619                 break;
1620                 }
1621                 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1622                 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1623                     glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1624                 } else {
1625                     glEnable(This->stateBlock->textureDimensions[i]);
1626                 }
1627                   /* Load up the texture now */
1628                 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1629                 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1630                 /* this is a stub function representing the state blocks being seperated here we are only updating the texture state changes, other objects and units get updated when they change (or need to be updated), e.g. states that relate to a context member line the texture unit are only updated when the context needs updating */
1631                 /* Tell the abse texture to sync it's states */
1632                 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1633
1634               }
1635             /* Bind a default texture if no texture has been set, but colour-op is enabled */
1636             else {
1637                 glDisable(GL_TEXTURE_2D);
1638                 glDisable(GL_TEXTURE_3D);
1639                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1640                 glEnable(GL_TEXTURE_1D);
1641                 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1642                 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1643             }
1644 /** these ops apply to the texture unit, so they are preseved between texture changes, but for now brute force and reapply all
1645         dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1646             set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1647                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1648                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1649                         This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1650             /* alphaop */
1651             set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1652                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1653                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1654                         This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1655         } else {
1656
1657             /* no colorop so disable all the texture states */
1658             glDisable(GL_TEXTURE_1D);
1659             glDisable(GL_TEXTURE_2D);
1660             glDisable(GL_TEXTURE_3D);
1661             glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1662           }
1663
1664       }
1665
1666 }
1667
1668 /* Routine common to the draw primitive and draw indexed primitive routines */
1669 void drawPrimitive(IWineD3DDevice *iface,
1670                     int PrimitiveType, long NumPrimitives,
1671
1672                     /* for Indexed: */
1673                     long  StartVertexIndex,
1674                     long  StartIdx,
1675                     short idxSize,
1676                     const void *idxData,
1677                     int   minIndex) {
1678
1679     BOOL                          rc = FALSE;
1680     DWORD                         fvf = 0;
1681 #if 0 /* TODO: vertex and pixel shaders */
1682     IDirect3DVertexShaderImpl    *vertex_shader = NULL;
1683     IDirect3DPixelShaderImpl     *pixel_shader = NULL;
1684 #endif
1685     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1686     BOOL                          useVertexShaderFunction = FALSE;
1687     BOOL                          isLightingOn = FALSE;
1688     Direct3DVertexStridedData     dataLocations;
1689     int                           useHW = FALSE;
1690
1691     if (This->stateBlock->vertexDecl == NULL) {
1692         /* Work out what the FVF should look like */
1693         rc = initializeFVF(iface, &fvf);
1694         if (rc) return;
1695     } else {
1696         TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1697     }
1698
1699     /* If we will be using a vertex shader, do some initialization for it */
1700     if (useVertexShaderFunction) {
1701 #if 0 /* TODO: vertex and pixel shaders */
1702         vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1703         memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1704
1705         useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1706                  This->devType != D3DDEVTYPE_REF &&
1707                  !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1708                  vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1709
1710         /** init Constants */
1711         if (This->stateBlock->Changed.vertexShaderConstant) {
1712             TRACE_(d3d_shader)("vertex shader initializing constants\n");
1713             IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1714         }
1715 #endif /* TODO: vertex and pixel shaders */
1716     }
1717
1718     /* Ok, we will be updating the screen from here onwards so grab the lock */
1719     ENTER_GL();
1720
1721 #if 0 /* TODO: vertex and pixel shaders */
1722     /* If we will be using a pixel, do some initialization for it */
1723     if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1724         TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1725         memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1726
1727         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1728         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1729         glEnable(GL_FRAGMENT_PROGRAM_ARB);
1730         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1731
1732         /* init Constants */
1733         if (This->stateBlock->Changed.pixelShaderConstant) {
1734             TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1735             IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1736         }
1737         /* Update the constants */
1738         for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1739             GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1740             checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1741         }
1742     }
1743 #endif /* TODO: vertex and pixel shaders */
1744
1745     /* Initialize all values to null */
1746     if (useVertexShaderFunction == FALSE) {
1747         memset(&dataLocations, 0x00, sizeof(dataLocations));
1748
1749         /* Convert to strided data */
1750          if (This->stateBlock->vertexDecl != NULL) {
1751             TRACE("================ Vertex Declaration  ===================\n");
1752             primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1753          } else {
1754             TRACE("================ FVF ===================\n");
1755             primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1756          }
1757
1758         /* write out some debug information*/
1759         drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1760     } else {
1761         FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1762     }
1763
1764     /* Setup transform matrices and sort out */
1765     if (useHW) {
1766         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1767         So make sure lighting is disabled. */
1768         isLightingOn = glIsEnabled(GL_LIGHTING);
1769         glDisable(GL_LIGHTING);
1770         checkGLcall("glDisable(GL_LIGHTING);");
1771         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1772     } else {
1773         isLightingOn = primitiveInitState(iface,
1774                                           fvf & D3DFVF_XYZRHW,
1775                                           !(fvf & D3DFVF_NORMAL),
1776                                           useVertexShaderFunction);
1777     }
1778
1779     /* Now initialize the materials state */
1780     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1781
1782     drawPrimitiveUploadTextures(This);
1783
1784     /* Now draw the graphics to the screen */
1785     if  (useVertexShaderFunction) {
1786
1787         /* Ideally, we should have software FV and hardware VS, possibly
1788            depending on the device type?                                 */
1789
1790         if (useHW) {
1791             TRACE("Swap HW vertex shader\n");
1792 #if 0 /* TODO: vertex and pixel shaders */
1793             drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1794                         idxData, idxSize, minIndex, StartIdx);
1795 #endif
1796         } else {
1797             /* We will have to use the very, very slow emulation layer */
1798             TRACE("Swap SW vertex shader\n");
1799 #if 0 /* TODO: vertex and pixel shaders */
1800             drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1801                         idxData, idxSize, minIndex, StartIdx);
1802 #endif
1803         }
1804
1805     } else if ((dataLocations.u.s.pSize.lpData           != NULL)
1806                || (dataLocations.u.s.diffuse.lpData      != NULL)
1807                /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1808
1809         /* Fixme, Ideally, only use the per-vertex code for software HAL
1810            but until opengl supports all the functions returned to setup
1811            vertex arrays, we need to drop down to the slow mechanism for
1812            certain functions                                              */
1813
1814         /* We will have to use the slow version of GL per vertex setup */
1815         drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1816                         idxData, idxSize, minIndex, StartIdx);
1817
1818     } else {
1819
1820         /* We can use the fast version of GL pointers */
1821         drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1822                         idxData, idxSize, minIndex, StartIdx);
1823     }
1824
1825     /* If vertex shaders or no normals, restore previous lighting state */
1826     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1827         if (isLightingOn) glEnable(GL_LIGHTING);
1828         else glDisable(GL_LIGHTING);
1829         TRACE("Restored lighting to original state\n");
1830     }
1831
1832 #if 0 /* TODO: vertex and pixel shaders */
1833     if (pixel_shader)
1834     {
1835 #if 0
1836       GLint errPos;
1837       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1838       if (errPos != -1)
1839         FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1840 #endif
1841       glDisable(GL_FRAGMENT_PROGRAM_ARB);
1842     }
1843 #endif
1844
1845     /* Finshed updating the screen, restore lock */
1846     LEAVE_GL();
1847     TRACE("Done all gl drawing\n");
1848
1849     /* Diagnostics */
1850 #if defined(SHOW_FRAME_MAKEUP)
1851     {
1852         if (isDumpingFrames) {
1853             D3DLOCKED_RECT r;
1854             char buffer[80];
1855             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1856             sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1857             TRACE("Saving screenshot %s\n", buffer);
1858             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1859             IWineD3DSurface_UnlockRect(This->renderTarget);
1860
1861 #if defined(SHOW_TEXTURE_MAKEUP)
1862            {
1863             IWineD3DSurface *pSur;
1864             int textureNo;
1865             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1866                 if (This->stateBlock->textures[textureNo] != NULL) {
1867                     sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1868                     TRACE("Saving texture %s\n", buffer);
1869                     IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur);
1870                     IWineD3DSurface_SaveSnapshot(pSur, buffer);
1871                     IWineD3DSurface_Release(pSur);
1872                 }
1873             }
1874            }
1875 #endif
1876            ++primCounter;
1877         }
1878     }
1879 #endif
1880 }