wined3d: Remove d3ddevice_set_ortho.
[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 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
30 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
31
32 #include <stdio.h>
33
34 #if 0 /* TODO */
35 extern IWineD3DVertexShaderImpl*            VertexShaders[64];
36 extern IWineD3DVertexDeclarationImpl*       VertexShaderDeclarations[64];
37 extern IWineD3DPixelShaderImpl*             PixelShaders[64];
38
39 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
40 #endif
41
42 /* Issues the glBegin call for gl given the primitive type and count */
43 static DWORD primitiveToGl(WINED3DPRIMITIVETYPE PrimitiveType,
44                     DWORD            NumPrimitives,
45                     GLenum          *primType)
46 {
47     DWORD   NumVertexes = NumPrimitives;
48
49     switch (PrimitiveType) {
50     case WINED3DPT_POINTLIST:
51         TRACE("POINTS\n");
52         *primType   = GL_POINTS;
53         NumVertexes = NumPrimitives;
54         break;
55
56     case WINED3DPT_LINELIST:
57         TRACE("LINES\n");
58         *primType   = GL_LINES;
59         NumVertexes = NumPrimitives * 2;
60         break;
61
62     case WINED3DPT_LINESTRIP:
63         TRACE("LINE_STRIP\n");
64         *primType   = GL_LINE_STRIP;
65         NumVertexes = NumPrimitives + 1;
66         break;
67
68     case WINED3DPT_TRIANGLELIST:
69         TRACE("TRIANGLES\n");
70         *primType   = GL_TRIANGLES;
71         NumVertexes = NumPrimitives * 3;
72         break;
73
74     case WINED3DPT_TRIANGLESTRIP:
75         TRACE("TRIANGLE_STRIP\n");
76         *primType   = GL_TRIANGLE_STRIP;
77         NumVertexes = NumPrimitives + 2;
78         break;
79
80     case WINED3DPT_TRIANGLEFAN:
81         TRACE("TRIANGLE_FAN\n");
82         *primType   = GL_TRIANGLE_FAN;
83         NumVertexes = NumPrimitives + 2;
84         break;
85
86     default:
87         FIXME("Unhandled primitive\n");
88         *primType    = GL_POINTS;
89         break;
90     }
91     return NumVertexes;
92 }
93
94 /* Ensure the appropriate material states are set up - only change
95    state if really required                                        */
96 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
97
98     BOOL requires_material_reset = FALSE;
99     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
100
101     if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
102         /* If we have not set up the material color tracking, do it now as required */
103         glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
104         checkGLcall("glDisable GL_COLOR_MATERIAL");
105         TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
106         glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
107         checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
108         glEnable(GL_COLOR_MATERIAL);
109         checkGLcall("glEnable GL_COLOR_MATERIAL");
110         This->tracking_color = IS_TRACKING;
111         requires_material_reset = TRUE; /* Restore material settings as will be used */
112
113     } else if ((This->tracking_color == IS_TRACKING && !isDiffuseSupplied) ||
114                (This->tracking_color == NEEDS_TRACKING && !isDiffuseSupplied)) {
115         /* If we are tracking the current color but one isn't supplied, don't! */
116         glDisable(GL_COLOR_MATERIAL);
117         checkGLcall("glDisable GL_COLOR_MATERIAL");
118         This->tracking_color = NEEDS_TRACKING;
119         requires_material_reset = TRUE; /* Restore material settings as will be used */
120
121     } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
122         /* No need to reset material colors since no change to gl_color_material */
123         requires_material_reset = FALSE;
124
125     } else if (This->tracking_color == NEEDS_DISABLE) {
126         glDisable(GL_COLOR_MATERIAL);
127         checkGLcall("glDisable GL_COLOR_MATERIAL");
128         This->tracking_color = DISABLED_TRACKING;
129         requires_material_reset = TRUE; /* Restore material settings as will be used */
130     }
131
132     /* Reset the material colors which may have been tracking the color*/
133     if (requires_material_reset) {
134         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
135         checkGLcall("glMaterialfv");
136         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
137         checkGLcall("glMaterialfv");
138         if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
139            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
140            checkGLcall("glMaterialfv");
141         } else {
142            float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
143            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
144            checkGLcall("glMaterialfv");
145         }
146         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
147         checkGLcall("glMaterialfv");
148     }
149
150 }
151
152 static const GLfloat invymat[16] = {
153         1.0f, 0.0f, 0.0f, 0.0f,
154         0.0f, -1.0f, 0.0f, 0.0f,
155         0.0f, 0.0f, 1.0f, 0.0f,
156         0.0f, 0.0f, 0.0f, 1.0f};
157
158 static BOOL fixed_get_input(
159     BYTE usage, BYTE usage_idx,
160     unsigned int* regnum) {
161
162     *regnum = -1;
163
164     /* Those positions must have the order in the
165      * named part of the strided data */
166
167     if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 0)
168         *regnum = 0;
169     else if (usage == D3DDECLUSAGE_BLENDWEIGHT && usage_idx == 0)
170         *regnum = 1;
171     else if (usage == D3DDECLUSAGE_BLENDINDICES && usage_idx == 0)
172         *regnum = 2;
173     else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 0)
174         *regnum = 3;
175     else if (usage == D3DDECLUSAGE_PSIZE && usage_idx == 0)
176         *regnum = 4;
177     else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 0)
178         *regnum = 5;
179     else if (usage == D3DDECLUSAGE_COLOR && usage_idx == 1)
180         *regnum = 6;
181     else if (usage == D3DDECLUSAGE_TEXCOORD && usage_idx < WINED3DDP_MAXTEXCOORD)
182         *regnum = 7 + usage_idx;
183     else if ((usage == D3DDECLUSAGE_POSITION || usage == D3DDECLUSAGE_POSITIONT) && usage_idx == 1)
184         *regnum = 7 + WINED3DDP_MAXTEXCOORD;
185     else if (usage == D3DDECLUSAGE_NORMAL && usage_idx == 1)
186         *regnum = 8 + WINED3DDP_MAXTEXCOORD;
187     else if (usage == D3DDECLUSAGE_TANGENT && usage_idx == 0)
188         *regnum = 9 + WINED3DDP_MAXTEXCOORD;
189     else if (usage == D3DDECLUSAGE_BINORMAL && usage_idx == 0)
190         *regnum = 10 + WINED3DDP_MAXTEXCOORD;
191     else if (usage == D3DDECLUSAGE_TESSFACTOR && usage_idx == 0)
192         *regnum = 11 + WINED3DDP_MAXTEXCOORD;
193     else if (usage == D3DDECLUSAGE_FOG && usage_idx == 0)
194         *regnum = 12 + WINED3DDP_MAXTEXCOORD;
195     else if (usage == D3DDECLUSAGE_DEPTH && usage_idx == 0)
196         *regnum = 13 + WINED3DDP_MAXTEXCOORD;
197     else if (usage == D3DDECLUSAGE_SAMPLE && usage_idx == 0)
198         *regnum = 14 + WINED3DDP_MAXTEXCOORD;
199
200     if (*regnum < 0) {
201         FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n",
202             debug_d3ddeclusage(usage), usage_idx);
203         return FALSE;
204     }
205     return TRUE;
206 }
207
208 void primitiveDeclarationConvertToStridedData(
209      IWineD3DDevice *iface,
210      BOOL useVertexShaderFunction,
211      WineDirect3DVertexStridedData *strided,
212      BOOL *fixup) {
213
214      /* We need to deal with frequency data!*/
215
216     BYTE  *data    = NULL;
217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
218     IWineD3DVertexDeclarationImpl* vertexDeclaration = NULL;
219     int i;
220     WINED3DVERTEXELEMENT *element;
221     DWORD stride;
222     int reg;
223
224     /* Locate the vertex declaration */
225     if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
226         TRACE("Using vertex declaration from shader\n");
227         vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
228     } else {
229         TRACE("Using vertex declaration\n");
230         vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->stateBlock->vertexDecl;
231     }
232
233     /* Translate the declaration into strided data */
234     for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
235         GLint streamVBO = 0;
236         BOOL stride_used;
237         unsigned int idx;
238
239         element = vertexDeclaration->pDeclarationWine + i;
240         TRACE("%p Element %p (%d of %d)\n", vertexDeclaration->pDeclarationWine,
241             element,  i + 1, vertexDeclaration->declarationWNumElements - 1);
242
243         if (This->stateBlock->streamSource[element->Stream] == NULL)
244             continue;
245
246         if (This->stateBlock->streamIsUP) {
247             TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
248             streamVBO = 0;
249             data    = (BYTE *)This->stateBlock->streamSource[element->Stream];
250             if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
251         } else {
252             TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
253             IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
254             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
255             if(fixup) {
256                 if( streamVBO != 0) *fixup = TRUE;
257                 else if(*fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
258             }
259         }
260         stride  = This->stateBlock->streamStride[element->Stream];
261         data += element->Offset;
262         reg = element->Reg;
263
264         TRACE("Offset %d Stream %d UsageIndex %d\n", element->Offset, element->Stream, element->UsageIndex);
265
266         if (useVertexShaderFunction)
267             stride_used = vshader_get_input(This->stateBlock->vertexShader,
268                 element->Usage, element->UsageIndex, &idx);
269         else
270             stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
271
272         if (stride_used) {
273            TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
274                  "stream=%u, offset=%u, stride=%u, VBO=%u]\n",
275                  useVertexShaderFunction? "shader": "fixed function", idx,
276                  debug_d3ddeclusage(element->Usage), element->UsageIndex,
277                  element->Stream, element->Offset, stride, streamVBO);
278
279            strided->u.input[idx].lpData = data;
280            strided->u.input[idx].dwType = element->Type;
281            strided->u.input[idx].dwStride = stride;
282            strided->u.input[idx].VBO = streamVBO;
283            if (!useVertexShaderFunction) {
284                if (element->Usage == D3DDECLUSAGE_POSITION)
285                    strided->u.s.position_transformed = FALSE;
286                else if (element->Usage == D3DDECLUSAGE_POSITIONT)
287                    strided->u.s.position_transformed = TRUE;
288            }
289         }
290     };
291 }
292
293 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
294     int           numBlends;
295     int           numTextures;
296     int           textureNo;
297     int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
298     int           numCoords[8];           /* Holding place for WINED3DFVF_TEXTUREFORMATx  */
299
300     /* Either 3 or 4 floats depending on the FVF */
301     /* FIXME: Can blending data be in a different stream to the position data?
302           and if so using the fixed pipeline how do we handle it               */
303     if (thisFVF & WINED3DFVF_POSITION_MASK) {
304         strided->u.s.position.lpData    = data;
305         strided->u.s.position.dwType    = WINED3DDECLTYPE_FLOAT3;
306         strided->u.s.position.dwStride  = stride;
307         strided->u.s.position.VBO       = streamVBO;
308         data += 3 * sizeof(float);
309         if (thisFVF & WINED3DFVF_XYZRHW) {
310             strided->u.s.position.dwType = WINED3DDECLTYPE_FLOAT4;
311             strided->u.s.position_transformed = TRUE;
312             data += sizeof(float);
313         } else
314             strided->u.s.position_transformed = FALSE;
315     }
316
317     /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
318     /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
319     numBlends = 1 + (((thisFVF & WINED3DFVF_XYZB5) - WINED3DFVF_XYZB1) >> 1);
320     if(thisFVF & WINED3DFVF_LASTBETA_UBYTE4) numBlends--;
321
322     if ((thisFVF & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW) {
323         TRACE("Setting blend Weights to %p\n", data);
324         strided->u.s.blendWeights.lpData    = data;
325         strided->u.s.blendWeights.dwType    = WINED3DDECLTYPE_FLOAT1 + numBlends - 1;
326         strided->u.s.blendWeights.dwStride  = stride;
327         strided->u.s.blendWeights.VBO       = streamVBO;
328         data += numBlends * sizeof(FLOAT);
329
330         if (thisFVF & WINED3DFVF_LASTBETA_UBYTE4) {
331             strided->u.s.blendMatrixIndices.lpData = data;
332             strided->u.s.blendMatrixIndices.dwType  = WINED3DDECLTYPE_UBYTE4;
333             strided->u.s.blendMatrixIndices.dwStride= stride;
334             strided->u.s.blendMatrixIndices.VBO     = streamVBO;
335             data += sizeof(DWORD);
336         }
337     }
338
339     /* Normal is always 3 floats */
340     if (thisFVF & WINED3DFVF_NORMAL) {
341         strided->u.s.normal.lpData    = data;
342         strided->u.s.normal.dwType    = WINED3DDECLTYPE_FLOAT3;
343         strided->u.s.normal.dwStride  = stride;
344         strided->u.s.normal.VBO     = streamVBO;
345         data += 3 * sizeof(FLOAT);
346     }
347
348     /* Pointsize is a single float */
349     if (thisFVF & WINED3DFVF_PSIZE) {
350         strided->u.s.pSize.lpData    = data;
351         strided->u.s.pSize.dwType    = WINED3DDECLTYPE_FLOAT1;
352         strided->u.s.pSize.dwStride  = stride;
353         strided->u.s.pSize.VBO       = streamVBO;
354         data += sizeof(FLOAT);
355     }
356
357     /* Diffuse is 4 unsigned bytes */
358     if (thisFVF & WINED3DFVF_DIFFUSE) {
359         strided->u.s.diffuse.lpData    = data;
360         strided->u.s.diffuse.dwType    = WINED3DDECLTYPE_SHORT4;
361         strided->u.s.diffuse.dwStride  = stride;
362         strided->u.s.diffuse.VBO       = streamVBO;
363         data += sizeof(DWORD);
364     }
365
366     /* Specular is 4 unsigned bytes */
367     if (thisFVF & WINED3DFVF_SPECULAR) {
368         strided->u.s.specular.lpData    = data;
369         strided->u.s.specular.dwType    = WINED3DDECLTYPE_SHORT4;
370         strided->u.s.specular.dwStride  = stride;
371         strided->u.s.specular.VBO       = streamVBO;
372         data += sizeof(DWORD);
373     }
374
375     /* Texture coords */
376     numTextures   = (thisFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
377     coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of WINED3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
378
379     /* numTextures indicates the number of texture coordinates supplied */
380     /* However, the first set may not be for stage 0 texture - it all   */
381     /*   depends on WINED3DTSS_TEXCOORDINDEX.                           */
382     /* The number of bytes for each coordinate set is based off         */
383     /*   WINED3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
384
385     /* So, for each supplied texture extract the coords */
386     for (textureNo = 0; textureNo < numTextures; ++textureNo) {
387
388         strided->u.s.texCoords[textureNo].lpData    = data;
389         strided->u.s.texCoords[textureNo].dwType    = WINED3DDECLTYPE_FLOAT1;
390         strided->u.s.texCoords[textureNo].dwStride  = stride;
391         strided->u.s.texCoords[textureNo].VBO       = streamVBO;
392         numCoords[textureNo] = coordIdxInfo & 0x03;
393
394         /* Always one set */
395         data += sizeof(float);
396         if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT1) {
397             strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT2;
398             data += sizeof(float);
399             if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT2) {
400                 strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT3;
401                 data += sizeof(float);
402                 if (numCoords[textureNo] != WINED3DFVF_TEXTUREFORMAT3) {
403                     strided->u.s.texCoords[textureNo].dwType = WINED3DDECLTYPE_FLOAT4;
404                     data += sizeof(float);
405                 }
406             }
407         }
408         coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
409     }
410 }
411
412 void primitiveConvertToStridedData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *strided, BOOL *fixup) {
413
414     short         LoopThroughTo = 0;
415     short         nStream;
416     GLint         streamVBO = 0;
417
418     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
419
420     /* OK, Now to setup the data locations
421        For the non-created vertex shaders, the VertexShader var holds the real
422           FVF and only stream 0 matters
423        For the created vertex shaders, there is an FVF per stream              */
424     if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
425         LoopThroughTo = MAX_STREAMS;
426     } else {
427         LoopThroughTo = 1;
428     }
429
430     /* Work through stream by stream */
431     for (nStream=0; nStream<LoopThroughTo; ++nStream) {
432         DWORD  stride  = This->stateBlock->streamStride[nStream];
433         BYTE  *data    = NULL;
434         DWORD  thisFVF = 0;
435
436         /* Skip empty streams */
437         if (This->stateBlock->streamSource[nStream] == NULL) continue;
438
439         /* Retrieve appropriate FVF */
440         if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
441             thisFVF = This->stateBlock->fvf;
442             /* Handle memory passed directly as well as vertex buffers */
443             if (This->stateBlock->streamIsUP) {
444                 streamVBO = 0;
445                 data    = (BYTE *)This->stateBlock->streamSource[nStream];
446             } else {
447                 IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
448                 /* GetMemory binds the VBO */
449                 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
450                 if(fixup) {
451                     if(streamVBO != 0 ) *fixup = TRUE;
452                 }
453             }
454         } else {
455 #if 0 /* TODO: Vertex shader support */
456             thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
457             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
458 #endif
459         }
460         VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
461         if (thisFVF == 0) continue;
462
463         /* Now convert the stream into pointers */
464         primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
465     }
466 }
467
468 #if 0 /* TODO: Software Shaders */
469 /* Draw a single vertex using this information */
470 static void draw_vertex(IWineD3DDevice *iface,                         /* interface    */
471                  BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
472                  BOOL isNormal, float nx, float ny, float nz,          /* normal       */
473                  BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
474                  BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
475                  BOOL isPtSize, float ptSize,                       /* pointSize    */
476                  WINED3DVECTOR_4 *texcoords, int *numcoords)        /* texture info */
477 {
478     unsigned int textureNo;
479     float s, t, r, q;
480     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
481
482     /* Diffuse -------------------------------- */
483     if (isDiffuse) {
484         glColor4fv(dRGBA);
485         VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
486     }
487
488     /* Specular Colour ------------------------------------------*/
489     if (isSpecular) {
490         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
491           GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
492           VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
493         } else {
494           VTRACE(("Specular color extensions not supplied\n"));
495         }
496     }
497
498     /* Normal -------------------------------- */
499     if (isNormal) {
500         VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
501         glNormal3f(nx, ny, nz);
502     }
503
504     /* Point Size ----------------------------------------------*/
505     if (isPtSize) {
506
507         /* no such functionality in the fixed function GL pipeline */
508         FIXME("Cannot change ptSize here in openGl\n");
509     }
510
511     /* Texture coords --------------------------- */
512     for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
513
514         if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
515             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
516             continue ;
517         }
518
519         /* Query tex coords */
520         if (This->stateBlock->textures[textureNo] != NULL) {
521
522             int    coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
523             if (coordIdx >= MAX_TEXTURES) {
524                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
525                 continue;
526             } else if (numcoords[coordIdx] == 0) {
527                 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
528                 continue;
529             } else {
530
531                 /* Initialize vars */
532                 s = 0.0f;
533                 t = 0.0f;
534                 r = 0.0f;
535                 q = 0.0f;
536
537                 switch (numcoords[coordIdx]) {
538                 case 4: q = texcoords[coordIdx].w; /* drop through */
539                 case 3: r = texcoords[coordIdx].z; /* drop through */
540                 case 2: t = texcoords[coordIdx].y; /* drop through */
541                 case 1: s = texcoords[coordIdx].x;
542                 }
543
544                 switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
545                 case WINED3DTTFF_COUNT1:
546                     VTRACE(("tex:%d, s=%f\n", textureNo, s));
547                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
548                         GLMULTITEXCOORD1F(textureNo, s);
549                     } else {
550                         glTexCoord1f(s);
551                     }
552                     break;
553                 case WINED3DTTFF_COUNT2:
554                     VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
555                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
556                         GLMULTITEXCOORD2F(textureNo, s, t);
557                     } else {
558                         glTexCoord2f(s, t);
559                     }
560                     break;
561                 case WINED3DTTFF_COUNT3:
562                     VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
563                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
564                         GLMULTITEXCOORD3F(textureNo, s, t, r);
565                     } else {
566                         glTexCoord3f(s, t, r);
567                     }
568                     break;
569                 case WINED3DTTFF_COUNT4:
570                     VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
571                     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
572                         GLMULTITEXCOORD4F(textureNo, s, t, r, q);
573                     } else {
574                         glTexCoord4f(s, t, r, q);
575                     }
576                     break;
577                 default:
578                     FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
579                 }
580             }
581         }
582     } /* End of textures */
583
584     /* Position -------------------------------- */
585     if (isXYZ) {
586         if (1.0f == rhw || rhw < 0.00001f) {
587             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
588             glVertex3f(x, y, z);
589         } else {
590             /* Cannot optimize by dividing through by rhw as rhw is required
591                later for perspective in the GL pipeline for vertex shaders   */
592             VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
593             glVertex4f(x,y,z,rhw);
594         }
595     }
596 }
597 #endif /* TODO: Software shaders */
598
599 /* This should match any arrays loaded in loadNumberedArrays. */
600 /* TODO: Only load / unload arrays if we have to. */
601 static void unloadNumberedArrays(IWineD3DDevice *iface) {
602     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
603
604     /* disable any attribs (this is the same for both GLSL and ARB modes) */
605     GLint maxAttribs;
606     int i;
607
608     /* Leave all the attribs disabled */
609     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
610     /* MESA does not support it right not */
611     if (glGetError() != GL_NO_ERROR)
612         maxAttribs = 16;
613     for (i = 0; i < maxAttribs; ++i) {
614         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
615         checkGLcall("glDisableVertexAttribArrayARB(reg);");
616     }
617 }
618
619 /* TODO: Only load / unload arrays if we have to. */
620 static void loadNumberedArrays(
621     IWineD3DDevice *iface,
622     IWineD3DVertexShader *shader,
623     WineDirect3DVertexStridedData *strided) {
624
625     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
626     GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
627     int i;
628
629     for (i = 0; i < MAX_ATTRIBS; i++) {
630
631         if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
632             continue;
633
634         TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
635
636         if(curVBO != strided->u.input[i].VBO) {
637             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
638             checkGLcall("glBindBufferARB");
639             curVBO = strided->u.input[i].VBO;
640         }
641         GL_EXTCALL(glVertexAttribPointerARB(i,
642                         WINED3D_ATR_SIZE(strided->u.input[i].dwType),
643                         WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
644                         WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
645                         strided->u.input[i].dwStride,
646                         strided->u.input[i].lpData + This->stateBlock->baseVertexIndex * strided->u.input[i].dwStride));
647         GL_EXTCALL(glEnableVertexAttribArrayARB(i));
648    }
649 }
650
651 /* This should match any arrays loaded in loadVertexData. */
652 /* TODO: Only load / unload arrays if we have to. */
653 static void unloadVertexData(IWineD3DDevice *iface) {
654     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
655     int texture_idx;
656
657     glDisableClientState(GL_VERTEX_ARRAY);
658     glDisableClientState(GL_NORMAL_ARRAY);
659     glDisableClientState(GL_COLOR_ARRAY);
660     if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
661         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
662     }
663     for (texture_idx = 0; texture_idx < GL_LIMITS(textures); ++texture_idx) {
664         GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
665         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
666     }
667 }
668
669 /* TODO: Only load / unload arrays if we have to. */
670 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
671     unsigned int textureNo   = 0;
672     unsigned int texture_idx = 0;
673     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
674     GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
675
676     TRACE("Using fast vertex array code\n");
677     /* Blend Data ---------------------------------------------- */
678     if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
679         (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
680
681
682         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
683
684 #if 1
685             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
686             checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
687 #endif
688
689             TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
690                 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride);
691             /* FIXME("TODO\n");*/
692             /* Note dwType == float3 or float4 == 2 or 3 */
693
694 #if 0
695             /* with this on, the normals appear to be being modified,
696                but the vertices aren't being translated as they should be
697                Maybe the world matrix aren't being setup properly? */
698             glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1);
699 #endif
700
701
702             VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
703                 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
704                 sd->u.s.blendWeights.dwStride,
705                 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride));
706
707             if(curVBO != sd->u.s.blendWeights.VBO) {
708                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
709                 checkGLcall("glBindBufferARB");
710                 curVBO = sd->u.s.blendWeights.VBO;
711             }
712
713             GL_EXTCALL(glWeightPointerARB)(
714                 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
715                 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
716                 sd->u.s.blendWeights.dwStride,
717                 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride);
718
719             checkGLcall("glWeightPointerARB");
720
721             if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
722                 static BOOL showfixme = TRUE;
723                 if(showfixme){
724                     FIXME("blendMatrixIndices support\n");
725                     showfixme = FALSE;
726                 }
727             }
728
729         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
730             /* FIXME("TODO\n");*/
731 #if 0
732
733             GL_EXTCALL(glVertexWeightPointerEXT)(
734                 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
735                 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
736                 sd->u.s.blendWeights.dwStride,
737                 sd->u.s.blendWeights.lpData + This->stateBlock->baseVertexIndex * sd->u.s.blendWeights.dwStride);
738             checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
739             glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
740             checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
741 #endif
742
743         } else {
744             /* TODO: support blends in fixupVertices */
745             FIXME("unsupported blending in openGl\n");
746         }
747     } else {
748         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
749 #if 0    /* TODO: Vertex blending */
750             glDisable(GL_VERTEX_BLEND_ARB);
751 #endif
752             TRACE("ARB_VERTEX_BLEND\n");
753         } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
754             TRACE(" EXT_VERTEX_WEIGHTING\n");
755             glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
756             checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
757
758         }
759     }
760
761 #if 0 /* FOG  ----------------------------------------------*/
762     if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
763         /* TODO: fog*/
764     if (GL_SUPPORT(EXT_FOG_COORD) {
765              glEnableClientState(GL_FOG_COORDINATE_EXT);
766             (GL_EXTCALL)(FogCoordPointerEXT)(
767                 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
768                 sd->u.s.fog.dwStride,
769                 sd->u.s.fog.lpData + This->stateBlock->baseVertexIndex * sd->u.s.fog.dwStride);
770         } else {
771             /* don't bother falling back to 'slow' as we don't support software FOG yet. */
772             /* FIXME: fixme once */
773             TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
774         }
775     } else {
776         if (GL_SUPPRT(EXT_FOR_COORD) {
777              /* make sure fog is disabled */
778              glDisableClientState(GL_FOG_COORDINATE_EXT);
779         }
780     }
781 #endif
782
783 #if 0 /* tangents  ----------------------------------------------*/
784     if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
785         sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
786         /* TODO: tangents*/
787         if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
788             if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
789                 glEnable(GL_TANGENT_ARRAY_EXT);
790                 (GL_EXTCALL)(TangentPointerEXT)(
791                     WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
792                     sd->u.s.tangent.dwStride,
793                     sd->u.s.tangent.lpData + This->stateBlock->baseVertexIndex * sd->u.s.tangent.dwStride);
794             } else {
795                     glDisable(GL_TANGENT_ARRAY_EXT);
796             }
797             if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
798                     glEnable(GL_BINORMAL_ARRAY_EXT);
799                     (GL_EXTCALL)(BinormalPointerEXT)(
800                         WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
801                         sd->u.s.binormal.dwStride,
802                         sd->u.s.binormal.lpData + This->stateBlock->baseVertexIndex * sd->u.s.binormal.dwStride);
803             } else{
804                     glDisable(GL_BINORMAL_ARRAY_EXT);
805             }
806
807         } else {
808             /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
809             /* FIXME: fixme once */
810             TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
811         }
812     } else {
813         if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
814              /* make sure fog is disabled */
815              glDisable(GL_TANGENT_ARRAY_EXT);
816              glDisable(GL_BINORMAL_ARRAY_EXT);
817         }
818     }
819 #endif
820
821     /* Point Size ----------------------------------------------*/
822     if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
823
824         /* no such functionality in the fixed function GL pipeline */
825         TRACE("Cannot change ptSize here in openGl\n");
826         /* TODO: Implement this function in using shaders if they are available */
827
828     }
829
830     /* Vertex Pointers -----------------------------------------*/
831     if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
832         /* Note dwType == float3 or float4 == 2 or 3 */
833         VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
834                 sd->u.s.position.dwStride,
835                 sd->u.s.position.dwType + 1,
836                 sd->u.s.position.lpData));
837
838         if(curVBO != sd->u.s.position.VBO) {
839             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
840             checkGLcall("glBindBufferARB");
841             curVBO = sd->u.s.position.VBO;
842         }
843
844         /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
845            handling for rhw mode should not impact screen position whereas in GL it does.
846            This may  result in very slightly distored textures in rhw mode, but
847            a very minimal different. There's always the other option of
848            fixing the view matrix to prevent w from having any effect
849
850            This only applies to user pointer sources, in VBOs the vertices are fixed up
851          */
852         if(sd->u.s.position.VBO == 0) {
853             glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
854                 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
855                 sd->u.s.position.dwStride, sd->u.s.position.lpData + This->stateBlock->baseVertexIndex * sd->u.s.position.dwStride);
856         } else {
857             glVertexPointer(
858                 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
859                 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
860                 sd->u.s.position.dwStride, sd->u.s.position.lpData + This->stateBlock->baseVertexIndex * sd->u.s.position.dwStride);
861         }
862         checkGLcall("glVertexPointer(...)");
863         glEnableClientState(GL_VERTEX_ARRAY);
864         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
865
866     } else {
867         glDisableClientState(GL_VERTEX_ARRAY);
868         checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
869     }
870
871     /* Normals -------------------------------------------------*/
872     if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
873         /* Note dwType == float3 or float4 == 2 or 3 */
874         VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
875                 sd->u.s.normal.dwStride,
876                 sd->u.s.normal.lpData));
877         if(curVBO != sd->u.s.normal.VBO) {
878             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
879             checkGLcall("glBindBufferARB");
880             curVBO = sd->u.s.normal.VBO;
881         }
882         glNormalPointer(
883             WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
884             sd->u.s.normal.dwStride,
885             sd->u.s.normal.lpData + This->stateBlock->baseVertexIndex * sd->u.s.normal.dwStride);
886         checkGLcall("glNormalPointer(...)");
887         glEnableClientState(GL_NORMAL_ARRAY);
888         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
889
890     } else {
891         glDisableClientState(GL_NORMAL_ARRAY);
892         checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
893         glNormal3f(0, 0, 1);
894         checkGLcall("glNormal3f(0, 0, 1)");
895     }
896
897     /* Diffuse Colour --------------------------------------------*/
898     /*  WARNING: Data here MUST be in RGBA format, so cannot      */
899     /*     go directly into fast mode from app pgm, because       */
900     /*     directx requires data in BGRA format.                  */
901     /* currently fixupVertices swizels the format, but this isn't */
902     /* very practical when using VBOS                             */
903     /* NOTE: Unless we write a vertex shader to swizel the colour */
904     /* , or the user doesn't care and wants the speed advantage   */
905
906     if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
907         /* Note dwType == float3 or float4 == 2 or 3 */
908         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
909                 sd->u.s.diffuse.dwStride,
910                 sd->u.s.diffuse.lpData));
911
912         if(curVBO != sd->u.s.diffuse.VBO) {
913             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
914             checkGLcall("glBindBufferARB");
915             curVBO = sd->u.s.diffuse.VBO;
916         }
917         glColorPointer(4, GL_UNSIGNED_BYTE,
918                        sd->u.s.diffuse.dwStride,
919                        sd->u.s.diffuse.lpData + This->stateBlock->baseVertexIndex * sd->u.s.diffuse.dwStride);
920         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
921         glEnableClientState(GL_COLOR_ARRAY);
922         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
923
924     } else {
925         glDisableClientState(GL_COLOR_ARRAY);
926         checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
927         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
928         checkGLcall("glColor4f(1, 1, 1, 1)");
929     }
930
931     /* Specular Colour ------------------------------------------*/
932     if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
933         TRACE("setting specular colour\n");
934         /* Note dwType == float3 or float4 == 2 or 3 */
935         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
936                 sd->u.s.specular.dwStride,
937                 sd->u.s.specular.lpData));
938         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
939             if(curVBO != sd->u.s.specular.VBO) {
940                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
941                 checkGLcall("glBindBufferARB");
942                 curVBO = sd->u.s.specular.VBO;
943             }
944             GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
945                                                    sd->u.s.specular.dwStride,
946                                                    sd->u.s.specular.lpData + This->stateBlock->baseVertexIndex * sd->u.s.specular.dwStride);
947             vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
948             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
949             vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
950         } else {
951
952         /* Missing specular color is not critical, no warnings */
953         VTRACE(("Specular colour is not supported in this GL implementation\n"));
954         }
955
956     } else {
957         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
958
959             glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
960             checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
961             GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
962             checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
963         } else {
964
965             /* Missing specular color is not critical, no warnings */
966             VTRACE(("Specular colour is not supported in this GL implementation\n"));
967         }
968     }
969
970     /* Texture coords -------------------------------------------*/
971
972     for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
973         /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
974         /* Abort if we don't support the extension. */
975         if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
976             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
977             continue;
978         }
979
980         if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/ TRUE) {
981             /* Select the correct texture stage */
982             GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
983         }
984
985         if (This->stateBlock->textures[textureNo] != NULL) {
986             int coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
987
988             if (coordIdx >= MAX_TEXTURES) {
989                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
990                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
991                 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
992
993             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
994                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
995                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
996                 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
997
998             } else {
999                 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1000                       textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1001                 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1002                     GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1003                     checkGLcall("glBindBufferARB");
1004                     curVBO = sd->u.s.texCoords[coordIdx].VBO;
1005                 }
1006                 /* The coords to supply depend completely on the fvf / vertex shader */
1007                 glTexCoordPointer(
1008                     WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1009                     WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1010                     sd->u.s.texCoords[coordIdx].dwStride,
1011                     sd->u.s.texCoords[coordIdx].lpData + This->stateBlock->baseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride);
1012                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1013             }
1014         } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1015             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1016             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1017         }
1018         if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/ TRUE) ++texture_idx;
1019     }
1020     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1021         for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
1022             GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
1023             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1024             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1025         }
1026     }
1027 }
1028
1029 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1030                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
1031     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1032
1033     if (idxData != NULL /* This crashes sometimes!*/) {
1034         TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1035         idxData = idxData == (void *)-1 ? NULL : idxData;
1036 #if 1
1037 #if 0
1038         glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1039         glEnableClientState(GL_INDEX_ARRAY);
1040 #endif
1041         glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1042                      (const char *)idxData+(idxSize * startIdx));
1043 #else /* using drawRangeElements may be faster */
1044
1045         glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1046                       idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1047                       (const char *)idxData+(idxSize * startIdx));
1048 #endif
1049         checkGLcall("glDrawRangeElements");
1050
1051     } else {
1052
1053         /* Note first is now zero as we shuffled along earlier */
1054         TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1055         glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
1056         checkGLcall("glDrawArrays");
1057
1058     }
1059
1060     return;
1061 }
1062
1063 /*
1064  * Actually draw using the supplied information.
1065  * Slower GL version which extracts info about each vertex in turn
1066  */
1067
1068 static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1069                      UINT NumVertexes, GLenum glPrimType,
1070                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
1071
1072     unsigned int               textureNo    = 0;
1073     unsigned int               texture_idx  = 0;
1074     const short               *pIdxBufS     = NULL;
1075     const long                *pIdxBufL     = NULL;
1076     LONG                       vx_index;
1077     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1078     float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
1079     float rhw = 0.0f;                      /* rhw                        */
1080     float ptSize = 0.0f;                   /* Point size                 */
1081     DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
1082     DWORD specularColor = 0;               /* Specular Color             */
1083     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1084     LONG                       SkipnStrides = startVertex + This->stateBlock->baseVertexIndex;
1085
1086     TRACE("Using slow vertex array code\n");
1087
1088     /* Variable Initialization */
1089     if (idxData != NULL) {
1090         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1091         else pIdxBufL = (const long *) idxData;
1092     }
1093
1094     /* Start drawing in GL */
1095     VTRACE(("glBegin(%x)\n", glPrimType));
1096     glBegin(glPrimType);
1097
1098     /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
1099      * Guess it's not necessary(we crash then anyway) and would only eat CPU time
1100      */
1101
1102     /* For each primitive */
1103     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1104
1105         /* Initialize diffuse color */
1106         diffuseColor = 0xFFFFFFFF;
1107
1108         /* For indexed data, we need to go a few more strides in */
1109         if (idxData != NULL) {
1110
1111             /* Indexed so work out the number of strides to skip */
1112             if (idxSize == 2) {
1113                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1114                 SkipnStrides = pIdxBufS[startIdx + vx_index] + This->stateBlock->baseVertexIndex;
1115             } else {
1116                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1117                 SkipnStrides = pIdxBufL[startIdx + vx_index] + This->stateBlock->baseVertexIndex;
1118             }
1119         }
1120
1121         /* Position Information ------------------ */
1122         if (sd->u.s.position.lpData != NULL) {
1123
1124             float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1125             x = ptrToCoords[0];
1126             y = ptrToCoords[1];
1127             z = ptrToCoords[2];
1128             rhw = 1.0;
1129             VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1130
1131             /* RHW follows, only if transformed, ie 4 floats were provided */
1132             if (sd->u.s.position_transformed) {
1133                 rhw = ptrToCoords[3];
1134                 VTRACE(("rhw=%f\n", rhw));
1135             }
1136         }
1137
1138         /* Blending data -------------------------- */
1139         if (sd->u.s.blendWeights.lpData != NULL) {
1140             /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1141             FIXME("Blending not supported yet\n");
1142
1143             if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1144                 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1145             }
1146         }
1147
1148         /* Vertex Normal Data (untransformed only)- */
1149         if (sd->u.s.normal.lpData != NULL) {
1150
1151             float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1152             nx = ptrToCoords[0];
1153             ny = ptrToCoords[1];
1154             nz = ptrToCoords[2];
1155             VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1156         }
1157
1158         /* Point Size ----------------------------- */
1159         if (sd->u.s.pSize.lpData != NULL) {
1160
1161             float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1162             ptSize = ptrToCoords[0];
1163             VTRACE(("ptSize=%f\n", ptSize));
1164             FIXME("No support for ptSize yet\n");
1165         }
1166
1167         /* Diffuse -------------------------------- */
1168         if (sd->u.s.diffuse.lpData != NULL) {
1169
1170             DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1171             diffuseColor = ptrToCoords[0];
1172             VTRACE(("diffuseColor=%lx\n", diffuseColor));
1173         }
1174
1175         /* Specular  -------------------------------- */
1176         if (sd->u.s.specular.lpData != NULL) {
1177
1178             DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1179             specularColor = ptrToCoords[0];
1180             VTRACE(("specularColor=%lx\n", specularColor));
1181         }
1182
1183         /* Texture coords --------------------------- */
1184         for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1185
1186             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1187                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1188                 continue ;
1189             }
1190
1191             /* Query tex coords */
1192             if (This->stateBlock->textures[textureNo] != NULL) {
1193
1194                 int    coordIdx = This->stateBlock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1195                 float *ptrToCoords = NULL;
1196                 float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1197
1198                 if (coordIdx > 7) {
1199                     VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1200                     ++texture_idx;
1201                     continue;
1202                 } else if (coordIdx < 0) {
1203                     FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
1204                     ++texture_idx;
1205                     continue;
1206                 }
1207
1208                 ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1209                 if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1210                     TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1211                     ++texture_idx;
1212                     continue;
1213                 } else {
1214
1215                     int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == WINED3DDECLTYPE_FLOAT1 etc */
1216
1217                     /* The coords to supply depend completely on the fvf / vertex shader */
1218                     switch (coordsToUse) {
1219                     case 4: q = ptrToCoords[3]; /* drop through */
1220                     case 3: r = ptrToCoords[2]; /* drop through */
1221                     case 2: t = ptrToCoords[1]; /* drop through */
1222                     case 1: s = ptrToCoords[0];
1223                     }
1224
1225                     /* Projected is more 'fun' - Move the last coord to the 'q'
1226                           parameter (see comments under WINED3DTSS_TEXTURETRANSFORMFLAGS */
1227                     if ((This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) &&
1228                         (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)) {
1229
1230                         if (This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) {
1231                             switch (coordsToUse) {
1232                             case 0:  /* Drop Through */
1233                             case 1:
1234                                 FIXME("WINED3DTTFF_PROJECTED but only zero or one coordinate?\n");
1235                                 break;
1236                             case 2:
1237                                 q = t;
1238                                 t = 0.0;
1239                                 coordsToUse = 4;
1240                                 break;
1241                             case 3:
1242                                 q = r;
1243                                 r = 0.0;
1244                                 coordsToUse = 4;
1245                                 break;
1246                             case 4:  /* Nop here */
1247                                 break;
1248                             default:
1249                                 FIXME("Unexpected WINED3DTSS_TEXTURETRANSFORMFLAGS value of %d\n",
1250                                       This->stateBlock->textureState[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED);
1251                             }
1252                         }
1253                     }
1254
1255                     switch (coordsToUse) {   /* Supply the provided texture coords */
1256                     case WINED3DTTFF_COUNT1:
1257                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
1258                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1259                             GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
1260                         } else {
1261                             glTexCoord1f(s);
1262                         }
1263                         break;
1264                     case WINED3DTTFF_COUNT2:
1265                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1266                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1267                             GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
1268                         } else {
1269                             glTexCoord2f(s, t);
1270                         }
1271                         break;
1272                     case WINED3DTTFF_COUNT3:
1273                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1274                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1275                             GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
1276                         } else {
1277                             glTexCoord3f(s, t, r);
1278                         }
1279                         break;
1280                     case WINED3DTTFF_COUNT4:
1281                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1282                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1283                             GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
1284                         } else {
1285                             glTexCoord4f(s, t, r, q);
1286                         }
1287                         break;
1288                     default:
1289                         FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1290                     }
1291                 }
1292             }
1293             if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]*/TRUE) ++texture_idx;
1294         } /* End of textures */
1295
1296         /* Diffuse -------------------------------- */
1297         if (sd->u.s.diffuse.lpData != NULL) {
1298           glColor4ub(D3DCOLOR_B_R(diffuseColor),
1299                      D3DCOLOR_B_G(diffuseColor),
1300                      D3DCOLOR_B_B(diffuseColor),
1301                      D3DCOLOR_B_A(diffuseColor));
1302             VTRACE(("glColor4ub: r,g,b,a=%lu,%lu,%lu,%lu\n", 
1303                     D3DCOLOR_B_R(diffuseColor),
1304                     D3DCOLOR_B_G(diffuseColor),
1305                     D3DCOLOR_B_B(diffuseColor),
1306                     D3DCOLOR_B_A(diffuseColor)));
1307         } else {
1308             if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1309         }
1310
1311         /* Specular ------------------------------- */
1312         if (sd->u.s.specular.lpData != NULL) {
1313             /* special case where the fog density is stored in the diffuse alpha channel */
1314             if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
1315               (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || sd->u.s.position.dwType == WINED3DDECLTYPE_FLOAT4 )&&
1316               This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1317                 if(GL_SUPPORT(EXT_FOG_COORD)) {
1318                     GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
1319                 } else {
1320                     static BOOL warned = FALSE;
1321                     if(!warned) {
1322                         /* TODO: Use the fog table code from old ddraw */
1323                         FIXME("Implement fog for transformed vertices in software\n");
1324                         warned = TRUE;
1325                     }
1326                 }
1327             }
1328
1329             VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n", 
1330                     D3DCOLOR_B_R(specularColor), 
1331                     D3DCOLOR_B_G(specularColor), 
1332                     D3DCOLOR_B_B(specularColor)));
1333             if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1334                 GL_EXTCALL(glSecondaryColor3ubEXT)(
1335                            D3DCOLOR_B_R(specularColor),
1336                            D3DCOLOR_B_G(specularColor),
1337                            D3DCOLOR_B_B(specularColor));
1338             } else {
1339                 /* Do not worry if specular colour missing and disable request */
1340                 VTRACE(("Specular color extensions not supplied\n"));
1341             }
1342         } else {
1343             if (vx_index == 0) {
1344                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1345                     GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1346                 } else {
1347                     /* Do not worry if specular colour missing and disable request */
1348                     VTRACE(("Specular color extensions not supplied\n"));
1349                 }
1350             }
1351         }
1352
1353         /* Normal -------------------------------- */
1354         if (sd->u.s.normal.lpData != NULL) {
1355             VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1356             glNormal3f(nx, ny, nz);
1357         } else {
1358             if (vx_index == 0) glNormal3f(0, 0, 1);
1359         }
1360
1361         /* Position -------------------------------- */
1362         if (sd->u.s.position.lpData != NULL) {
1363             if (1.0f == rhw || ((rhw < eps) && (rhw > -eps))) {
1364                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1365                 glVertex3f(x, y, z);
1366             } else {
1367                 GLfloat w = 1.0 / rhw;
1368                 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1369                 glVertex4f(x*w, y*w, z*w, w);
1370             }
1371         }
1372
1373         /* For non indexed mode, step onto next parts */
1374         if (idxData == NULL) {
1375             ++SkipnStrides;
1376         }
1377     }
1378
1379     glEnd();
1380     checkGLcall("glEnd and previous calls");
1381 }
1382
1383 #if 0 /* TODO: Software/Hardware vertex blending support */
1384 /*
1385  * Draw with emulated vertex shaders
1386  * Note: strided data is uninitialized, as we need to pass the vertex
1387  *     shader directly as ordering irs yet
1388  */
1389 void drawStridedSoftwareVS(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd,
1390                      int PrimitiveType, ULONG NumPrimitives,
1391                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1392
1393     unsigned int               textureNo    = 0;
1394     GLenum                     glPrimType   = GL_POINTS;
1395     int                        NumVertexes  = NumPrimitives;
1396     const short               *pIdxBufS     = NULL;
1397     const long                *pIdxBufL     = NULL;
1398     LONG                       SkipnStrides = 0;
1399     LONG                       vx_index;
1400     float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
1401     float rhw = 0.0f;                      /* rhw                        */
1402     float ptSize = 0.0f;                   /* Point size                 */
1403     D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
1404     int   numcoords[8];                    /* Number of coords           */
1405     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1406
1407     IDirect3DVertexShaderImpl* vertexShader = NULL;
1408
1409     TRACE("Using slow software vertex shader code\n");
1410
1411     /* Variable Initialization */
1412     if (idxData != NULL) {
1413         if (idxSize == 2) pIdxBufS = (const short *) idxData;
1414         else pIdxBufL = (const long *) idxData;
1415     }
1416
1417     /* Ok, Work out which primitive is requested and how many vertexes that will be */
1418     NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1419
1420     /* Retrieve the VS information */
1421     vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1422
1423     /* Start drawing in GL */
1424     VTRACE(("glBegin(%x)\n", glPrimType));
1425     glBegin(glPrimType);
1426
1427     /* For each primitive */
1428     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1429
1430         /* For indexed data, we need to go a few more strides in */
1431         if (idxData != NULL) {
1432
1433             /* Indexed so work out the number of strides to skip */
1434             if (idxSize == 2) {
1435                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1436                 SkipnStrides = pIdxBufS[startIdx+vx_index];
1437             } else {
1438                 VTRACE(("Idx for vertex %d = %d\n", vx_index, pIdxBufL[startIdx+vx_index]));
1439                 SkipnStrides = pIdxBufL[startIdx+vx_index];
1440             }
1441         }
1442
1443         /* Fill the vertex shader input */
1444         IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1445
1446         /* Initialize the output fields to the same defaults as it would normally have */
1447         memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1448         vertexShader->output.oD[0].x = 1.0;
1449         vertexShader->output.oD[0].y = 1.0;
1450         vertexShader->output.oD[0].z = 1.0;
1451         vertexShader->output.oD[0].w = 1.0;
1452
1453         /* Now execute the vertex shader */
1454         IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1455
1456         /*
1457         TRACE_VECTOR(vertexShader->output.oPos);
1458         TRACE_VECTOR(vertexShader->output.oD[0]);
1459         TRACE_VECTOR(vertexShader->output.oD[1]);
1460         TRACE_VECTOR(vertexShader->output.oT[0]);
1461         TRACE_VECTOR(vertexShader->output.oT[1]);
1462         TRACE_VECTOR(vertexShader->input.V[0]);
1463         TRACE_VECTOR(vertexShader->data->C[0]);
1464         TRACE_VECTOR(vertexShader->data->C[1]);
1465         TRACE_VECTOR(vertexShader->data->C[2]);
1466         TRACE_VECTOR(vertexShader->data->C[3]);
1467         TRACE_VECTOR(vertexShader->data->C[4]);
1468         TRACE_VECTOR(vertexShader->data->C[5]);
1469         TRACE_VECTOR(vertexShader->data->C[6]);
1470         TRACE_VECTOR(vertexShader->data->C[7]);
1471         */
1472
1473         /* Extract out the output */
1474         /* FIXME: Fog coords? */
1475         x = vertexShader->output.oPos.x;
1476         y = vertexShader->output.oPos.y;
1477         z = vertexShader->output.oPos.z;
1478         rhw = vertexShader->output.oPos.w;
1479         ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1480
1481         /** Update textures coords using vertexShader->output.oT[0->7] */
1482         memset(texcoords, 0x00, sizeof(texcoords));
1483         memset(numcoords, 0x00, sizeof(numcoords));
1484         for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1485             if (This->stateBlock->textures[textureNo] != NULL) {
1486                texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1487                texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1488                texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1489                texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1490                if (This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] != WINED3DTTFF_DISABLE) {
1491                    numcoords[textureNo]    = This->stateBlock->texture_state[textureNo][WINED3DTSS_TEXTURETRANSFORMFLAGS] & ~WINED3DTTFF_PROJECTED;
1492                } else {
1493                    switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1494                    case WINED3DRTYPE_TEXTURE:       numcoords[textureNo] = 2; break;
1495                    case WINED3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1496                    default:                         numcoords[textureNo] = 4;
1497                    }
1498                }
1499             } else {
1500                 numcoords[textureNo] = 0;
1501             }
1502         }
1503
1504         /* Draw using this information */
1505         draw_vertex(iface,
1506                     TRUE, x, y, z, rhw,
1507                     TRUE, 0.0f, 0.0f, 1.0f,
1508                     TRUE, (float*) &vertexShader->output.oD[0],
1509                     TRUE, (float*) &vertexShader->output.oD[1],
1510                     FALSE, ptSize,         /* FIXME: Change back when supported */
1511                     texcoords, numcoords);
1512
1513         /* For non indexed mode, step onto next parts */
1514         if (idxData == NULL) {
1515            ++SkipnStrides;
1516         }
1517
1518     } /* for each vertex */
1519
1520     glEnd();
1521     checkGLcall("glEnd and previous calls");
1522 }
1523
1524 #endif
1525
1526 inline static void drawPrimitiveDrawStrided(
1527     IWineD3DDevice *iface,
1528     BOOL useVertexShaderFunction,
1529     BOOL usePixelShaderFunction,
1530     WineDirect3DVertexStridedData *dataLocations,
1531     ULONG baseVIndex,
1532     UINT numberOfvertices,
1533     UINT numberOfIndicies,
1534     GLenum glPrimType,
1535     const void *idxData,
1536     short idxSize,
1537     int minIndex,
1538     long StartIdx,
1539     BOOL fixup) {
1540
1541     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1542     BOOL useDrawStridedSlow;
1543
1544     int startStride = idxData == NULL ? 0 : 
1545                       idxData == (void *) -1 ? 0 :
1546                       (idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1547     int endStride = startStride;
1548     TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n",
1549         startStride, endStride, numberOfIndicies, numberOfvertices);
1550
1551 /* Generate some fixme's if unsupported functionality is being used */
1552 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1553     /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1554     if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1555         FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1556     }
1557     if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1558         FIXME("Tweening is only valid with vertex shaders\n");
1559     }
1560     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1561         FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1562     }
1563     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1564         FIXME("Extended attributes are only valid with vertex shaders\n");
1565     }
1566 #undef BUFFER_OR_DATA
1567
1568     /* Fixed pipeline, no fixups required - load arrays */
1569     if (!useVertexShaderFunction &&
1570        ((dataLocations->u.s.pSize.lpData == NULL &&
1571          dataLocations->u.s.diffuse.lpData == NULL &&
1572          dataLocations->u.s.specular.lpData == NULL) ||
1573          fixup) ) {
1574
1575         /* Load the vertex data using named arrays */
1576         TRACE("(%p) Loading vertex data\n", This);
1577         loadVertexData(iface, dataLocations);
1578         useDrawStridedSlow = FALSE;
1579
1580     /* Shader pipeline - load attribute arrays */
1581     } else if(useVertexShaderFunction) {
1582
1583         loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
1584         useDrawStridedSlow = FALSE;
1585
1586         /* We compile the shader here because we need the vertex declaration
1587          * in order to determine if we need to do any swizzling for D3DCOLOR
1588          * registers. If the shader is already compiled this call will do nothing. */
1589         IWineD3DVertexShader_CompileShader(This->stateBlock->vertexShader);
1590     /* Draw vertex by vertex */
1591     } else { 
1592         TRACE("Not loading vertex data\n");
1593         useDrawStridedSlow = TRUE;
1594     }
1595
1596     /* Make any shaders active */
1597     This->shader_backend->shader_select(iface, usePixelShaderFunction, useVertexShaderFunction);
1598
1599     /* Load any global constants/uniforms that may have been set by the application */
1600     This->shader_backend->shader_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
1601
1602     /* Draw vertex-by-vertex */
1603     if (useDrawStridedSlow)
1604         drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx, baseVIndex);
1605     else
1606         drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx, baseVIndex);
1607
1608     /* Cleanup any shaders */
1609     This->shader_backend->shader_cleanup(usePixelShaderFunction, useVertexShaderFunction);
1610
1611     /* Unload vertex data */
1612     if (useVertexShaderFunction) {
1613         unloadNumberedArrays(iface);
1614     } else {
1615         unloadVertexData(iface);
1616     }
1617 }
1618
1619 inline void drawPrimitiveTraceDataLocations(
1620     WineDirect3DVertexStridedData *dataLocations) {
1621
1622     /* Dump out what parts we have supplied */
1623     TRACE("Strided Data:\n");
1624     TRACE_STRIDED((dataLocations), position);
1625     TRACE_STRIDED((dataLocations), blendWeights);
1626     TRACE_STRIDED((dataLocations), blendMatrixIndices);
1627     TRACE_STRIDED((dataLocations), normal);
1628     TRACE_STRIDED((dataLocations), pSize);
1629     TRACE_STRIDED((dataLocations), diffuse);
1630     TRACE_STRIDED((dataLocations), specular);
1631     TRACE_STRIDED((dataLocations), texCoords[0]);
1632     TRACE_STRIDED((dataLocations), texCoords[1]);
1633     TRACE_STRIDED((dataLocations), texCoords[2]);
1634     TRACE_STRIDED((dataLocations), texCoords[3]);
1635     TRACE_STRIDED((dataLocations), texCoords[4]);
1636     TRACE_STRIDED((dataLocations), texCoords[5]);
1637     TRACE_STRIDED((dataLocations), texCoords[6]);
1638     TRACE_STRIDED((dataLocations), texCoords[7]);
1639     TRACE_STRIDED((dataLocations), position2);
1640     TRACE_STRIDED((dataLocations), normal2);
1641     TRACE_STRIDED((dataLocations), tangent);
1642     TRACE_STRIDED((dataLocations), binormal);
1643     TRACE_STRIDED((dataLocations), tessFactor);
1644     TRACE_STRIDED((dataLocations), fog);
1645     TRACE_STRIDED((dataLocations), depth);
1646     TRACE_STRIDED((dataLocations), sample);
1647
1648     return;
1649
1650 }
1651
1652 static void check_fbo_status(IWineD3DDevice *iface) {
1653     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1654
1655     GLenum status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
1656     switch(status) {
1657         case GL_FRAMEBUFFER_COMPLETE_EXT: TRACE("FBO complete.\n"); break;
1658         default: TRACE("FBO status %#x.\n", status); break;
1659     }
1660 }
1661
1662 static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
1663     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1664     GLint old_binding = 0;
1665
1666     glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
1667
1668     glDisable(GL_CULL_FACE);
1669     glDisable(GL_BLEND);
1670     glDisable(GL_ALPHA_TEST);
1671     glDisable(GL_STENCIL_TEST);
1672     glEnable(GL_DEPTH_TEST);
1673     glDepthFunc(GL_ALWAYS);
1674
1675     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1676     glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
1677     glBindTexture(GL_TEXTURE_2D, texture);
1678     glEnable(GL_TEXTURE_2D);
1679
1680     This->shader_backend->shader_select_depth_blt(iface);
1681
1682     glBegin(GL_TRIANGLE_STRIP);
1683     glVertex2f(-1.0f, -1.0f);
1684     glVertex2f(1.0f, -1.0f);
1685     glVertex2f(-1.0f, 1.0f);
1686     glVertex2f(1.0f, 1.0f);
1687     glEnd();
1688
1689     glBindTexture(GL_TEXTURE_2D, old_binding);
1690
1691     glPopAttrib();
1692 }
1693
1694 static void depth_copy(IWineD3DDevice *iface) {
1695     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1696     IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->depthStencilBuffer;
1697
1698     /* Only copy the depth buffer if there is one. */
1699     if (!depth_stencil) return;
1700
1701     /* TODO: Make this work for modes other than FBO */
1702     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
1703
1704     if (This->render_offscreen) {
1705         static GLuint tmp_texture = 0;
1706         GLint old_binding = 0;
1707
1708         TRACE("Copying onscreen depth buffer to offscreen surface\n");
1709
1710         if (!tmp_texture) {
1711             glGenTextures(1, &tmp_texture);
1712         }
1713
1714         /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
1715          * directly on the FBO texture. That's because we need to flip. */
1716         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1717         glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
1718         glBindTexture(GL_TEXTURE_2D, tmp_texture);
1719         glCopyTexImage2D(depth_stencil->glDescription.target,
1720                 depth_stencil->glDescription.level,
1721                 depth_stencil->glDescription.glFormatInternal,
1722                 0,
1723                 0,
1724                 depth_stencil->currentDesc.Width,
1725                 depth_stencil->currentDesc.Height,
1726                 0);
1727         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1728         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1729         glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
1730         glBindTexture(GL_TEXTURE_2D, old_binding);
1731
1732         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
1733         checkGLcall("glBindFramebuffer()");
1734         depth_blt(iface, tmp_texture);
1735         checkGLcall("depth_blt");
1736     } else {
1737         TRACE("Copying offscreen surface to onscreen depth buffer\n");
1738
1739         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
1740         checkGLcall("glBindFramebuffer()");
1741         depth_blt(iface, depth_stencil->glDescription.textureName);
1742         checkGLcall("depth_blt");
1743     }
1744 }
1745
1746 /* Routine common to the draw primitive and draw indexed primitive routines */
1747 void drawPrimitive(IWineD3DDevice *iface,
1748                    int PrimitiveType,
1749                    long NumPrimitives,
1750                    /* for Indexed: */
1751                    long  StartVertexIndex,
1752                    UINT  numberOfVertices,
1753                    long  StartIdx,
1754                    short idxSize,
1755                    const void *idxData,
1756                    int   minIndex) {
1757
1758     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
1759     BOOL                          useVertexShaderFunction = FALSE;
1760     BOOL                          usePixelShaderFunction = FALSE;
1761     IWineD3DSwapChainImpl         *swapchain;
1762     int                           i;
1763     BOOL                          fixup;
1764     DWORD                         dirtyState, idx;
1765     BYTE                          shift;
1766
1767     /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
1768      * here simply check whether a shader was set, or the user disabled shaders */
1769     if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
1770         ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL) 
1771         useVertexShaderFunction = TRUE;
1772
1773     if (This->ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
1774         ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function) 
1775         usePixelShaderFunction = TRUE;
1776
1777     /* Invalidate the back buffer memory so LockRect will read it the next time */
1778     for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
1779         IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
1780         if(swapchain) {
1781             if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
1782             IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1783         }
1784     }
1785
1786     /* Ok, we will be updating the screen from here onwards so grab the lock */
1787     ENTER_GL();
1788
1789     /* Apply dirty states */
1790     for(i=0; i < This->numDirtyEntries; i++) {
1791         dirtyState = This->dirtyArray[i];
1792         idx = dirtyState >> 5;
1793         shift = dirtyState & 0x1f;
1794         This->isStateDirty[idx] &= ~(1 << shift);
1795         StateTable[dirtyState].apply(dirtyState, This->stateBlock);
1796     }
1797     This->numDirtyEntries = 0; /* This makes the whole list clean */
1798     fixup = This->streamFixedUp;
1799
1800     if (TRACE_ON(d3d_draw) && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1801         check_fbo_status(iface);
1802     }
1803
1804     if (This->depth_copy_state == WINED3D_DCS_COPY) {
1805         depth_copy(iface);
1806     }
1807     This->depth_copy_state = WINED3D_DCS_INITIAL;
1808
1809     /* Now initialize the materials state */
1810     init_materials(iface, (This->strided_streams.u.s.diffuse.lpData != NULL || This->strided_streams.u.s.diffuse.VBO != 0));
1811
1812     {
1813         GLenum glPrimType;
1814         /* Ok, Work out which primitive is requested and how many vertexes that
1815            will be                                                              */
1816         UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1817         if (numberOfVertices == 0 )
1818             numberOfVertices = calculatedNumberOfindices;
1819
1820         drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction,
1821             &This->strided_streams, StartVertexIndex, numberOfVertices, calculatedNumberOfindices, glPrimType,
1822             idxData, idxSize, minIndex, StartIdx, fixup);
1823     }
1824
1825     /* Finshed updating the screen, restore lock */
1826     LEAVE_GL();
1827     TRACE("Done all gl drawing\n");
1828
1829     /* Diagnostics */
1830 #ifdef SHOW_FRAME_MAKEUP
1831     {
1832         static long int primCounter = 0;
1833         /* NOTE: set primCounter to the value reported by drawprim 
1834            before you want to to write frame makeup to /tmp */
1835         if (primCounter >= 0) {
1836             WINED3DLOCKED_RECT r;
1837             char buffer[80];
1838             IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
1839             sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
1840             TRACE("Saving screenshot %s\n", buffer);
1841             IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1842             IWineD3DSurface_UnlockRect(This->renderTarget);
1843
1844 #ifdef SHOW_TEXTURE_MAKEUP
1845            {
1846             IWineD3DSurface *pSur;
1847             int textureNo;
1848             for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1849                 if (This->stateBlock->textures[textureNo] != NULL) {
1850                     sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
1851                     TRACE("Saving texture %s\n", buffer);
1852                     if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
1853                             IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
1854                             IWineD3DSurface_SaveSnapshot(pSur, buffer);
1855                             IWineD3DSurface_Release(pSur);
1856                     } else  {
1857                         FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
1858                     }
1859                 }
1860             }
1861            }
1862 #endif
1863         }
1864         TRACE("drawprim #%d\n", primCounter);
1865         ++primCounter;
1866     }
1867 #endif
1868 }