Tidy up some of the formatting in drawprim and add missing strided
[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(1.0 / This->stateBlock->viewport.Width, -1.0 / This->stateBlock->viewport.Height, 0);
276             checkGLcall("glTranslatef (1.0 / width, -1.0 / 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(1.0 / This->stateBlock->viewport.Width, -1.0 / This->stateBlock->viewport.Height, 0);
300             checkGLcall("glTranslatef (1.0 / width, -1.0 / 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                     /* crude support for non-power2 textures */
1220                     if (((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2) {
1221                         t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY;
1222                         s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX;
1223                     }
1224
1225                     switch (coordsToUse) {   /* Supply the provided texture coords */
1226                     case D3DTTFF_COUNT1:
1227                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1228                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1229                             GLMULTITEXCOORD1F(textureNo, s);
1230                         } else {
1231                             glTexCoord1f(s);
1232                         }
1233                         break;
1234                     case D3DTTFF_COUNT2:
1235                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1236                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1237                             GLMULTITEXCOORD2F(textureNo, s, t);
1238                         } else {
1239                             glTexCoord2f(s, t);
1240                         }
1241                         break;
1242                     case D3DTTFF_COUNT3:
1243                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1244                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1245                             GLMULTITEXCOORD3F(textureNo, s, t, r);
1246                         } else {
1247                             glTexCoord3f(s, t, r);
1248                         }
1249                         break;
1250                     case D3DTTFF_COUNT4:
1251                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1252                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1253                             GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1254                         } else {
1255                             glTexCoord4f(s, t, r, q);
1256                         }
1257                         break;
1258                     default:
1259                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1260                     }
1261                 }
1262             }
1263         } /* End of textures */
1264
1265         /* Diffuse -------------------------------- */
1266         if (sd->u.s.diffuse.lpData != NULL) {
1267             glColor4ub((diffuseColor >> 16) & 0xFF,
1268                        (diffuseColor >>  8) & 0xFF,
1269                        (diffuseColor >>  0) & 0xFF,
1270                        (diffuseColor >> 24) & 0xFF);
1271             VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1272                     ((diffuseColor >> 16) & 0xFF) / 255.0f,
1273                     ((diffuseColor >>  8) & 0xFF) / 255.0f,
1274                     ((diffuseColor >>  0) & 0xFF) / 255.0f,
1275                     ((diffuseColor >> 24) & 0xFF) / 255.0f));
1276         } else {
1277             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1278         }
1279
1280         /* Specular ------------------------------- */
1281         if (sd->u.s.diffuse.lpData != NULL) {
1282             VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1283                     ((specularColor >> 16) & 0xFF) / 255.0f,
1284                     ((specularColor >>  8) & 0xFF) / 255.0f,
1285                     ((specularColor >>  0) & 0xFF) / 255.0f));
1286             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1287                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1288                            (specularColor >> 16) & 0xFF,
1289                            (specularColor >>  8) & 0xFF,
1290                            (specularColor >>  0) & 0xFF);
1291             } else {
1292                 /* Do not worry if specular colour missing and disable request */
1293                 VTRACE(("Specular color extensions not supplied\n"));
1294             }
1295         } else {
1296             if (vx_index == 0) {
1297                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1298                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1299                 } else {
1300                     /* Do not worry if specular colour missing and disable request */
1301                     VTRACE(("Specular color extensions not supplied\n"));
1302                 }
1303             }
1304         }
1305
1306         /* Normal -------------------------------- */
1307         if (sd->u.s.normal.lpData != NULL) {
1308             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1309             glNormal3f(nx, ny, nz);
1310         } else {
1311             if (vx_index == 0) glNormal3f(0, 0, 1);
1312         }
1313
1314         /* Position -------------------------------- */
1315         if (sd->u.s.position.lpData != NULL) {
1316             if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1317                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1318                 glVertex3f(x, y, z);
1319             } else {
1320                 GLfloat w = 1.0 / rhw;
1321                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1322                 glVertex4f(x*w, y*w, z*w, w);
1323             }
1324         }
1325
1326         /* For non indexed mode, step onto next parts */
1327         if (idxData == NULL) {
1328             ++SkipnStrides;
1329         }
1330     }
1331
1332     glEnd();
1333     checkGLcall("glEnd and previous calls");
1334 }
1335
1336 #if 0 /* TODO: Software/Hardware vertex blending support */
1337 /*
1338  * Draw with emulated vertex shaders
1339  * Note: strided data is uninitialized, as we need to pass the vertex
1340  *     shader directly as ordering irs yet
1341  */
1342 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1343                      int PrimitiveType, ULONG NumPrimitives,
1344                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1345
1346     unsigned int               textureNo    = 0;
1347     GLenum                     glPrimType   = GL_POINTS;
1348     int                        NumVertexes  = NumPrimitives;
1349     const short               *pIdxBufS     = NULL;
1350     const long                *pIdxBufL     = NULL;
1351     LONG                       SkipnStrides = 0;
1352     LONG                       vx_index;
1353     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1354     float rhw = 0.0f;                      /* rhw                        */
1355     float ptSize = 0.0f;                   /* Point size                 */
1356     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1357     int   numcoords[8];                    /* Number of coords           */
1358     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1359
1360     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1361
1362     TRACE("Using slow software vertex shader code\n");
1363
1364     /* Variable Initialization */
1365     if (idxData != NULL) {
1366         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1367         else pIdxBufL = (const long *) idxData;
1368     }
1369
1370     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1371     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1372
1373     /* Retrieve the VS information */
1374     vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1375
1376     /* Start drawing in GL */
1377     VTRACE(("glBegin(%x)\n", glPrimType));
1378     glBegin(glPrimType);
1379
1380     /* For each primitive */
1381     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1382
1383         /* For indexed data, we need to go a few more strides in */
1384         if (idxData != NULL) {
1385
1386             /* Indexed so work out the number of strides to skip */
1387             if (idxSize == 2) {
1388                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1389                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1390             } else {
1391                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1392                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1393             }
1394         }
1395
1396         /* Fill the vertex shader input */
1397         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1398
1399         /* Initialize the output fields to the same defaults as it would normally have */
1400         memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1401         vertex_shader->output.oD[0].x = 1.0;
1402         vertex_shader->output.oD[0].y = 1.0;
1403         vertex_shader->output.oD[0].z = 1.0;
1404         vertex_shader->output.oD[0].w = 1.0;
1405
1406         /* Now execute the vertex shader */
1407         IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1408
1409         /*
1410         TRACE_VECTOR(vertex_shader->output.oPos);
1411         TRACE_VECTOR(vertex_shader->output.oD[0]);
1412         TRACE_VECTOR(vertex_shader->output.oD[1]);
1413         TRACE_VECTOR(vertex_shader->output.oT[0]);
1414         TRACE_VECTOR(vertex_shader->output.oT[1]);
1415         TRACE_VECTOR(vertex_shader->input.V[0]);
1416         TRACE_VECTOR(vertex_shader->data->C[0]);
1417         TRACE_VECTOR(vertex_shader->data->C[1]);
1418         TRACE_VECTOR(vertex_shader->data->C[2]);
1419         TRACE_VECTOR(vertex_shader->data->C[3]);
1420         TRACE_VECTOR(vertex_shader->data->C[4]);
1421         TRACE_VECTOR(vertex_shader->data->C[5]);
1422         TRACE_VECTOR(vertex_shader->data->C[6]);
1423         TRACE_VECTOR(vertex_shader->data->C[7]);
1424         */
1425
1426         /* Extract out the output */
1427         /*FIXME: Fog coords? */
1428         x = vertex_shader->output.oPos.x;
1429         y = vertex_shader->output.oPos.y;
1430         z = vertex_shader->output.oPos.z;
1431         rhw = vertex_shader->output.oPos.w;
1432         ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1433
1434         /** Update textures coords using vertex_shader->output.oT[0->7] */
1435         memset(texcoords, 0x00, sizeof(texcoords));
1436         memset(numcoords, 0x00, sizeof(numcoords));
1437         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1438             if (This->stateBlock->textures[textureNo] != NULL) {
1439                texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1440                texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1441                texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1442                texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1443                if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1444                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1445                } else {
1446                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1447                    case D3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1448                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1449                    default:                     numcoords[textureNo] = 4;
1450                    }
1451                }
1452             } else {
1453                 numcoords[textureNo] = 0;
1454             }
1455         }
1456
1457         /* Draw using this information */
1458         draw_vertex(iface,
1459                     TRUE, x, y, z, rhw,
1460                     TRUE, 0.0f, 0.0f, 1.0f,
1461                     TRUE, (float*) &vertex_shader->output.oD[0],
1462                     TRUE, (float*) &vertex_shader->output.oD[1],
1463                     FALSE, ptSize,         /* FIXME: Change back when supported */
1464                     texcoords, numcoords);
1465
1466         /* For non indexed mode, step onto next parts */
1467         if (idxData == NULL) {
1468            ++SkipnStrides;
1469         }
1470
1471     } /* for each vertex */
1472
1473     glEnd();
1474     checkGLcall("glEnd and previous calls");
1475 }
1476
1477 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1478                      int PrimitiveType, ULONG NumPrimitives,
1479                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1480
1481     IDirect3DVertexShaderImpl *vertex_shader = NULL;
1482     int                        i;
1483     int                        NumVertexes;
1484     int                        glPrimType;
1485     int                        maxAttribs;
1486
1487     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1488     TRACE("Drawing with hardware vertex shaders\n");
1489
1490     /* Retrieve the VS information */
1491     vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1492
1493     /* Enable the Vertex Shader */
1494     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1495     checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1496     glEnable(GL_VERTEX_PROGRAM_ARB);
1497     checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1498
1499     /* Update the constants */
1500     for (i = 0; i < D3D8_VSHADER_MAX_CONSTANTS; ++i) {
1501         GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1502         checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1503     }
1504
1505     /* Set up the vertex.attr[n] inputs */
1506     IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1507
1508     /* Ok, Work out which primitive is requested and how many vertexes that
1509        will be                                                              */
1510     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1511
1512     /* Finally do the drawing */
1513     if (idxData != NULL) {
1514
1515         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1516 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1517         glDrawElements(glPrimType, NumVertexes, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1518                       (const char *)idxData + (idxSize * startIdx));
1519 #else
1520         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes - 1, NumVertexes,
1521                       idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1522                       (const char *)idxData + (idxSize * startIdx));
1523 #endif
1524         checkGLcall("glDrawRangeElements");
1525
1526     } else {
1527
1528         /* Note first is now zero as we shuffled along earlier */
1529         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1530         glDrawArrays(glPrimType, 0, NumVertexes);
1531         checkGLcall("glDrawArrays");
1532
1533     }
1534
1535     {
1536     GLint errPos;
1537     glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1538     if (errPos != -1)
1539         FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1540     }
1541
1542
1543     /* Leave all the attribs disabled */
1544     glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1545     /* MESA does not support it right not */
1546     if (glGetError() != GL_NO_ERROR)
1547         maxAttribs = 16;
1548     for (i = 0; i < maxAttribs; ++i) {
1549         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1550         checkGLcall("glDisableVertexAttribArrayARB(reg);");
1551     }
1552
1553     /* Done */
1554     glDisable(GL_VERTEX_PROGRAM_ARB);
1555 }
1556 #endif
1557
1558 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1559
1560     /* Dump out what parts we have supplied */
1561     TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1562     TRACE_STRIDED((dataLocations), position);
1563     TRACE_STRIDED((dataLocations), blendWeights);
1564     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1565     TRACE_STRIDED((dataLocations), normal);
1566     TRACE_STRIDED((dataLocations), pSize);
1567     TRACE_STRIDED((dataLocations), diffuse);
1568     TRACE_STRIDED((dataLocations), specular);
1569     TRACE_STRIDED((dataLocations), texCoords[0]);
1570     TRACE_STRIDED((dataLocations), texCoords[1]);
1571     TRACE_STRIDED((dataLocations), texCoords[2]);
1572     TRACE_STRIDED((dataLocations), texCoords[3]);
1573     TRACE_STRIDED((dataLocations), texCoords[4]);
1574     TRACE_STRIDED((dataLocations), texCoords[5]);
1575     TRACE_STRIDED((dataLocations), texCoords[6]);
1576     TRACE_STRIDED((dataLocations), texCoords[7]);
1577     return;
1578
1579 }
1580
1581 /* loads any dirty textures and returns true if any of the textures are nonpower2 */
1582 BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
1583     BOOL nonPower2 = FALSE;
1584     unsigned int i;
1585     register IWineD3DBaseTexture *texture;
1586     /* And re-upload any dirty textures */
1587     for (i = 0; i < GL_LIMITS(textures); ++i) {
1588         texture = This->stateBlock->textures[i];
1589         if (texture != NULL) {
1590             if(IWineD3DBaseTexture_GetDirty(texture)) {
1591                 /* Load up the texture now */
1592                 IWineD3DTexture_PreLoad((IWineD3DTexture *)texture);
1593             }
1594             if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) {
1595                 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1596                 IWineD3DSurface *surface;
1597                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface);
1598                 if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
1599                     nonPower2 = TRUE;
1600                 }
1601             }
1602         }
1603     }
1604     return nonPower2;
1605 }
1606
1607 /* Routine common to the draw primitive and draw indexed primitive routines */
1608 void drawPrimitive(IWineD3DDevice *iface,
1609                     int PrimitiveType, long NumPrimitives,
1610
1611                     /* for Indexed: */
1612                     long  StartVertexIndex,
1613                     long  StartIdx,
1614                     short idxSize,
1615                     const void *idxData,
1616                     int   minIndex) {
1617
1618     BOOL                          rc = FALSE;
1619     DWORD                         fvf = 0;
1620 #if 0 /* TODO: vertex and pixel shaders */
1621     IDirect3DVertexShaderImpl    *vertex_shader = NULL;
1622     IDirect3DPixelShaderImpl     *pixel_shader = NULL;
1623 #endif
1624     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1625     BOOL                          useVertexShaderFunction = FALSE;
1626     BOOL                          isLightingOn = FALSE;
1627     Direct3DVertexStridedData     dataLocations;
1628     int                           useHW = FALSE;
1629     BOOL                          nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */
1630
1631     if (This->stateBlock->vertexDecl == NULL) {
1632         /* Work out what the FVF should look like */
1633         rc = initializeFVF(iface, &fvf);
1634         if (rc) return;
1635     } else {
1636         TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1637     }
1638
1639     /* If we will be using a vertex shader, do some initialization for it */
1640     if (useVertexShaderFunction) {
1641 #if 0 /* TODO: vertex and pixel shaders */
1642         vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1643         memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1644
1645         useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1646                  This->devType != D3DDEVTYPE_REF &&
1647                  !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1648                  vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1649
1650         /** init Constants */
1651         if (This->stateBlock->Changed.vertexShaderConstant) {
1652             TRACE_(d3d_shader)("vertex shader initializing constants\n");
1653             IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1654         }
1655 #endif /* TODO: vertex and pixel shaders */
1656     }
1657
1658     /* Ok, we will be updating the screen from here onwards so grab the lock */
1659     ENTER_GL();
1660
1661 #if 0 /* TODO: vertex and pixel shaders */
1662     /* If we will be using a pixel, do some initialization for it */
1663     if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1664         TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1665         memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1666
1667         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1668         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1669         glEnable(GL_FRAGMENT_PROGRAM_ARB);
1670         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1671
1672         /* init Constants */
1673         if (This->stateBlock->Changed.pixelShaderConstant) {
1674             TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1675             IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1676         }
1677         /* Update the constants */
1678         for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1679             GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1680             checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1681         }
1682     }
1683 #endif /* TODO: vertex and pixel shaders */
1684
1685     /* Initialize all values to null */
1686     if (useVertexShaderFunction == FALSE) {
1687         memset(&dataLocations, 0x00, sizeof(dataLocations));
1688
1689         /* Convert to strided data */
1690          if (This->stateBlock->vertexDecl != NULL) {
1691             TRACE("================ Vertex Declaration  ===================\n");
1692             primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1693          } else {
1694             TRACE("================ FVF ===================\n");
1695             primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1696          }
1697
1698         /* write out some debug information*/
1699         drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1700     } else {
1701         FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1702     }
1703
1704     /* Setup transform matrices and sort out */
1705     if (useHW) {
1706         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1707         So make sure lighting is disabled. */
1708         isLightingOn = glIsEnabled(GL_LIGHTING);
1709         glDisable(GL_LIGHTING);
1710         checkGLcall("glDisable(GL_LIGHTING);");
1711         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1712     } else {
1713         isLightingOn = primitiveInitState(iface,
1714                                           fvf & D3DFVF_XYZRHW,
1715                                           !(fvf & D3DFVF_NORMAL),
1716                                           useVertexShaderFunction);
1717     }
1718
1719     /* Now initialize the materials state */
1720     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1721
1722     nonPower2 = drawPrimitiveUploadDirtyTextures(This);
1723
1724     /* Now draw the graphics to the screen */
1725     if  (useVertexShaderFunction) {
1726
1727         /* Ideally, we should have software FV and hardware VS, possibly
1728            depending on the device type?                                 */
1729
1730         if (useHW) {
1731             TRACE("Swap HW vertex shader\n");
1732 #if 0 /* TODO: vertex and pixel shaders */
1733             drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1734                         idxData, idxSize, minIndex, StartIdx);
1735 #endif
1736         } else {
1737             /* We will have to use the very, very slow emulation layer */
1738             TRACE("Swap SW vertex shader\n");
1739 #if 0 /* TODO: vertex and pixel shaders */
1740             drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1741                         idxData, idxSize, minIndex, StartIdx);
1742 #endif
1743         }
1744
1745     } else if ((dataLocations.u.s.pSize.lpData           != NULL)
1746                || (dataLocations.u.s.diffuse.lpData      != NULL)
1747                || nonPower2
1748                /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1749
1750         /* Fixme, Ideally, only use the per-vertex code for software HAL
1751            but until opengl supports all the functions returned to setup
1752            vertex arrays, we need to drop down to the slow mechanism for
1753            certain functions                                              */
1754
1755         /* We will have to use the slow version of GL per vertex setup */
1756         drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1757                         idxData, idxSize, minIndex, StartIdx);
1758
1759     } else {
1760
1761         /* We can use the fast version of GL pointers */
1762         drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1763                         idxData, idxSize, minIndex, StartIdx);
1764     }
1765
1766     /* If vertex shaders or no normals, restore previous lighting state */
1767     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1768         if (isLightingOn) glEnable(GL_LIGHTING);
1769         else glDisable(GL_LIGHTING);
1770         TRACE("Restored lighting to original state\n");
1771     }
1772
1773 #if 0 /* TODO: vertex and pixel shaders */
1774     if (pixel_shader)
1775     {
1776 #if 0
1777       GLint errPos;
1778       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1779       if (errPos != -1)
1780         FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1781 #endif
1782       glDisable(GL_FRAGMENT_PROGRAM_ARB);
1783     }
1784 #endif
1785
1786     /* Finshed updating the screen, restore lock */
1787     LEAVE_GL();
1788     TRACE("Done all gl drawing\n");
1789
1790     /* Diagnostics */
1791 #if defined(SHOW_FRAME_MAKEUP)
1792     {
1793         if (isDumpingFrames) {
1794             D3DLOCKED_RECT r;
1795             char buffer[80];
1796             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1797             sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1798             TRACE("Saving screenshot %s\n", buffer);
1799             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1800             IWineD3DSurface_UnlockRect(This->renderTarget);
1801
1802 #if defined(SHOW_TEXTURE_MAKEUP)
1803            {
1804             IWineD3DSurface *pSur;
1805             int textureNo;
1806             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1807                 if (This->stateBlock->textures[textureNo] != NULL) {
1808                     sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1809                     TRACE("Saving texture %s\n", buffer);
1810                     IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur);
1811                     IWineD3DSurface_SaveSnapshot(pSur, buffer);
1812                     IWineD3DSurface_Release(pSur);
1813                 }
1814             }
1815            }
1816 #endif
1817            ++primCounter;
1818         }
1819     }
1820 #endif
1821 }