Correct a problem with the way that FVF vertex arrays containing
[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 *)This->stateBlock->streamSource[element->Stream])->resource.allocatedMemory;
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     BOOL          canDoViaGLPointers = TRUE;
541     int           numBlends;
542     int           numTextures;
543     int           textureNo;
544     int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
545     int           numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
546
547     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
548
549     /* OK, Now to setup the data locations
550        For the non-created vertex shaders, the VertexShader var holds the real
551           FVF and only stream 0 matters
552        For the created vertex shaders, there is an FVF per stream              */
553     if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
554         LoopThroughTo = MAX_STREAMS;
555     } else {
556         LoopThroughTo = 1;
557     }
558
559     /* Work through stream by stream */
560     for (nStream=0; nStream<LoopThroughTo; nStream++) {
561         DWORD  stride  = This->stateBlock->streamStride[nStream];
562         BYTE  *data    = NULL;
563         DWORD  thisFVF = 0;
564
565         /* Skip empty streams */
566         if (This->stateBlock->streamSource[nStream] == NULL) continue;
567
568         /* Retrieve appropriate FVF */
569         if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
570             thisFVF = This->stateBlock->fvf;
571             /* Handle memory passed directly as well as vertex buffers */
572             if (This->stateBlock->streamIsUP) {
573                 data    = (BYTE *)This->stateBlock->streamSource[nStream];
574             } else {
575                 data    = ((IWineD3DVertexBufferImpl *)This->stateBlock->streamSource[nStream])->resource.allocatedMemory;
576             }
577         } else {
578 #if 0 /* TODO: Vertex shader support */
579             thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
580             data    = ((IDirect3DVertexBuffer8Impl *)This->stateBlock->streamSource[nStream])->allocatedMemory;
581 #endif
582         }
583         VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
584         if (thisFVF == 0) continue;
585
586         /* Now convert the stream into pointers */
587
588         /* Shuffle to the beginning of the vertexes to render and index from there */
589         data = data + (BaseVertexIndex * stride);
590
591         /* Either 3 or 4 floats depending on the FVF */
592         /* FIXME: Can blending data be in a different stream to the position data?
593               and if so using the fixed pipeline how do we handle it               */
594         if (thisFVF & D3DFVF_POSITION_MASK) {
595             strided->u.s.position.lpData    = data;
596             strided->u.s.position.dwType    = D3DDECLTYPE_FLOAT3;
597             strided->u.s.position.dwStride  = stride;
598             data += 3 * sizeof(float);
599             if (thisFVF & D3DFVF_XYZRHW) {
600                 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
601                 data += sizeof(float);
602             }
603         }
604
605         /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
606         /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
607         numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
608         if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
609
610         if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
611             TRACE("Setting blend Weights to %p \n", data);
612             strided->u.s.blendWeights.lpData    = data;
613             strided->u.s.blendWeights.dwType    = D3DDECLTYPE_FLOAT1 + numBlends - 1;
614             strided->u.s.blendWeights.dwStride  = stride;
615             data += numBlends * sizeof(FLOAT);
616
617             if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
618                 strided->u.s.blendMatrixIndices.lpData = data;
619                 strided->u.s.blendMatrixIndices.dwType  = D3DDECLTYPE_UBYTE4;
620                 strided->u.s.blendMatrixIndices.dwStride= stride;
621                 data += sizeof(DWORD);
622             }
623         }
624
625         /* Normal is always 3 floats */
626         if (thisFVF & D3DFVF_NORMAL) {
627             strided->u.s.normal.lpData    = data;
628             strided->u.s.normal.dwType    = D3DDECLTYPE_FLOAT3;
629             strided->u.s.normal.dwStride  = stride;
630             data += 3 * sizeof(FLOAT);
631         }
632
633         /* Pointsize is a single float */
634         if (thisFVF & D3DFVF_PSIZE) {
635             strided->u.s.pSize.lpData    = data;
636             strided->u.s.pSize.dwType    = D3DDECLTYPE_FLOAT1;
637             strided->u.s.pSize.dwStride  = stride;
638             data += sizeof(FLOAT);
639         }
640
641         /* Diffuse is 4 unsigned bytes */
642         if (thisFVF & D3DFVF_DIFFUSE) {
643             strided->u.s.diffuse.lpData    = data;
644             strided->u.s.diffuse.dwType    = D3DDECLTYPE_SHORT4;
645             strided->u.s.diffuse.dwStride  = stride;
646             data += sizeof(DWORD);
647         }
648
649         /* Specular is 4 unsigned bytes */
650         if (thisFVF & D3DFVF_SPECULAR) {
651             strided->u.s.specular.lpData    = data;
652             strided->u.s.specular.dwType    = D3DDECLTYPE_SHORT4;
653             strided->u.s.specular.dwStride  = stride;
654             data += sizeof(DWORD);
655         }
656
657         /* Texture coords */
658         numTextures   = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
659         coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
660
661         /* numTextures indicates the number of texture coordinates supplied */
662         /* However, the first set may not be for stage 0 texture - it all   */
663         /*   depends on D3DTSS_TEXCOORDINDEX.                               */
664         /* The number of bytes for each coordinate set is based off         */
665         /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
666
667         /* So, for each supplied texture extract the coords */
668         for (textureNo = 0; textureNo < numTextures; ++textureNo) {
669
670             strided->u.s.texCoords[textureNo].lpData    = data;
671             strided->u.s.texCoords[textureNo].dwType    = D3DDECLTYPE_FLOAT1;
672             strided->u.s.texCoords[textureNo].dwStride  = stride;
673             numCoords[textureNo] = coordIdxInfo & 0x03;
674
675             /* Always one set */
676             data += sizeof(float);
677             if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
678                 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
679                 data += sizeof(float);
680                 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
681                     strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
682                     data += sizeof(float);
683                     if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
684                         strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
685                         data += sizeof(float);
686                     }
687                 }
688             }
689             coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
690         }
691     }
692 }
693
694 /* Draw a single vertex using this information */
695 static void draw_vertex(IWineD3DDevice *iface,                         /* interface    */
696                  BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
697                  BOOL isNormal, float nx, float ny, float nz,          /* normal       */
698                  BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
699                  BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
700                  BOOL isPtSize, float ptSize,                       /* pointSize    */
701                  WINED3DVECTOR_4 *texcoords, int *numcoords)        /* texture info */
702 {
703     unsigned int textureNo;
704     float s, t, r, q;
705     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
706
707     /* Diffuse -------------------------------- */
708     if (isDiffuse) {
709         glColor4fv(dRGBA);
710         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
711     }
712
713     /* Specular Colour ------------------------------------------*/
714     if (isSpecular) {
715         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
716           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
717           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
718         } else {
719           VTRACE(("Specular color extensions not supplied\n"));
720         }
721     }
722
723     /* Normal -------------------------------- */
724     if (isNormal) {
725         VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
726         glNormal3f(nx, ny, nz);
727     }
728
729     /* Point Size ----------------------------------------------*/
730     if (isPtSize) {
731
732         /* no such functionality in the fixed function GL pipeline */
733         FIXME("Cannot change ptSize here in openGl\n");
734     }
735
736     /* Texture coords --------------------------- */
737     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
738
739         if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
740             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
741             continue ;
742         }
743
744         /* Query tex coords */
745         if (This->stateBlock->textures[textureNo] != NULL) {
746
747             int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
748             if (coordIdx > 7) {
749                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
750                 continue;
751             } else if (numcoords[coordIdx] == 0) {
752                 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
753                 continue;
754             } else {
755
756                 /* Initialize vars */
757                 s = 0.0f;
758                 t = 0.0f;
759                 r = 0.0f;
760                 q = 0.0f;
761
762                 switch (numcoords[coordIdx]) {
763                 case 4: q = texcoords[coordIdx].w; /* drop through */
764                 case 3: r = texcoords[coordIdx].z; /* drop through */
765                 case 2: t = texcoords[coordIdx].y; /* drop through */
766                 case 1: s = texcoords[coordIdx].x;
767                 }
768
769                 switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
770                 case D3DTTFF_COUNT1:
771                     VTRACE(("tex:%d, s=%f\n", textureNo, s));
772                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
773                         GLMULTITEXCOORD1F(textureNo, s);
774                     } else {
775                         glTexCoord1f(s);
776                     }
777                     break;
778                 case D3DTTFF_COUNT2:
779                     VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
780                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
781                         GLMULTITEXCOORD2F(textureNo, s, t);
782                     } else {
783                         glTexCoord2f(s, t);
784                     }
785                     break;
786                 case D3DTTFF_COUNT3:
787                     VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
788                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
789                         GLMULTITEXCOORD3F(textureNo, s, t, r);
790                     } else {
791                         glTexCoord3f(s, t, r);
792                     }
793                     break;
794                 case D3DTTFF_COUNT4:
795                     VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
796                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
797                         GLMULTITEXCOORD4F(textureNo, s, t, r, q);
798                     } else {
799                         glTexCoord4f(s, t, r, q);
800                     }
801                     break;
802                 default:
803                     FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
804                 }
805             }
806         }
807     } /* End of textures */
808
809     /* Position -------------------------------- */
810     if (isXYZ) {
811         if (1.0f == rhw || rhw < 0.00001f) {
812             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
813             glVertex3f(x, y, z);
814         } else {
815             /* Cannot optimize by dividing through by rhw as rhw is required
816                later for perspective in the GL pipeline for vertex shaders   */
817             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
818             glVertex4f(x,y,z,rhw);
819         }
820     }
821 }
822
823 /*
824  * Actually draw using the supplied information.
825  * Faster GL version using pointers to data, harder to debug though
826  * Note does not handle vertex shaders yet
827  */
828 static void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
829                      int PrimitiveType, ULONG NumPrimitives,
830                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
831     unsigned int textureNo   = 0;
832     GLenum       glPrimType  = GL_POINTS;
833     int          NumVertexes = NumPrimitives;
834     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
835
836     TRACE("Using fast vertex array code\n");
837
838     /* Vertex Pointers -----------------------------------------*/
839     if (sd->u.s.position.lpData != NULL) {
840
841         /* Note dwType == float3 or float4 == 2 or 3 */
842         VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
843                 sd->u.s.position.dwStride,
844                 sd->u.s.position.dwType + 1,
845                 sd->u.s.position.lpData));
846
847         /* Disable RHW mode as 'w' coord handling for rhw mode should
848            not impact screen position whereas in GL it does. This may
849            result in very slightly distored textures in rhw mode, but
850            a very minimal different                                   */
851         glVertexPointer(3, GL_FLOAT,  /* RHW: Was 'sd->u.s.position.dwType + 1' */
852                         sd->u.s.position.dwStride,
853                         sd->u.s.position.lpData);
854         checkGLcall("glVertexPointer(...)");
855         glEnableClientState(GL_VERTEX_ARRAY);
856         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
857
858     } else {
859
860         glDisableClientState(GL_VERTEX_ARRAY);
861         checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
862     }
863
864     /* Blend Data ----------------------------------------------*/
865     if ((sd->u.s.blendWeights.lpData != NULL) ||
866         (sd->u.s.blendMatrixIndices.lpData != NULL)) {
867 #if 1 /* Vertex blend support needs to be added */
868         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
869             DWORD fvf = (sd->u.s.blendWeights.dwType - D3DDECLTYPE_FLOAT1) + 1;
870             int numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == (fvf & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);
871
872             /* Note dwType == float3 or float4 == 2 or 3 */
873             VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
874                     numBlends,
875                     sd->u.s.blendWeights.dwStride,
876                     sd->u.s.blendWeights.lpData));
877             GL_EXTCALL(glWeightPointerARB)(numBlends, GL_FLOAT,
878                                            sd->u.s.blendWeights.dwStride,
879                                            sd->u.s.blendWeights.lpData);
880             checkGLcall("glWeightPointerARB(...)");
881             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
882             checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
883         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
884             /*FIXME("TODO\n");*/
885             /*
886             GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
887             checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
888             glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
889             checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
890             */
891         } else {
892             FIXME("unsupported blending in openGl\n");
893         }
894     } else {
895         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
896             TRACE("TODO ARB_VERTEX_BLEND\n");
897         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
898             TRACE("TODO EXT_VERTEX_WEIGHTING\n");
899             /*
900             glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
901             checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
902             */
903         }
904 #else
905         /* FIXME: Won't get here as will drop to slow method        */
906         FIXME("Blending not supported in fast draw routine\n");
907 #endif
908     }
909
910     /* Normals -------------------------------------------------*/
911     if (sd->u.s.normal.lpData != NULL) {
912
913         /* Note dwType == float3 or float4 == 2 or 3 */
914         VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
915                 sd->u.s.normal.dwStride,
916                 sd->u.s.normal.lpData));
917         glNormalPointer(GL_FLOAT,
918                         sd->u.s.normal.dwStride,
919                         sd->u.s.normal.lpData);
920         checkGLcall("glNormalPointer(...)");
921         glEnableClientState(GL_NORMAL_ARRAY);
922         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
923
924     } else {
925
926         glDisableClientState(GL_NORMAL_ARRAY);
927         checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
928         glNormal3f(0, 0, 1);
929         checkGLcall("glNormal3f(0, 0, 1)");
930     }
931
932     /* Point Size ----------------------------------------------*/
933     if (sd->u.s.pSize.lpData != NULL) {
934
935         /* no such functionality in the fixed function GL pipeline */
936         /* FIXME: Won't get here as will drop to slow method        */
937         FIXME("Cannot change ptSize here in openGl\n");
938     }
939
940     /* Diffuse Colour ------------------------------------------*/
941     /*  WARNING: Data here MUST be in RGBA format, so cannot    */
942     /*     go directly into fast mode from app pgm, because     */
943     /*     directx requires data in BGRA format.                */
944     if (sd->u.s.diffuse.lpData != NULL) {
945
946         /* Note dwType == float3 or float4 == 2 or 3 */
947         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
948                 sd->u.s.diffuse.dwStride,
949                 sd->u.s.diffuse.lpData));
950         glColorPointer(4, GL_UNSIGNED_BYTE,
951                        sd->u.s.diffuse.dwStride,
952                        sd->u.s.diffuse.lpData);
953         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
954         glEnableClientState(GL_COLOR_ARRAY);
955         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
956
957     } else {
958
959         glDisableClientState(GL_COLOR_ARRAY);
960         checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
961         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
962         checkGLcall("glColor4f(1, 1, 1, 1)");
963     }
964
965     /* Specular Colour ------------------------------------------*/
966     if (sd->u.s.specular.lpData != NULL) {
967
968         /* Note dwType == float3 or float4 == 2 or 3 */
969         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
970                 sd->u.s.specular.dwStride,
971                 sd->u.s.specular.lpData));
972
973         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
974             GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
975                                                    sd->u.s.specular.dwStride,
976                                                    sd->u.s.specular.lpData);
977             vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
978             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
979             vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
980         } else {
981           /* Missing specular color is not critical, no warnings */
982           VTRACE(("Specular colour is not supported in this GL implementation\n"));
983         }
984
985     } else {
986
987       if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
988         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
989         checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
990         GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
991         checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
992       } else {
993         /* Missing specular color is not critical, no warnings */
994         VTRACE(("Specular colour is not supported in this GL implementation\n"));
995       }
996     }
997
998     /* Texture coords -------------------------------------------*/
999     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1000
1001         /* Select the correct texture stage */
1002         GLCLIENTACTIVETEXTURE(textureNo);
1003
1004         /* Query tex coords */
1005         if (This->stateBlock->textures[textureNo] != NULL) {
1006             int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1007
1008             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1009                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1010                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1011                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1012                 continue;
1013             }
1014
1015             if (coordIdx > 7) {
1016                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1017                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1018                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1019
1020             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1021                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1022                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1023                 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1024
1025             } else {
1026
1027                 /* The coords to supply depend completely on the fvf / vertex shader */
1028                 GLint size;
1029                 GLenum type;
1030
1031                 switch (sd->u.s.texCoords[coordIdx].dwType) {
1032                 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
1033                 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
1034                 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
1035                 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
1036                 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
1037                 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
1038                 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
1039                 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
1040                       size = 4; type = GL_UNSIGNED_BYTE;
1041                 }
1042
1043                 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1044                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1045             }
1046         } else {
1047             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1048             GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1049         }
1050     }
1051
1052     /* Ok, Work out which primitive is requested and how many vertexes that
1053        will be                                                              */
1054     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1055
1056     /* Finally do the drawing */
1057     if (idxData != NULL) {
1058
1059         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1060 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1061         glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1062                       (const char *)idxData+(idxSize * startIdx));
1063 #else
1064         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1065                       idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1066                       (const char *)idxData+(idxSize * startIdx));
1067 #endif
1068         checkGLcall("glDrawRangeElements");
1069
1070     } else {
1071
1072         /* Note first is now zero as we shuffled along earlier */
1073         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1074         glDrawArrays(glPrimType, 0, NumVertexes);
1075         checkGLcall("glDrawArrays");
1076
1077     }
1078 }
1079
1080 /*
1081  * Actually draw using the supplied information.
1082  * Slower GL version which extracts info about each vertex in turn
1083  */
1084 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1085                      int PrimitiveType, ULONG NumPrimitives,
1086                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1087
1088     unsigned int               textureNo    = 0;
1089     GLenum                     glPrimType   = GL_POINTS;
1090     int                        NumVertexes  = NumPrimitives;
1091     const short               *pIdxBufS     = NULL;
1092     const long                *pIdxBufL     = NULL;
1093     LONG                       SkipnStrides = 0;
1094     LONG                       vx_index;
1095     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1096     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
1097     float rhw = 0.0f;                      /* rhw                        */
1098     float ptSize = 0.0f;                   /* Point size                 */
1099     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
1100     DWORD specularColor = 0;               /* Specular Color             */
1101     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1102
1103     TRACE("Using slow vertex array code\n");
1104
1105     /* Variable Initialization */
1106     if (idxData != NULL) {
1107         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1108         else pIdxBufL = (const long *) idxData;
1109     }
1110
1111     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1112     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1113
1114     /* Start drawing in GL */
1115     VTRACE(("glBegin(%x)\n", glPrimType));
1116     glBegin(glPrimType);
1117
1118     /* For each primitive */
1119     for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1120
1121         /* Initialize diffuse color */
1122         diffuseColor = 0xFFFFFFFF;
1123
1124         /* For indexed data, we need to go a few more strides in */
1125         if (idxData != NULL) {
1126
1127             /* Indexed so work out the number of strides to skip */
1128             if (idxSize == 2) {
1129                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1130                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1131             } else {
1132                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1133                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1134             }
1135         }
1136
1137         /* Position Information ------------------ */
1138         if (sd->u.s.position.lpData != NULL) {
1139
1140             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1141             x = ptrToCoords[0];
1142             y = ptrToCoords[1];
1143             z = ptrToCoords[2];
1144             rhw = 1.0;
1145             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1146
1147             /* RHW follows, only if transformed, ie 4 floats were provided */
1148             if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1149                 rhw = ptrToCoords[3];
1150                 VTRACE(("rhw=%f\n", rhw));
1151             }
1152         }
1153
1154         /* Blending data -------------------------- */
1155         if (sd->u.s.blendWeights.lpData != NULL) {
1156             /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1157             FIXME("Blending not supported yet\n");
1158
1159             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1160                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1161             }
1162         }
1163
1164         /* Vertex Normal Data (untransformed only)- */
1165         if (sd->u.s.normal.lpData != NULL) {
1166
1167             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1168             nx = ptrToCoords[0];
1169             ny = ptrToCoords[1];
1170             nz = ptrToCoords[2];
1171             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1172         }
1173
1174         /* Point Size ----------------------------- */
1175         if (sd->u.s.pSize.lpData != NULL) {
1176
1177             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1178             ptSize = ptrToCoords[0];
1179             VTRACE(("ptSize=%f\n", ptSize));
1180             FIXME("No support for ptSize yet\n");
1181         }
1182
1183         /* Diffuse -------------------------------- */
1184         if (sd->u.s.diffuse.lpData != NULL) {
1185
1186             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1187             diffuseColor = ptrToCoords[0];
1188             VTRACE(("diffuseColor=%lx\n", diffuseColor));
1189         }
1190
1191         /* Specular  -------------------------------- */
1192         if (sd->u.s.specular.lpData != NULL) {
1193
1194             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1195             specularColor = ptrToCoords[0];
1196             VTRACE(("specularColor=%lx\n", specularColor));
1197         }
1198
1199         /* Texture coords --------------------------- */
1200         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1201
1202             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1203                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1204                 continue ;
1205             }
1206
1207             /* Query tex coords */
1208             if (This->stateBlock->textures[textureNo] != NULL) {
1209
1210                 int    coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1211                 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1212                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1213
1214                 if (coordIdx > 7) {
1215                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1216                     continue;
1217                 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1218                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1219                     continue;
1220                 } else {
1221
1222                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1223
1224                     /* The coords to supply depend completely on the fvf / vertex shader */
1225                     switch (coordsToUse) {
1226                     case 4: q = ptrToCoords[3]; /* drop through */
1227                     case 3: r = ptrToCoords[2]; /* drop through */
1228                     case 2: t = ptrToCoords[1]; /* drop through */
1229                     case 1: s = ptrToCoords[0];
1230                     }
1231
1232                     /* Projected is more 'fun' - Move the last coord to the 'q'
1233                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1234                     if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1235                         (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1236
1237                         if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1238                             switch (coordsToUse) {
1239                             case 0:  /* Drop Through */
1240                             case 1:
1241                                 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1242                                 break;
1243                             case 2:
1244                                 q = t;
1245                                 t = 0.0;
1246                                 coordsToUse = 4;
1247                                 break;
1248                             case 3:
1249                                 q = r;
1250                                 r = 0.0;
1251                                 coordsToUse = 4;
1252                                 break;
1253                             case 4:  /* Nop here */
1254                                 break;
1255                             default:
1256                                 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1257                                       This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1258                             }
1259                         }
1260                     }
1261
1262                     /* crude support for non-power2 textures */
1263                     if(((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2){
1264                         t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY;
1265                         s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX;
1266                     }
1267
1268                     switch (coordsToUse) {   /* Supply the provided texture coords */
1269                     case D3DTTFF_COUNT1:
1270                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1271                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1272                             GLMULTITEXCOORD1F(textureNo, s);
1273                         } else {
1274                             glTexCoord1f(s);
1275                         }
1276                         break;
1277                     case D3DTTFF_COUNT2:
1278                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1279                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1280                             GLMULTITEXCOORD2F(textureNo, s, t);
1281                         } else {
1282                             glTexCoord2f(s, t);
1283                         }
1284                         break;
1285                     case D3DTTFF_COUNT3:
1286                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1287                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1288                             GLMULTITEXCOORD3F(textureNo, s, t, r);
1289                         } else {
1290                             glTexCoord3f(s, t, r);
1291                         }
1292                         break;
1293                     case D3DTTFF_COUNT4:
1294                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1295                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1296                             GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1297                         } else {
1298                             glTexCoord4f(s, t, r, q);
1299                         }
1300                         break;
1301                     default:
1302                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1303                     }
1304                 }
1305             }
1306         } /* End of textures */
1307
1308         /* Diffuse -------------------------------- */
1309         if (sd->u.s.diffuse.lpData != NULL) {
1310             glColor4ub((diffuseColor >> 16) & 0xFF,
1311                        (diffuseColor >>  8) & 0xFF,
1312                        (diffuseColor >>  0) & 0xFF,
1313                        (diffuseColor >> 24) & 0xFF);
1314             VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1315                     ((diffuseColor >> 16) & 0xFF) / 255.0f,
1316                     ((diffuseColor >>  8) & 0xFF) / 255.0f,
1317                     ((diffuseColor >>  0) & 0xFF) / 255.0f,
1318                     ((diffuseColor >> 24) & 0xFF) / 255.0f));
1319         } else {
1320             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1321         }
1322
1323         /* Specular ------------------------------- */
1324         if (sd->u.s.diffuse.lpData != NULL) {
1325             VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1326                     ((specularColor >> 16) & 0xFF) / 255.0f,
1327                     ((specularColor >>  8) & 0xFF) / 255.0f,
1328                     ((specularColor >>  0) & 0xFF) / 255.0f));
1329             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1330                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1331                            (specularColor >> 16) & 0xFF,
1332                            (specularColor >>  8) & 0xFF,
1333                            (specularColor >>  0) & 0xFF);
1334             } else {
1335                 /* Do not worry if specular colour missing and disable request */
1336                 VTRACE(("Specular color extensions not supplied\n"));
1337             }
1338         } else {
1339             if (vx_index == 0) {
1340                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1341                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1342                 } else {
1343                     /* Do not worry if specular colour missing and disable request */
1344                     VTRACE(("Specular color extensions not supplied\n"));
1345                 }
1346             }
1347         }
1348
1349         /* Normal -------------------------------- */
1350         if (sd->u.s.normal.lpData != NULL) {
1351             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1352             glNormal3f(nx, ny, nz);
1353         } else {
1354             if (vx_index == 0) glNormal3f(0, 0, 1);
1355         }
1356
1357         /* Position -------------------------------- */
1358         if (sd->u.s.position.lpData != NULL) {
1359             if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1360                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1361                 glVertex3f(x, y, z);
1362             } else {
1363                 GLfloat w = 1.0 / rhw;
1364                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1365                 glVertex4f(x*w, y*w, z*w, w);
1366             }
1367         }
1368
1369         /* For non indexed mode, step onto next parts */
1370         if (idxData == NULL) {
1371             SkipnStrides += 1;
1372         }
1373     }
1374
1375     glEnd();
1376     checkGLcall("glEnd and previous calls");
1377 }
1378
1379 #if 0 /* TODO: Software/Hardware vertex blending support */
1380 /*
1381  * Draw with emulated vertex shaders
1382  * Note: strided data is uninitialized, as we need to pass the vertex
1383  *     shader directly as ordering irs yet
1384  */
1385 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1386                      int PrimitiveType, ULONG NumPrimitives,
1387                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1388
1389     unsigned int               textureNo    = 0;
1390     GLenum                     glPrimType   = GL_POINTS;
1391     int                        NumVertexes  = NumPrimitives;
1392     const short               *pIdxBufS     = NULL;
1393     const long                *pIdxBufL     = NULL;
1394     LONG                       SkipnStrides = 0;
1395     LONG                       vx_index;
1396     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1397     float rhw = 0.0f;                      /* rhw                        */
1398     float ptSize = 0.0f;                   /* Point size                 */
1399     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1400     int   numcoords[8];                    /* Number of coords           */
1401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1402
1403     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1404
1405     TRACE("Using slow software vertex shader code\n");
1406
1407     /* Variable Initialization */
1408     if (idxData != NULL) {
1409         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1410         else pIdxBufL = (const long *) idxData;
1411     }
1412
1413     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1414     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1415
1416     /* Retrieve the VS information */
1417     vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1418
1419     /* Start drawing in GL */
1420     VTRACE(("glBegin(%x)\n", glPrimType));
1421     glBegin(glPrimType);
1422
1423     /* For each primitive */
1424     for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1425
1426         /* For indexed data, we need to go a few more strides in */
1427         if (idxData != NULL) {
1428
1429             /* Indexed so work out the number of strides to skip */
1430             if (idxSize == 2) {
1431                 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1432                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1433             } else {
1434                 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1435                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1436             }
1437         }
1438
1439         /* Fill the vertex shader input */
1440         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1441
1442         /* Initialize the output fields to the same defaults as it would normally have */
1443         memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1444         vertex_shader->output.oD[0].x = 1.0;
1445         vertex_shader->output.oD[0].y = 1.0;
1446         vertex_shader->output.oD[0].z = 1.0;
1447         vertex_shader->output.oD[0].w = 1.0;
1448
1449         /* Now execute the vertex shader */
1450         IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1451
1452         /*
1453         TRACE_VECTOR(vertex_shader->output.oPos);
1454         TRACE_VECTOR(vertex_shader->output.oD[0]);
1455         TRACE_VECTOR(vertex_shader->output.oD[1]);
1456         TRACE_VECTOR(vertex_shader->output.oT[0]);
1457         TRACE_VECTOR(vertex_shader->output.oT[1]);
1458         TRACE_VECTOR(vertex_shader->input.V[0]);
1459         TRACE_VECTOR(vertex_shader->data->C[0]);
1460         TRACE_VECTOR(vertex_shader->data->C[1]);
1461         TRACE_VECTOR(vertex_shader->data->C[2]);
1462         TRACE_VECTOR(vertex_shader->data->C[3]);
1463         TRACE_VECTOR(vertex_shader->data->C[4]);
1464         TRACE_VECTOR(vertex_shader->data->C[5]);
1465         TRACE_VECTOR(vertex_shader->data->C[6]);
1466         TRACE_VECTOR(vertex_shader->data->C[7]);
1467         */
1468
1469         /* Extract out the output */
1470         /*FIXME: Fog coords? */
1471         x = vertex_shader->output.oPos.x;
1472         y = vertex_shader->output.oPos.y;
1473         z = vertex_shader->output.oPos.z;
1474         rhw = vertex_shader->output.oPos.w;
1475         ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1476
1477         /** Update textures coords using vertex_shader->output.oT[0->7] */
1478         memset(texcoords, 0x00, sizeof(texcoords));
1479         memset(numcoords, 0x00, sizeof(numcoords));
1480         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1481             if (This->stateBlock->textures[textureNo] != NULL) {
1482                texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1483                texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1484                texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1485                texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1486                if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1487                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1488                } else {
1489                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1490                    case D3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1491                    case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1492                    default:                     numcoords[textureNo] = 4;
1493                    }
1494                }
1495             } else {
1496                 numcoords[textureNo] = 0;
1497             }
1498         }
1499
1500         /* Draw using this information */
1501         draw_vertex(iface,
1502                     TRUE, x, y, z, rhw,
1503                     TRUE, 0.0f, 0.0f, 1.0f,
1504                     TRUE, (float*) &vertex_shader->output.oD[0],
1505                     TRUE, (float*) &vertex_shader->output.oD[1],
1506                     FALSE, ptSize,         /* FIXME: Change back when supported */
1507                     texcoords, numcoords);
1508
1509         /* For non indexed mode, step onto next parts */
1510         if (idxData == NULL) {
1511             SkipnStrides += 1;
1512         }
1513
1514     } /* for each vertex */
1515
1516     glEnd();
1517     checkGLcall("glEnd and previous calls");
1518 }
1519
1520 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1521                      int PrimitiveType, ULONG NumPrimitives,
1522                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1523
1524     IDirect3DVertexShaderImpl* vertex_shader = NULL;
1525     int                        i;
1526     int                        NumVertexes;
1527     int                        glPrimType;
1528     int                        maxAttribs;
1529
1530     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1531     TRACE("Drawing with hardware vertex shaders\n");
1532
1533     /* Retrieve the VS information */
1534     vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1535
1536     /* Enable the Vertex Shader */
1537     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1538     checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1539     glEnable(GL_VERTEX_PROGRAM_ARB);
1540     checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1541
1542     /* Update the constants */
1543     for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1544         GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1545         checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1546     }
1547
1548     /* Set up the vertex.attr[n] inputs */
1549     IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1550
1551     /* Ok, Work out which primitive is requested and how many vertexes that
1552        will be                                                              */
1553     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1554
1555     /* Finally do the drawing */
1556     if (idxData != NULL) {
1557
1558         TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1559 #if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1560         glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1561                       (const char *)idxData+(idxSize * startIdx));
1562 #else
1563         glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1564                       idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1565                       (const char *)idxData+(idxSize * startIdx));
1566 #endif
1567         checkGLcall("glDrawRangeElements");
1568
1569     } else {
1570
1571         /* Note first is now zero as we shuffled along earlier */
1572         TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1573         glDrawArrays(glPrimType, 0, NumVertexes);
1574         checkGLcall("glDrawArrays");
1575
1576     }
1577
1578     {
1579     GLint errPos;
1580     glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1581     if (errPos != -1)
1582         FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1583     }
1584
1585
1586     /* Leave all the attribs disabled */
1587     glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1588     /* MESA does not support it right not */
1589     if (glGetError() != GL_NO_ERROR)
1590         maxAttribs = 16;
1591     for (i=0; i<maxAttribs; i++) {
1592         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1593         checkGLcall("glDisableVertexAttribArrayARB(reg);");
1594     }
1595
1596     /* Done */
1597     glDisable(GL_VERTEX_PROGRAM_ARB);
1598 }
1599 #endif
1600
1601 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf){
1602
1603     /* Dump out what parts we have supplied */
1604     TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1605     TRACE_STRIDED((dataLocations), position);
1606     TRACE_STRIDED((dataLocations), blendWeights);
1607     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1608     TRACE_STRIDED((dataLocations), normal);
1609     TRACE_STRIDED((dataLocations), pSize);
1610     TRACE_STRIDED((dataLocations), diffuse);
1611     TRACE_STRIDED((dataLocations), specular);
1612     TRACE_STRIDED((dataLocations), texCoords[0]);
1613     TRACE_STRIDED((dataLocations), texCoords[1]);
1614     TRACE_STRIDED((dataLocations), texCoords[2]);
1615     TRACE_STRIDED((dataLocations), texCoords[3]);
1616     TRACE_STRIDED((dataLocations), texCoords[4]);
1617     TRACE_STRIDED((dataLocations), texCoords[5]);
1618     TRACE_STRIDED((dataLocations), texCoords[6]);
1619     TRACE_STRIDED((dataLocations), texCoords[7]);
1620     return;
1621
1622 }
1623
1624 /* loads any dirty textures and returns true if any of the textures are nonpower2 */
1625 BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
1626     BOOL nonPower2 = FALSE;
1627     unsigned int i;
1628     register IWineD3DBaseTexture *texture;
1629     /* And re-upload any dirty textures */
1630     for (i = 0; i<GL_LIMITS(textures); ++i) {
1631         texture = This->stateBlock->textures[i];
1632         if (texture != NULL) {
1633             if(IWineD3DBaseTexture_GetDirty(texture)) {
1634                 /* Load up the texture now */
1635                 IWineD3DTexture_PreLoad((IWineD3DTexture *)texture);
1636             }
1637             if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) {
1638                 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1639                 IWineD3DSurface *surface;
1640                 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface);
1641                 if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
1642                     nonPower2 = TRUE;
1643                 }
1644             }
1645         }
1646     }
1647     return nonPower2;
1648 }
1649
1650 /* Routine common to the draw primitive and draw indexed primitive routines */
1651 void drawPrimitive(IWineD3DDevice *iface,
1652                     int PrimitiveType, long NumPrimitives,
1653
1654                     /* for Indexed: */
1655                     long  StartVertexIndex,
1656                     long  StartIdx,
1657                     short idxSize,
1658                     const void *idxData,
1659                     int   minIndex) {
1660
1661     BOOL                          rc = FALSE;
1662     DWORD                         fvf = 0;
1663 #if 0 /* TODO: vertex and pixel shaders */
1664     IDirect3DVertexShaderImpl    *vertex_shader = NULL;
1665     IDirect3DPixelShaderImpl     *pixel_shader = NULL;
1666 #endif
1667     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1668     BOOL                          useVertexShaderFunction = FALSE;
1669     BOOL                          isLightingOn = FALSE;
1670     Direct3DVertexStridedData     dataLocations;
1671     int                           useHW = FALSE;
1672     BOOL                          nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */
1673
1674     if (This->stateBlock->vertexDecl == NULL) {
1675         /* Work out what the FVF should look like */
1676         rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1677         if (rc) return;
1678     } else {
1679         TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1680     }
1681
1682     /* If we will be using a vertex shader, do some initialization for it */
1683     if (useVertexShaderFunction) {
1684 #if 0 /* TODO: vertex and pixel shaders */
1685         vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1686         memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1687
1688         useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1689                  This->devType != D3DDEVTYPE_REF &&
1690                  !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1691                  vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1692
1693         /** init Constants */
1694         if (This->stateBlock->Changed.vertexShaderConstant) {
1695             TRACE_(d3d_shader)("vertex shader initializing constants\n");
1696             IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1697         }
1698 #endif /* TODO: vertex and pixel shaders */
1699     }
1700
1701     /* Ok, we will be updating the screen from here onwards so grab the lock */
1702     ENTER_GL();
1703
1704 #if 0 /* TODO: vertex and pixel shaders */
1705     /* If we will be using a pixel, do some initialization for it */
1706     if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1707         TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1708         memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1709
1710         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1711         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1712         glEnable(GL_FRAGMENT_PROGRAM_ARB);
1713         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1714
1715         /* init Constants */
1716         if (This->stateBlock->Changed.pixelShaderConstant) {
1717             TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1718             IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1719         }
1720         /* Update the constants */
1721         for (i=0; i<D3D8_PSHADER_MAX_CONSTANTS; i++) {
1722             GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1723             checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1724         }
1725     }
1726 #endif /* TODO: vertex and pixel shaders */
1727
1728     /* Initialize all values to null */
1729     if (useVertexShaderFunction == FALSE) {
1730         memset(&dataLocations, 0x00, sizeof(dataLocations));
1731
1732         /* Convert to strided data */
1733          if(This->stateBlock->vertexDecl != NULL){
1734             TRACE("================ Vertex Declaration  ===================\n");
1735             primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1736          }else{
1737             TRACE("================ FVF ===================\n");
1738             primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1739          }
1740
1741         /* write out some debug information*/
1742         drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1743     } else {
1744         FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1745     }
1746
1747     /* Setup transform matrices and sort out */
1748     if (useHW) {
1749         /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1750         So make sure lighting is disabled. */
1751         isLightingOn = glIsEnabled(GL_LIGHTING);
1752         glDisable(GL_LIGHTING);
1753         checkGLcall("glDisable(GL_LIGHTING);");
1754         TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1755     } else {
1756         isLightingOn = primitiveInitState(iface,
1757                                           fvf & D3DFVF_XYZRHW,
1758                                           !(fvf & D3DFVF_NORMAL),
1759                                           useVertexShaderFunction);
1760     }
1761
1762     /* Now initialize the materials state */
1763     init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1764
1765     nonPower2 = drawPrimitiveUploadDirtyTextures(This);
1766
1767     /* Now draw the graphics to the screen */
1768     if  (useVertexShaderFunction) {
1769
1770         /* Ideally, we should have software FV and hardware VS, possibly
1771            depending on the device type?                                 */
1772
1773         if (useHW) {
1774             TRACE("Swap HW vertex shader\n");
1775 #if 0 /* TODO: vertex and pixel shaders */
1776             drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1777                         idxData, idxSize, minIndex, StartIdx);
1778 #endif
1779         } else {
1780             /* We will have to use the very, very slow emulation layer */
1781             TRACE("Swap SW vertex shader\n");
1782 #if 0 /* TODO: vertex and pixel shaders */
1783             drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1784                         idxData, idxSize, minIndex, StartIdx);
1785 #endif
1786         }
1787
1788     } else if ((dataLocations.u.s.pSize.lpData           != NULL)
1789                || (dataLocations.u.s.diffuse.lpData      != NULL)
1790                || nonPower2
1791                /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1792
1793         /* Fixme, Ideally, only use the per-vertex code for software HAL
1794            but until opengl supports all the functions returned to setup
1795            vertex arrays, we need to drop down to the slow mechanism for
1796            certain functions                                              */
1797
1798         /* We will have to use the slow version of GL per vertex setup */
1799         drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1800                         idxData, idxSize, minIndex, StartIdx);
1801
1802     } else {
1803
1804         /* We can use the fast version of GL pointers */
1805         drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1806                         idxData, idxSize, minIndex, StartIdx);
1807     }
1808
1809     /* If vertex shaders or no normals, restore previous lighting state */
1810     if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1811         if (isLightingOn) glEnable(GL_LIGHTING);
1812         else glDisable(GL_LIGHTING);
1813         TRACE("Restored lighting to original state\n");
1814     }
1815
1816 #if 0 /* TODO: vertex and pixel shaders */
1817     if (pixel_shader)
1818     {
1819 #if 0
1820       GLint errPos;
1821       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1822       if (errPos != -1)
1823         FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1824 #endif
1825       glDisable(GL_FRAGMENT_PROGRAM_ARB);
1826     }
1827 #endif
1828
1829     /* Finshed updating the screen, restore lock */
1830     LEAVE_GL();
1831     TRACE("Done all gl drawing\n");
1832
1833     /* Diagnostics */
1834 #if defined(SHOW_FRAME_MAKEUP)
1835     {
1836         if (isDumpingFrames) {
1837             D3DLOCKED_RECT r;
1838             char buffer[80];
1839             IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1840             sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1841             TRACE("Saving screenshot %s\n", buffer);
1842             IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1843             IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1844
1845 #if defined(SHOW_TEXTURE_MAKEUP)
1846            {
1847             LPDIRECT3DSURFACE8 pSur;
1848             int textureNo;
1849             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1850                 if (This->stateBlock->textures[textureNo] != NULL) {
1851                     sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1852                     TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->stateBlock->textures[textureNo])->format));
1853                     IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->stateBlock->textures[textureNo], 0, &pSur);
1854                     IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1855                     IDirect3DSurface8Impl_Release(pSur);
1856                 }
1857             }
1858            }
1859 #endif
1860            primCounter = primCounter + 1;
1861         }
1862     }
1863 #endif
1864 }