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