wined3d: Do not reset the material.
[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  * Copyright 2006 Henri Verbeet
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #include "config.h"
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
30
31 #include <stdio.h>
32
33 #if 0 /* TODO */
34 extern IWineD3DVertexShaderImpl*            VertexShaders[64];
35 extern IWineD3DVertexDeclarationImpl*       VertexShaderDeclarations[64];
36 extern IWineD3DPixelShaderImpl*             PixelShaders[64];
37
38 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
39 #endif
40
41 /* Issues the glBegin call for gl given the primitive type and count */
42 static DWORD primitiveToGl(WINED3DPRIMITIVETYPE PrimitiveType,
43                     DWORD            NumPrimitives,
44                     GLenum          *primType)
45 {
46     DWORD   NumVertexes = NumPrimitives;
47
48     switch (PrimitiveType) {
49     case WINED3DPT_POINTLIST:
50         TRACE("POINTS\n");
51         *primType   = GL_POINTS;
52         NumVertexes = NumPrimitives;
53         break;
54
55     case WINED3DPT_LINELIST:
56         TRACE("LINES\n");
57         *primType   = GL_LINES;
58         NumVertexes = NumPrimitives * 2;
59         break;
60
61     case WINED3DPT_LINESTRIP:
62         TRACE("LINE_STRIP\n");
63         *primType   = GL_LINE_STRIP;
64         NumVertexes = NumPrimitives + 1;
65         break;
66
67     case WINED3DPT_TRIANGLELIST:
68         TRACE("TRIANGLES\n");
69         *primType   = GL_TRIANGLES;
70         NumVertexes = NumPrimitives * 3;
71         break;
72
73     case WINED3DPT_TRIANGLESTRIP:
74         TRACE("TRIANGLE_STRIP\n");
75         *primType   = GL_TRIANGLE_STRIP;
76         NumVertexes = NumPrimitives + 2;
77         break;
78
79     case WINED3DPT_TRIANGLEFAN:
80         TRACE("TRIANGLE_FAN\n");
81         *primType   = GL_TRIANGLE_FAN;
82         NumVertexes = NumPrimitives + 2;
83         break;
84
85     default:
86         FIXME("Unhandled primitive\n");
87         *primType    = GL_POINTS;
88         break;
89     }
90     return NumVertexes;
91 }
92
93 /* Ensure the appropriate material states are set up - only change
94    state if really required                                        */
95 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
96     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
97
98     if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
99         /* If we have not set up the material color tracking, do it now as required */
100         glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
101         checkGLcall("glDisable GL_COLOR_MATERIAL");
102         TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
103         glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
104         checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
105         glEnable(GL_COLOR_MATERIAL);
106         checkGLcall("glEnable GL_COLOR_MATERIAL");
107         This->tracking_color = IS_TRACKING;
108     } else if ((This->tracking_color == IS_TRACKING && !isDiffuseSupplied) ||
109                (This->tracking_color == NEEDS_TRACKING && !isDiffuseSupplied)) {
110         /* If we are tracking the current color but one isn't supplied, don't! */
111         glDisable(GL_COLOR_MATERIAL);
112         checkGLcall("glDisable GL_COLOR_MATERIAL");
113         This->tracking_color = NEEDS_TRACKING;
114     } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
115         /* No need to reset material colors since no change to gl_color_material */
116     } else if (This->tracking_color == NEEDS_DISABLE) {
117         glDisable(GL_COLOR_MATERIAL);
118         checkGLcall("glDisable GL_COLOR_MATERIAL");
119         This->tracking_color = DISABLED_TRACKING;
120     }
121 }
122
123 static const GLfloat invymat[16] = {
124         1.0f, 0.0f, 0.0f, 0.0f,
125         0.0f, -1.0f, 0.0f, 0.0f,
126         0.0f, 0.0f, 1.0f, 0.0f,
127         0.0f, 0.0f, 0.0f, 1.0f};
128
129 static BOOL fixed_get_input(
130     BYTE usage, BYTE usage_idx,
131     unsigned int* regnum) {
132
133     *regnum = -1;
134
135     /* Those positions must have the order in the
136      * named part of the strided data */
137
138     if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
139         *regnum = 0;
140     else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
141         *regnum = 1;
142     else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
143         *regnum = 2;
144     else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
145         *regnum = 3;
146     else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
147         *regnum = 4;
148     else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
149         *regnum = 5;
150     else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
151         *regnum = 6;
152     else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
153         *regnum = 7 + usage_idx;
154     else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
155         *regnum = 7 + WINED3DDP_MAXTEXCOORD;
156     else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
157         *regnum = 8 + WINED3DDP_MAXTEXCOORD;
158     else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
159         *regnum = 9 + WINED3DDP_MAXTEXCOORD;
160     else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
161         *regnum = 10 + WINED3DDP_MAXTEXCOORD;
162     else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
163         *regnum = 11 + WINED3DDP_MAXTEXCOORD;
164     else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
165         *regnum = 12 + WINED3DDP_MAXTEXCOORD;
166     else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
167         *regnum = 13 + WINED3DDP_MAXTEXCOORD;
168     else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
169         *regnum = 14 + WINED3DDP_MAXTEXCOORD;
170
171     if (*regnum < 0) {
172         FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
173             debug_d3ddeclusage(usage), usage_idx);
174         return FALSE;
175     }
176     return TRUE;
177 }
178
179 void primitiveDeclarationConvertToStridedData(
180      IWineD3DDevice *iface,
181      BOOL useVertexShaderFunction,
182      WineDirect3DVertexStridedData *strided,
183      BOOL *fixup) {
184
185      /* We need to deal with frequency data!*/
186
187     BYTE  *data    = NULL;
188     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
189     IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
190     int i;
191     WINED3DVERTEXELEMENT *element;
192     DWORD stride;
193     int reg;
194     char isPreLoaded[MAX_STREAMS];
195     DWORD preLoadStreams[MAX_STREAMS], numPreloadStreams = 0;
196
197     memset(isPreLoaded, 0, sizeof(isPreLoaded));
198
199     /* Locate the vertex declaration */
200     if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
201         TRACE("Using vertex declaration from shader\n");
202         vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
203     } else {
204         TRACE("Using vertex declaration\n");
205         vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
206     }
207
208     /* Translate the declaration into strided data */
209     for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
210         GLint streamVBO = 0;
211         BOOL stride_used;
212         unsigned int idx;
213
214         element = vertexDeclaration->pDeclarationWine + i;
215         TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
216             element,  i + 1, vertexDeclaration->declarationWNumElements - 1);
217
218         if (This->stateBlock->streamSource[element->Stream] == NULL)
219             continue;
220
221         if (This->stateBlock->streamIsUP) {
222             TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
223             streamVBO = 0;
224             data    = (BYTE *)This->stateBlock->streamSource[element->Stream];
225             if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
226         } else {
227             TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
228             if(!isPreLoaded[element->Stream]) {
229                 preLoadStreams[numPreloadStreams] = element->Stream;
230                 numPreloadStreams++;
231                 isPreLoaded[element->Stream] = 1;
232             }
233             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
234             if(fixup) {
235                 if( streamVBO != 0) *fixup = TRUE;
236                 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
237             }
238         }
239         stride  = This->stateBlock->streamStride[element->Stream];
240         data += element->Offset;
241         reg = element->Reg;
242
243         TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
244
245         if (useVertexShaderFunction)
246             stride_used = vshader_get_input(This->stateBlock->vertexShader,
247                 element->Usage, element->UsageIndex, &idx);
248         else
249             stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
250
251         if (stride_used) {
252            TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
253                  "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
254                  useVertexShaderFunction? "shader": "fixed function", idx,
255                  debug_d3ddeclusage(element->Usage), element->UsageIndex,
256                  element->Stream, element->Offset, stride, streamVBO);
257
258            strided->u.input[idx].lpData = data;
259            strided->u.input[idx].dwType = element->Type;
260            strided->u.input[idx].dwStride = stride;
261            strided->u.input[idx].VBO = streamVBO;
262            if (!useVertexShaderFunction) {
263                if (element->Usage == D3DDECLUSAGE_POSITION)
264                    strided->u.s.position_transformed = FALSE;
265                else if (element->Usage == D3DDECLUSAGE_POSITIONT)
266                    strided->u.s.position_transformed = TRUE;
267            }
268         }
269     };
270     /* Now call PreLoad on all the vertex buffers. In the very rare case
271      * that the buffers stopps converting PreLoad will dirtify the VDECL again.
272      * The vertex buffer can now use the strided structure in the device instead of finding its
273      * own again.
274      *
275      * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
276      * once in there.
277      */
278     for(i=0; i < numPreloadStreams; i++) {
279             IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[preLoadStreams[i]]);
280     }
281 }
282
283 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
284     int           numBlends;
285     int           numTextures;
286     int           textureNo;
287     int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
288     int           numCoords[8];           /* Holding place for WINED3DFVF_TEXTUREFORMATx  */
289
290     /* Either 3 or 4 floats depending on the FVF */
291     /* FIXME: Can blending data be in a different stream to the position data?
292           and if so using the fixed pipeline how do we handle it               */
293     if (thisFVF & WINED3DFVF_POSITION_MASK) {
294         strided->u.s.position.lpData    = data;
295         strided->u.s.position.dwType    = WINED3DDECLTYPE_FLOAT3;
296         strided->u.s.position.dwStride  = stride;
297         strided->u.s.position.VBO       = streamVBO;
298         data += 3 * sizeof(float);
299         if (thisFVF & WINED3DFVF_XYZRHW) {
300             strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
301             strided->u.s.position_transformed = TRUE;
302             data += sizeof(float);
303         } else
304             strided->u.s.position_transformed = FALSE;
305     }
306
307     /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
308     /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
309     numBlends = 1 + (((thisFVF & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
310     if(thisFVF & WINED3DFVF_LASTBETA_UBYTE4) numBlends--;
311
312     if ((thisFVF & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW) {
313         TRACE("Setting blend Weights to %p\n", data);
314         strided->u.s.blendWeights.lpData    = data;
315         strided->u.s.blendWeights.dwType    = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
316         strided->u.s.blendWeights.dwStride  = stride;
317         strided->u.s.blendWeights.VBO       = streamVBO;
318         data += numBlends * sizeof(FLOAT);
319
320         if (thisFVF & WINED3DFVF_LASTBETA_UBYTE4) {
321             strided->u.s.blendMatrixIndices.lpData = data;
322             strided->u.s.blendMatrixIndices.dwType  = WINED3DDECLTYPE_UBYTE4;
323             strided->u.s.blendMatrixIndices.dwStride= stride;
324             strided->u.s.blendMatrixIndices.VBO     = streamVBO;
325             data += sizeof(DWORD);
326         }
327     }
328
329     /* Normal is always 3 floats */
330     if (thisFVF & WINED3DFVF_NORMAL) {
331         strided->u.s.normal.lpData    = data;
332         strided->u.s.normal.dwType    = WINED3DDECLTYPE_FLOAT3;
333         strided->u.s.normal.dwStride  = stride;
334         strided->u.s.normal.VBO     = streamVBO;
335         data += 3 * sizeof(FLOAT);
336     }
337
338     /* Pointsize is a single float */
339     if (thisFVF & WINED3DFVF_PSIZE) {
340         strided->u.s.pSize.lpData    = data;
341         strided->u.s.pSize.dwType    = WINED3DDECLTYPE_FLOAT1;
342         strided->u.s.pSize.dwStride  = stride;
343         strided->u.s.pSize.VBO       = streamVBO;
344         data += sizeof(FLOAT);
345     }
346
347     /* Diffuse is 4 unsigned bytes */
348     if (thisFVF & WINED3DFVF_DIFFUSE) {
349         strided->u.s.diffuse.lpData    = data;
350         strided->u.s.diffuse.dwType    = WINED3DDECLTYPE_SHORT4;
351         strided->u.s.diffuse.dwStride  = stride;
352         strided->u.s.diffuse.VBO       = streamVBO;
353         data += sizeof(DWORD);
354     }
355
356     /* Specular is 4 unsigned bytes */
357     if (thisFVF & WINED3DFVF_SPECULAR) {
358         strided->u.s.specular.lpData    = data;
359         strided->u.s.specular.dwType    = WINED3DDECLTYPE_SHORT4;
360         strided->u.s.specular.dwStride  = stride;
361         strided->u.s.specular.VBO       = streamVBO;
362         data += sizeof(DWORD);
363     }
364
365     /* Texture coords */
366     numTextures   = (thisFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
367     coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of WINED3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
368
369     /* numTextures indicates the number of texture coordinates supplied */
370     /* However, the first set may not be for stage 0 texture - it all   */
371     /*   depends on WINED3DTSS_TEXCOORDINDEX.                           */
372     /* The number of bytes for each coordinate set is based off         */
373     /*   WINED3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
374
375     /* So, for each supplied texture extract the coords */
376     for (textureNo = 0; textureNo < numTextures; ++textureNo) {
377
378         strided->u.s.texCoords[textureNo].lpData    = data;
379         strided->u.s.texCoords[textureNo].dwType    = WINED3DDECLTYPE_FLOAT1;
380         strided->u.s.texCoords[textureNo].dwStride  = stride;
381         strided->u.s.texCoords[textureNo].VBO       = streamVBO;
382         numCoords[textureNo] = coordIdxInfo & 0x03;
383
384         /* Always one set */
385         data += sizeof(float);
386         if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT1) {
387             strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT2;
388             data += sizeof(float);
389             if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT2) {
390                 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT3;
391                 data += sizeof(float);
392                 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT3) {
393                     strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT4;
394                     data += sizeof(float);
395                 }
396             }
397         }
398         coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
399     }
400 }
401
402 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, BOOL *fixup) {
403
404     short         LoopThroughTo = 0;
405     short         nStream;
406     GLint         streamVBO = 0;
407     DWORD preLoadStreams[MAX_STREAMS], numPreloadStreams = 0;
408
409     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
410
411     /* OK, Now to setup the data locations
412        For the non-created vertex shaders, the VertexShader var holds the real
413           FVF and only stream 0 matters
414        For the created vertex shaders, there is an FVF per stream              */
415     if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
416         LoopThroughTo = MAX_STREAMS;
417     } else {
418         LoopThroughTo = 1;
419     }
420
421     /* Work through stream by stream */
422     for (nStream=0; nStream<LoopThroughTo; ++nStream) {
423         DWORD  stride  = This->stateBlock->streamStride[nStream];
424         BYTE  *data    = NULL;
425         DWORD  thisFVF = 0;
426
427         /* Skip empty streams */
428         if (This->stateBlock->streamSource[nStream] == NULL) continue;
429
430         /* Retrieve appropriate FVF */
431         if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
432             thisFVF = This->stateBlock->fvf;
433             /* Handle memory passed directly as well as vertex buffers */
434             if (This->stateBlock->streamIsUP) {
435                 streamVBO = 0;
436                 data    = (BYTE *)This->stateBlock->streamSource[nStream];
437             } else {
438                 /* The for loop should iterate through here only once per stream, so we don't need magic to prevent double loading
439                  * buffers
440                  */
441                 preLoadStreams[numPreloadStreams] = nStream;
442                 numPreloadStreams++;
443                 /* GetMemory binds the VBO */
444                 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
445                 if(fixup) {
446                     if(streamVBO != 0 ) *fixup = TRUE;
447                 }
448             }
449         } else {
450 #if 0 /* TODO: Vertex shader support */
451             thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
452             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
453 #endif
454         }
455         VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
456         if (thisFVF == 0) continue;
457
458         /* Now convert the stream into pointers */
459         primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
460     }
461     /* Now call PreLoad on all the vertex buffers. In the very rare case
462      * that the buffers stopps converting PreLoad will dirtify the VDECL again.
463      * The vertex buffer can now use the strided structure in the device instead of finding its
464      * own again.
465      *
466      * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
467      * once in there.
468      */
469     for(nStream=0; nStream < numPreloadStreams; nStream++) {
470             IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[preLoadStreams[nStream]]);
471     }
472 }
473
474 #if 0 /* TODO: Software Shaders */
475 /* Draw a single vertex using this information */
476 static void draw_vertex(IWineD3DDevice *iface,                         /* interface    */
477                  BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
478                  BOOL isNormal, float nx, float ny, float nz,          /* normal       */
479                  BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
480                  BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
481                  BOOL isPtSize, float ptSize,                       /* pointSize    */
482                  WINED3DVECTOR_4 *texcoords, int *numcoords)        /* texture info */
483 {
484     unsigned int textureNo;
485     float s, t, r, q;
486     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
487
488     /* Diffuse -------------------------------- */
489     if (isDiffuse) {
490         glColor4fv(dRGBA);
491         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
492     }
493
494     /* Specular Colour ------------------------------------------*/
495     if (isSpecular) {
496         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
497           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
498           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
499         } else {
500           VTRACE(("Specular color extensions not supplied\n"));
501         }
502     }
503
504     /* Normal -------------------------------- */
505     if (isNormal) {
506         VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
507         glNormal3f(nx, ny, nz);
508     }
509
510     /* Point Size ----------------------------------------------*/
511     if (isPtSize) {
512
513         /* no such functionality in the fixed function GL pipeline */
514         FIXME("Cannot change ptSize here in openGl\n");
515     }
516
517     /* Texture coords --------------------------- */
518     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
519
520         if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
521             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
522             continue ;
523         }
524
525         /* Query tex coords */
526         if (This->stateBlock->textures[textureNo] != NULL) {
527
528             int    coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
529             if (coordIdx >= MAX_TEXTURES) {
530                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
531                 continue;
532             } else if (numcoords[coordIdx] == 0) {
533                 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
534                 continue;
535             } else {
536
537                 /* Initialize vars */
538                 s = 0.0f;
539                 t = 0.0f;
540                 r = 0.0f;
541                 q = 0.0f;
542
543                 switch (numcoords[coordIdx]) {
544                 case 4: q = texcoords[coordIdx].w; /* drop through */
545                 case 3: r = texcoords[coordIdx].z; /* drop through */
546                 case 2: t = texcoords[coordIdx].y; /* drop through */
547                 case 1: s = texcoords[coordIdx].x;
548                 }
549
550                 switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
551                 case WINED3DTTFF_COUNT1:
552                     VTRACE(("tex:%d, s=%f\n", textureNo, s));
553                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
554                         GLMULTITEXCOORD1F(textureNo, s);
555                     } else {
556                         glTexCoord1f(s);
557                     }
558                     break;
559                 case WINED3DTTFF_COUNT2:
560                     VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
561                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
562                         GLMULTITEXCOORD2F(textureNo, s, t);
563                     } else {
564                         glTexCoord2f(s, t);
565                     }
566                     break;
567                 case WINED3DTTFF_COUNT3:
568                     VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
569                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
570                         GLMULTITEXCOORD3F(textureNo, s, t, r);
571                     } else {
572                         glTexCoord3f(s, t, r);
573                     }
574                     break;
575                 case WINED3DTTFF_COUNT4:
576                     VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
577                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
578                         GLMULTITEXCOORD4F(textureNo, s, t, r, q);
579                     } else {
580                         glTexCoord4f(s, t, r, q);
581                     }
582                     break;
583                 default:
584                     FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
585                 }
586             }
587         }
588     } /* End of textures */
589
590     /* Position -------------------------------- */
591     if (isXYZ) {
592         if (1.0f == rhw || rhw < 0.00001f) {
593             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
594             glVertex3f(x, y, z);
595         } else {
596             /* Cannot optimize by dividing through by rhw as rhw is required
597                later for perspective in the GL pipeline for vertex shaders   */
598             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
599             glVertex4f(x,y,z,rhw);
600         }
601     }
602 }
603 #endif /* TODO: Software shaders */
604
605 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
606                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
607     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
608
609     if (idxData != NULL /* This crashes sometimes!*/) {
610         TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
611         idxData = idxData == (void *)-1 ? NULL : idxData;
612 #if 1
613 #if 0
614         glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
615         glEnableClientState(GL_INDEX_ARRAY);
616 #endif
617         glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
618                      (const char *)idxData+(idxSize * startIdx));
619 #else /* using drawRangeElements may be faster */
620
621         glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
622                       idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
623                       (const char *)idxData+(idxSize * startIdx));
624 #endif
625         checkGLcall("glDrawRangeElements");
626
627     } else {
628
629         /* Note first is now zero as we shuffled along earlier */
630         TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
631         glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
632         checkGLcall("glDrawArrays");
633
634     }
635
636     return;
637 }
638
639 /*
640  * Actually draw using the supplied information.
641  * Slower GL version which extracts info about each vertex in turn
642  */
643
644 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
645                      UINT NumVertexes, GLenum glPrimType,
646                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
647
648     unsigned int               textureNo    = 0;
649     unsigned int               texture_idx  = 0;
650     const short               *pIdxBufS     = NULL;
651     const long                *pIdxBufL     = NULL;
652     LONG                       vx_index;
653     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
654     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
655     float rhw = 0.0f;                      /* rhw                        */
656     float ptSize = 0.0f;                   /* Point size                 */
657     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
658     DWORD specularColor = 0;               /* Specular Color             */
659     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
660     LONG                       SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
661
662     TRACE("Using slow vertex array code\n");
663
664     /* Variable Initialization */
665     if (idxData != NULL) {
666         if (idxSize == 2) pIdxBufS = (const short *) idxData;
667         else pIdxBufL = (const long *) idxData;
668     }
669
670     /* Start drawing in GL */
671     VTRACE(("glBegin(%x)\n", glPrimType));
672     glBegin(glPrimType);
673
674     /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
675      * Guess it's not necessary(we crash then anyway) and would only eat CPU time
676      */
677
678     /* For each primitive */
679     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
680
681         /* Initialize diffuse color */
682         diffuseColor = 0xFFFFFFFF;
683
684         /* For indexed data, we need to go a few more strides in */
685         if (idxData != NULL) {
686
687             /* Indexed so work out the number of strides to skip */
688             if (idxSize == 2) {
689                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
690                 SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex;
691             } else {
692                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
693                 SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->loadBaseVertexIndex;
694             }
695         }
696
697         /* Position Information ------------------ */
698         if (sd->u.s.position.lpData != NULL) {
699
700             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
701             x = ptrToCoords[0];
702             y = ptrToCoords[1];
703             z = ptrToCoords[2];
704             rhw = 1.0;
705             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
706
707             /* RHW follows, only if transformed, ie 4 floats were provided */
708             if (sd->u.s.position_transformed) {
709                 rhw = ptrToCoords[3];
710                 VTRACE(("rhw=%f\n", rhw));
711             }
712         }
713
714         /* Blending data -------------------------- */
715         if (sd->u.s.blendWeights.lpData != NULL) {
716             /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
717             FIXME("Blending not supported yet\n");
718
719             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
720                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
721             }
722         }
723
724         /* Vertex Normal Data (untransformed only)- */
725         if (sd->u.s.normal.lpData != NULL) {
726
727             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
728             nx = ptrToCoords[0];
729             ny = ptrToCoords[1];
730             nz = ptrToCoords[2];
731             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
732         }
733
734         /* Point Size ----------------------------- */
735         if (sd->u.s.pSize.lpData != NULL) {
736
737             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
738             ptSize = ptrToCoords[0];
739             VTRACE(("ptSize=%f\n", ptSize));
740             FIXME("No support for ptSize yet\n");
741         }
742
743         /* Diffuse -------------------------------- */
744         if (sd->u.s.diffuse.lpData != NULL) {
745
746             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
747             diffuseColor = ptrToCoords[0];
748             VTRACE(("diffuseColor=%lx\n", diffuseColor));
749         }
750
751         /* Specular  -------------------------------- */
752         if (sd->u.s.specular.lpData != NULL) {
753
754             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
755             specularColor = ptrToCoords[0];
756             VTRACE(("specularColor=%lx\n", specularColor));
757         }
758
759         /* Texture coords --------------------------- */
760         for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
761
762             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
763                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
764                 continue ;
765             }
766
767             /* Query tex coords */
768             if (This->stateBlock->textures[textureNo] != NULL) {
769
770                 int    coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
771                 float *ptrToCoords = NULL;
772                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
773
774                 if (coordIdx > 7) {
775                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
776                     ++texture_idx;
777                     continue;
778                 } else if (coordIdx < 0) {
779                     FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
780                     ++texture_idx;
781                     continue;
782                 }
783
784                 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
785                 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
786                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
787                     ++texture_idx;
788                     continue;
789                 } else {
790
791                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
792
793                     /* The coords to supply depend completely on the fvf / vertex shader */
794                     switch (coordsToUse) {
795                     case 4: q = ptrToCoords[3]; /* drop through */
796                     case 3: r = ptrToCoords[2]; /* drop through */
797                     case 2: t = ptrToCoords[1]; /* drop through */
798                     case 1: s = ptrToCoords[0];
799                     }
800
801                     /* Projected is more 'fun' - Move the last coord to the 'q'
802                           parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
803                     if ((This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) &&
804                         (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)) {
805
806                         if (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) {
807                             switch (coordsToUse) {
808                             case 0:  /* Drop Through */
809                             case 1:
810                                 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
811                                 break;
812                             case 2:
813                                 q = t;
814                                 t = 0.0;
815                                 coordsToUse = 4;
816                                 break;
817                             case 3:
818                                 q = r;
819                                 r = 0.0;
820                                 coordsToUse = 4;
821                                 break;
822                             case 4:  /* Nop here */
823                                 break;
824                             default:
825                                 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
826                                       This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED);
827                             }
828                         }
829                     }
830
831                     switch (coordsToUse) {   /* Supply the provided texture coords */
832                     case WINED3DTTFF_COUNT1:
833                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
834                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
835                             GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
836                         } else {
837                             glTexCoord1f(s);
838                         }
839                         break;
840                     case WINED3DTTFF_COUNT2:
841                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
842                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
843                             GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
844                         } else {
845                             glTexCoord2f(s, t);
846                         }
847                         break;
848                     case WINED3DTTFF_COUNT3:
849                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
850                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
851                             GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
852                         } else {
853                             glTexCoord3f(s, t, r);
854                         }
855                         break;
856                     case WINED3DTTFF_COUNT4:
857                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
858                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
859                             GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
860                         } else {
861                             glTexCoord4f(s, t, r, q);
862                         }
863                         break;
864                     default:
865                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
866                     }
867                 }
868             }
869             if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/TRUE) ++texture_idx;
870         } /* End of textures */
871
872         /* Diffuse -------------------------------- */
873         if (sd->u.s.diffuse.lpData != NULL) {
874           glColor4ub(D3DCOLOR_B_R(diffuseColor),
875                      D3DCOLOR_B_G(diffuseColor),
876                      D3DCOLOR_B_B(diffuseColor),
877                      D3DCOLOR_B_A(diffuseColor));
878             VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n", 
879                     D3DCOLOR_B_R(diffuseColor),
880                     D3DCOLOR_B_G(diffuseColor),
881                     D3DCOLOR_B_B(diffuseColor),
882                     D3DCOLOR_B_A(diffuseColor)));
883         } else {
884             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
885         }
886
887         /* Specular ------------------------------- */
888         if (sd->u.s.specular.lpData != NULL) {
889             /* special case where the fog density is stored in the diffuse alpha channel */
890             if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
891               (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
892               This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
893                 if(GL_SUPPORT(EXT_FOG_COORD)) {
894                     GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
895                 } else {
896                     static BOOL warned = FALSE;
897                     if(!warned) {
898                         /* TODO: Use the fog table code from old ddraw */
899                         FIXME("Implement fog for transformed vertices in software\n");
900                         warned = TRUE;
901                     }
902                 }
903             }
904
905             VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n", 
906                     D3DCOLOR_B_R(specularColor), 
907                     D3DCOLOR_B_G(specularColor), 
908                     D3DCOLOR_B_B(specularColor)));
909             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
910                 GL_EXTCALL(glSecondaryColor3ubEXT)(
911                            D3DCOLOR_B_R(specularColor),
912                            D3DCOLOR_B_G(specularColor),
913                            D3DCOLOR_B_B(specularColor));
914             } else {
915                 /* Do not worry if specular colour missing and disable request */
916                 VTRACE(("Specular color extensions not supplied\n"));
917             }
918         } else {
919             if (vx_index == 0) {
920                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
921                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
922                 } else {
923                     /* Do not worry if specular colour missing and disable request */
924                     VTRACE(("Specular color extensions not supplied\n"));
925                 }
926             }
927         }
928
929         /* Normal -------------------------------- */
930         if (sd->u.s.normal.lpData != NULL) {
931             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
932             glNormal3f(nx, ny, nz);
933         } else {
934             if (vx_index == 0) glNormal3f(0, 0, 1);
935         }
936
937         /* Position -------------------------------- */
938         if (sd->u.s.position.lpData != NULL) {
939             if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
940                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
941                 glVertex3f(x, y, z);
942             } else {
943                 GLfloat w = 1.0 / rhw;
944                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
945                 glVertex4f(x*w, y*w, z*w, w);
946             }
947         }
948
949         /* For non indexed mode, step onto next parts */
950         if (idxData == NULL) {
951             ++SkipnStrides;
952         }
953     }
954
955     glEnd();
956     checkGLcall("glEnd and previous calls");
957 }
958
959 #if 0 /* TODO: Software/Hardware vertex blending support */
960 /*
961  * Draw with emulated vertex shaders
962  * Note: strided data is uninitialized, as we need to pass the vertex
963  *     shader directly as ordering irs yet
964  */
965 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
966                      int PrimitiveType, ULONG NumPrimitives,
967                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
968
969     unsigned int               textureNo    = 0;
970     GLenum                     glPrimType   = GL_POINTS;
971     int                        NumVertexes  = NumPrimitives;
972     const short               *pIdxBufS     = NULL;
973     const long                *pIdxBufL     = NULL;
974     LONG                       SkipnStrides = 0;
975     LONG                       vx_index;
976     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
977     float rhw = 0.0f;                      /* rhw                        */
978     float ptSize = 0.0f;                   /* Point size                 */
979     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
980     int   numcoords[8];                    /* Number of coords           */
981     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982
983     IDirect3DVertexShaderImpl* vertexShader = NULL;
984
985     TRACE("Using slow software vertex shader code\n");
986
987     /* Variable Initialization */
988     if (idxData != NULL) {
989         if (idxSize == 2) pIdxBufS = (const short *) idxData;
990         else pIdxBufL = (const long *) idxData;
991     }
992
993     /* Ok, Work out which primitive is requested and how many vertexes that will be */
994     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
995
996     /* Retrieve the VS information */
997     vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
998
999     /* Start drawing in GL */
1000     VTRACE(("glBegin(%x)\n", glPrimType));
1001     glBegin(glPrimType);
1002
1003     /* For each primitive */
1004     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1005
1006         /* For indexed data, we need to go a few more strides in */
1007         if (idxData != NULL) {
1008
1009             /* Indexed so work out the number of strides to skip */
1010             if (idxSize == 2) {
1011                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1012                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1013             } else {
1014                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1015                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1016             }
1017         }
1018
1019         /* Fill the vertex shader input */
1020         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1021
1022         /* Initialize the output fields to the same defaults as it would normally have */
1023         memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1024         vertexShader->output.oD[0].x = 1.0;
1025         vertexShader->output.oD[0].y = 1.0;
1026         vertexShader->output.oD[0].z = 1.0;
1027         vertexShader->output.oD[0].w = 1.0;
1028
1029         /* Now execute the vertex shader */
1030         IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1031
1032         /*
1033         TRACE_VECTOR(vertexShader->output.oPos);
1034         TRACE_VECTOR(vertexShader->output.oD[0]);
1035         TRACE_VECTOR(vertexShader->output.oD[1]);
1036         TRACE_VECTOR(vertexShader->output.oT[0]);
1037         TRACE_VECTOR(vertexShader->output.oT[1]);
1038         TRACE_VECTOR(vertexShader->input.V[0]);
1039         TRACE_VECTOR(vertexShader->data->C[0]);
1040         TRACE_VECTOR(vertexShader->data->C[1]);
1041         TRACE_VECTOR(vertexShader->data->C[2]);
1042         TRACE_VECTOR(vertexShader->data->C[3]);
1043         TRACE_VECTOR(vertexShader->data->C[4]);
1044         TRACE_VECTOR(vertexShader->data->C[5]);
1045         TRACE_VECTOR(vertexShader->data->C[6]);
1046         TRACE_VECTOR(vertexShader->data->C[7]);
1047         */
1048
1049         /* Extract out the output */
1050         /* FIXME: Fog coords? */
1051         x = vertexShader->output.oPos.x;
1052         y = vertexShader->output.oPos.y;
1053         z = vertexShader->output.oPos.z;
1054         rhw = vertexShader->output.oPos.w;
1055         ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1056
1057         /** Update textures coords using vertexShader->output.oT[0->7] */
1058         memset(texcoords, 0x00, sizeof(texcoords));
1059         memset(numcoords, 0x00, sizeof(numcoords));
1060         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1061             if (This->stateBlock->textures[textureNo] != NULL) {
1062                texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1063                texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1064                texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1065                texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1066                if (This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) {
1067                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & ~WINED3DTTFF_PROJECTED;
1068                } else {
1069                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1070                    case WINED3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1071                    case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1072                    default:                         numcoords[textureNo] = 4;
1073                    }
1074                }
1075             } else {
1076                 numcoords[textureNo] = 0;
1077             }
1078         }
1079
1080         /* Draw using this information */
1081         draw_vertex(iface,
1082                     TRUE, x, y, z, rhw,
1083                     TRUE, 0.0f, 0.0f, 1.0f,
1084                     TRUE, (float*) &vertexShader->output.oD[0],
1085                     TRUE, (float*) &vertexShader->output.oD[1],
1086                     FALSE, ptSize,         /* FIXME: Change back when supported */
1087                     texcoords, numcoords);
1088
1089         /* For non indexed mode, step onto next parts */
1090         if (idxData == NULL) {
1091            ++SkipnStrides;
1092         }
1093
1094     } /* for each vertex */
1095
1096     glEnd();
1097     checkGLcall("glEnd and previous calls");
1098 }
1099
1100 #endif
1101
1102 static void check_fbo_status(IWineD3DDevice *iface) {
1103     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1104
1105     GLenum status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
1106     switch(status) {
1107         case GL_FRAMEBUFFER_COMPLETE_EXT: TRACE("FBO complete.\n"); break;
1108         default: TRACE("FBO status %#x.\n", status); break;
1109     }
1110 }
1111
1112 static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
1113     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1114     GLint old_binding = 0;
1115
1116     glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
1117
1118     glDisable(GL_CULL_FACE);
1119     glDisable(GL_BLEND);
1120     glDisable(GL_ALPHA_TEST);
1121     glDisable(GL_STENCIL_TEST);
1122     glEnable(GL_DEPTH_TEST);
1123     glDepthFunc(GL_ALWAYS);
1124
1125     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1126     glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
1127     glBindTexture(GL_TEXTURE_2D, texture);
1128     glEnable(GL_TEXTURE_2D);
1129
1130     This->shader_backend->shader_select_depth_blt(iface);
1131
1132     glBegin(GL_TRIANGLE_STRIP);
1133     glVertex2f(-1.0f, -1.0f);
1134     glVertex2f(1.0f, -1.0f);
1135     glVertex2f(-1.0f, 1.0f);
1136     glVertex2f(1.0f, 1.0f);
1137     glEnd();
1138
1139     glBindTexture(GL_TEXTURE_2D, old_binding);
1140
1141     glPopAttrib();
1142
1143     /* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders,
1144      * and this seems easier and more efficient than providing the shader backend with a private
1145      * storage to read and restore the old shader settings
1146      */
1147     This->shader_backend->shader_select(iface,
1148         This->stateBlock->pixelShader && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function,
1149         This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function);
1150 }
1151
1152 static void depth_copy(IWineD3DDevice *iface) {
1153     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1154     IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->depthStencilBuffer;
1155
1156     /* Only copy the depth buffer if there is one. */
1157     if (!depth_stencil) return;
1158
1159     /* TODO: Make this work for modes other than FBO */
1160     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
1161
1162     if (This->render_offscreen) {
1163         static GLuint tmp_texture = 0;
1164         GLint old_binding = 0;
1165
1166         TRACE("Copying onscreen depth buffer to offscreen surface\n");
1167
1168         if (!tmp_texture) {
1169             glGenTextures(1, &tmp_texture);
1170         }
1171
1172         /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
1173          * directly on the FBO texture. That's because we need to flip. */
1174         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1175         glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
1176         glBindTexture(GL_TEXTURE_2D, tmp_texture);
1177         glCopyTexImage2D(depth_stencil->glDescription.target,
1178                 depth_stencil->glDescription.level,
1179                 depth_stencil->glDescription.glFormatInternal,
1180                 0,
1181                 0,
1182                 depth_stencil->currentDesc.Width,
1183                 depth_stencil->currentDesc.Height,
1184                 0);
1185         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1186         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1187         glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
1188         glBindTexture(GL_TEXTURE_2D, old_binding);
1189
1190         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
1191         checkGLcall("glBindFramebuffer()");
1192         depth_blt(iface, tmp_texture);
1193         checkGLcall("depth_blt");
1194     } else {
1195         TRACE("Copying offscreen surface to onscreen depth buffer\n");
1196
1197         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1198         checkGLcall("glBindFramebuffer()");
1199         depth_blt(iface, depth_stencil->glDescription.textureName);
1200         checkGLcall("depth_blt");
1201     }
1202 }
1203
1204 /* Routine common to the draw primitive and draw indexed primitive routines */
1205 void drawPrimitive(IWineD3DDevice *iface,
1206                    int PrimitiveType,
1207                    long NumPrimitives,
1208                    /* for Indexed: */
1209                    long  StartVertexIndex,
1210                    UINT  numberOfVertices,
1211                    long  StartIdx,
1212                    short idxSize,
1213                    const void *idxData,
1214                    int   minIndex) {
1215
1216     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1217     IWineD3DSwapChainImpl         *swapchain;
1218     int                           i;
1219     DWORD                         dirtyState, idx;
1220     BYTE                          shift;
1221
1222     /* Signals other modules that a drawing is in progress and the stateblock finalized */
1223     This->isInDraw = TRUE;
1224
1225     /* Invalidate the back buffer memory so LockRect will read it the next time */
1226     for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
1227         IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
1228         if(swapchain) {
1229             if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
1230             IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1231         }
1232     }
1233
1234     /* Ok, we will be updating the screen from here onwards so grab the lock */
1235     ENTER_GL();
1236
1237     /* Apply dirty states */
1238     for(i=0; i < This->numDirtyEntries; i++) {
1239         dirtyState = This->dirtyArray[i];
1240         idx = dirtyState >> 5;
1241         shift = dirtyState & 0x1f;
1242         This->isStateDirty[idx] &= ~(1 << shift);
1243         StateTable[dirtyState].apply(dirtyState, This->stateBlock);
1244     }
1245     This->numDirtyEntries = 0; /* This makes the whole list clean */
1246
1247     if (TRACE_ON(d3d_draw) && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1248         check_fbo_status(iface);
1249     }
1250
1251     if (This->depth_copy_state == WINED3D_DCS_COPY) {
1252         depth_copy(iface);
1253     }
1254     This->depth_copy_state = WINED3D_DCS_INITIAL;
1255
1256     /* Now initialize the materials state */
1257     init_materials(iface, (This->strided_streams.u.s.diffuse.lpData != NULL || This->strided_streams.u.s.diffuse.VBO != 0));
1258
1259     {
1260         GLenum glPrimType;
1261         /* Ok, Work out which primitive is requested and how many vertexes that
1262            will be                                                              */
1263         UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1264         if (numberOfVertices == 0 )
1265             numberOfVertices = calculatedNumberOfindices;
1266
1267         if (This->useDrawStridedSlow)
1268             drawStridedSlow(iface, &This->strided_streams, calculatedNumberOfindices,
1269                             glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
1270         else
1271             drawStridedFast(iface, calculatedNumberOfindices, glPrimType,
1272                             idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
1273     }
1274
1275     /* Finshed updating the screen, restore lock */
1276     LEAVE_GL();
1277     TRACE("Done all gl drawing\n");
1278
1279     /* Diagnostics */
1280 #ifdef SHOW_FRAME_MAKEUP
1281     {
1282         static long int primCounter = 0;
1283         /* NOTE: set primCounter to the value reported by drawprim 
1284            before you want to to write frame makeup to /tmp */
1285         if (primCounter >= 0) {
1286             WINED3DLOCKED_RECT r;
1287             char buffer[80];
1288             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
1289             sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
1290             TRACE("Saving screenshot %s\n", buffer);
1291             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1292             IWineD3DSurface_UnlockRect(This->renderTarget);
1293
1294 #ifdef SHOW_TEXTURE_MAKEUP
1295            {
1296             IWineD3DSurface *pSur;
1297             int textureNo;
1298             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1299                 if (This->stateBlock->textures[textureNo] != NULL) {
1300                     sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
1301                     TRACE("Saving texture %s\n", buffer);
1302                     if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
1303                             IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
1304                             IWineD3DSurface_SaveSnapshot(pSur, buffer);
1305                             IWineD3DSurface_Release(pSur);
1306                     } else  {
1307                         FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
1308                     }
1309                 }
1310             }
1311            }
1312 #endif
1313         }
1314         TRACE("drawprim #%d\n", primCounter);
1315         ++primCounter;
1316     }
1317 #endif
1318
1319     /* Control goes back to the device, stateblock values may change again */
1320     This->isInDraw = FALSE;
1321 }