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