2 * WINED3D draw functions
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
32 extern IDirect3DVertexShaderImpl* VertexShaders[64];
33 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
34 extern IDirect3DPixelShaderImpl* PixelShaders[64];
36 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
39 /* Returns bits for what is expected from the fixed function pipeline, and whether
40 a vertex shader will be in use. Note the fvf bits returned may be split over
41 multiple streams only if the vertex shader was created, otherwise it all relates
43 static BOOL initializeFVF(IWineD3DDevice *iface, DWORD *FVFbits)
46 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
48 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
49 /* The first thing to work out is if we are using the fixed function pipeline
50 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
51 is the FVF, or with a shader which was created with no function - in which
52 case there is an FVF per declared stream. If this occurs, we also maintain
53 an 'OR' of all the FVF's together so we know what to expect across all the
56 *FVFbits = This->stateBlock->fvf;
58 *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
63 /* Issues the glBegin call for gl given the primitive type and count */
64 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
68 DWORD NumVertexes = NumPrimitives;
70 switch (PrimitiveType) {
73 *primType = GL_POINTS;
74 NumVertexes = NumPrimitives;
80 NumVertexes = NumPrimitives * 2;
84 TRACE("LINE_STRIP\n");
85 *primType = GL_LINE_STRIP;
86 NumVertexes = NumPrimitives + 1;
89 case D3DPT_TRIANGLELIST:
91 *primType = GL_TRIANGLES;
92 NumVertexes = NumPrimitives * 3;
95 case D3DPT_TRIANGLESTRIP:
96 TRACE("TRIANGLE_STRIP\n");
97 *primType = GL_TRIANGLE_STRIP;
98 NumVertexes = NumPrimitives + 2;
101 case D3DPT_TRIANGLEFAN:
102 TRACE("TRIANGLE_FAN\n");
103 *primType = GL_TRIANGLE_FAN;
104 NumVertexes = NumPrimitives + 2;
108 FIXME("Unhandled primitive\n");
109 *primType = GL_POINTS;
115 /* Ensure the appropriate material states are set up - only change
116 state if really required */
117 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
119 BOOL requires_material_reset = FALSE;
120 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
122 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
123 /* If we have not set up the material color tracking, do it now as required */
124 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
125 checkGLcall("glDisable GL_COLOR_MATERIAL");
126 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
127 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
128 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
129 glEnable(GL_COLOR_MATERIAL);
130 checkGLcall("glEnable GL_COLOR_MATERIAL");
131 This->tracking_color = IS_TRACKING;
132 requires_material_reset = TRUE; /* Restore material settings as will be used */
134 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
135 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
136 /* If we are tracking the current color but one isn't supplied, don't! */
137 glDisable(GL_COLOR_MATERIAL);
138 checkGLcall("glDisable GL_COLOR_MATERIAL");
139 This->tracking_color = NEEDS_TRACKING;
140 requires_material_reset = TRUE; /* Restore material settings as will be used */
142 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
143 /* No need to reset material colors since no change to gl_color_material */
144 requires_material_reset = FALSE;
146 } else if (This->tracking_color == NEEDS_DISABLE) {
147 glDisable(GL_COLOR_MATERIAL);
148 checkGLcall("glDisable GL_COLOR_MATERIAL");
149 This->tracking_color = DISABLED_TRACKING;
150 requires_material_reset = TRUE; /* Restore material settings as will be used */
153 /* Reset the material colors which may have been tracking the color*/
154 if (requires_material_reset) {
155 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
156 checkGLcall("glMaterialfv");
157 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
158 checkGLcall("glMaterialfv");
159 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
160 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
161 checkGLcall("glMaterialfv");
163 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
164 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
165 checkGLcall("glMaterialfv");
167 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
168 checkGLcall("glMaterialfv");
173 static GLfloat invymat[16] = {
174 1.0f, 0.0f, 0.0f, 0.0f,
175 0.0f, -1.0f, 0.0f, 0.0f,
176 0.0f, 0.0f, 1.0f, 0.0f,
177 0.0f, 0.0f, 0.0f, 1.0f};
179 /* Setup views - Transformed & lit if RHW, else untransformed.
180 Only unlit if Normals are supplied
181 Returns: Whether to restore lighting afterwards */
182 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
184 BOOL isLightingOn = FALSE;
185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
187 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
188 set by the appropriate render state. Note Vertex Shader output is already lit */
189 if (vtx_lit || useVS) {
190 isLightingOn = glIsEnabled(GL_LIGHTING);
191 glDisable(GL_LIGHTING);
192 checkGLcall("glDisable(GL_LIGHTING);");
193 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
196 if (!useVS && vtx_transformed) {
198 /* If the last draw was transformed as well, no need to reapply all the matrixes */
199 if (!This->last_was_rhw) {
201 double X, Y, height, width, minZ, maxZ;
202 This->last_was_rhw = TRUE;
204 /* Transformed already into viewport coordinates, so we do not need transform
205 matrices. Reset all matrices to identity and leave the default matrix in world
207 glMatrixMode(GL_MODELVIEW);
208 checkGLcall("glMatrixMode(GL_MODELVIEW)");
210 checkGLcall("glLoadIdentity");
212 glMatrixMode(GL_PROJECTION);
213 checkGLcall("glMatrixMode(GL_PROJECTION)");
215 checkGLcall("glLoadIdentity");
217 /* Set up the viewport to be full viewport */
218 X = This->stateBlock->viewport.X;
219 Y = This->stateBlock->viewport.Y;
220 height = This->stateBlock->viewport.Height;
221 width = This->stateBlock->viewport.Width;
222 minZ = This->stateBlock->viewport.MinZ;
223 maxZ = This->stateBlock->viewport.MaxZ;
224 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
225 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
226 checkGLcall("glOrtho");
228 /* Window Coord 0 is the middle of the first pixel, so translate by half
229 a pixel (See comment above glTranslate below) */
230 glTranslatef(0.5, 0.5, 0);
231 checkGLcall("glTranslatef(0.5, 0.5, 0)");
232 if (This->renderUpsideDown) {
233 glMultMatrixf(invymat);
234 checkGLcall("glMultMatrixf(invymat)");
240 /* Untransformed, so relies on the view and projection matrices */
242 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
243 /* Only reapply when have to */
244 This->modelview_valid = TRUE;
245 glMatrixMode(GL_MODELVIEW);
246 checkGLcall("glMatrixMode");
248 /* In the general case, the view matrix is the identity matrix */
249 if (This->view_ident) {
250 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
251 checkGLcall("glLoadMatrixf");
253 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
254 checkGLcall("glLoadMatrixf");
255 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
256 checkGLcall("glMultMatrixf");
260 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
261 /* Only reapply when have to */
262 This->proj_valid = TRUE;
263 glMatrixMode(GL_PROJECTION);
264 checkGLcall("glMatrixMode");
266 /* The rule is that the window coordinate 0 does not correspond to the
267 beginning of the first pixel, but the center of the first pixel.
268 As a consequence if you want to correctly draw one line exactly from
269 the left to the right end of the viewport (with all matrices set to
270 be identity), the x coords of both ends of the line would be not
271 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
275 glTranslatef(1.0 / This->stateBlock->viewport.Width, -1.0 / This->stateBlock->viewport.Height, 0);
276 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, 0)");
278 if (This->renderUpsideDown) {
279 glMultMatrixf(invymat);
280 checkGLcall("glMultMatrixf(invymat)");
282 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
283 checkGLcall("glLoadMatrixf");
286 /* Vertex Shader output is already transformed, so set up identity matrices */
287 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
288 come along this needs to take into account whether s/w ones were
291 glMatrixMode(GL_MODELVIEW);
292 checkGLcall("glMatrixMode");
294 glMatrixMode(GL_PROJECTION);
295 checkGLcall("glMatrixMode");
297 /* Window Coord 0 is the middle of the first pixel, so translate by half
298 a pixel (See comment above glTranslate above) */
299 glTranslatef(1.0 / This->stateBlock->viewport.Width, -1.0 / This->stateBlock->viewport.Height, 0);
300 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, 0)");
301 if (This->renderUpsideDown) {
302 glMultMatrixf(invymat);
303 checkGLcall("glMultMatrixf(invymat)");
305 This->modelview_valid = FALSE;
306 This->proj_valid = FALSE;
308 This->last_was_rhw = FALSE;
313 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
314 /* We need to deal with frequency data!*/
318 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
319 IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
321 D3DVERTEXELEMENT9 *element;
323 for (i = 0 ; i < vertexDeclaration->declaration9NumElements - 1; ++i) {
325 element = vertexDeclaration->pDeclaration9 + i;
326 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclaration9, element, i, vertexDeclaration->declaration9NumElements);
327 if (This->stateBlock->streamIsUP) {
328 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
329 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
331 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
332 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
334 stride = This->stateBlock->streamStride[element->Stream];
335 data += (BaseVertexIndex * stride);
336 data += element->Offset;
337 /* Why can't I just use a lookup table instead of a switch statment? */
338 switch (element->Usage) {
339 case D3DDECLUSAGE_POSITION:
340 switch (element->UsageIndex) {
341 case 0: /* N-patch */
342 strided->u.s.position.lpData = data;
343 strided->u.s.position.dwType = element->Type;
344 strided->u.s.position.dwStride = stride;
346 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
347 TRACE("Tweened positions\n");
348 strided->u.s.position2.lpData = data;
349 strided->u.s.position2.dwType = element->Type;
350 strided->u.s.position2.dwStride = stride;
354 case D3DDECLUSAGE_NORMAL:
355 switch (element->UsageIndex) {
356 case 0: /* N-patch */
357 strided->u.s.normal.lpData = data;
358 strided->u.s.normal.dwType = element->Type;
359 strided->u.s.normal.dwStride = stride;
361 case 1: /* skinning */
362 TRACE("Skinning / tween normals\n");
363 strided->u.s.normal2.lpData = data;
364 strided->u.s.normal2.dwType = element->Type;
365 strided->u.s.normal2.dwStride = stride;
368 *fvf |= D3DFVF_NORMAL;
370 case D3DDECLUSAGE_BLENDINDICES:
371 /* demo @http://www.ati.com/developer/vertexblend.html
372 and http://www.flipcode.com/articles/article_dx8shaders.shtml
374 strided->u.s.blendMatrixIndices.lpData = data;
375 strided->u.s.blendMatrixIndices.dwType = element->Type;
376 strided->u.s.blendMatrixIndices.dwStride= stride;
378 case D3DDECLUSAGE_BLENDWEIGHT:
379 strided->u.s.blendWeights.lpData = data;
380 strided->u.s.blendWeights.dwType = element->Type;
381 strided->u.s.blendWeights.dwStride = stride;
383 case D3DDECLUSAGE_PSIZE:
384 strided->u.s.pSize.lpData = data;
385 strided->u.s.pSize.dwType = element->Type;
386 strided->u.s.pSize.dwStride = stride;
388 case D3DDECLUSAGE_COLOR:
389 switch (element->UsageIndex) {
391 strided->u.s.diffuse.lpData = data;
392 strided->u.s.diffuse.dwType = element->Type;
393 strided->u.s.diffuse.dwStride = stride;
395 case 1: /* specular */
396 strided->u.s.specular.lpData = data;
397 strided->u.s.specular.dwType = element->Type;
398 strided->u.s.specular.dwStride = stride;
402 case D3DDECLUSAGE_TEXCOORD:
403 /* For some odd reason Microsoft decided to sum usage accross all the streams,
404 which means we need to do a count and not just use the usage number */
406 strided->u.s.texCoords[textureNo].lpData = data;
407 strided->u.s.texCoords[textureNo].dwType = element->Type;
408 strided->u.s.texCoords[textureNo].dwStride = stride;
412 case D3DDECLUSAGE_TANGENT:
413 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
414 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
415 normal using tangents where no normal data has been provided */
417 strided->u.s.tangent.lpData = data;
418 strided->u.s.tangent.dwType = element->Type;
419 strided->u.s.tangent.dwStride = stride;
421 case D3DDECLUSAGE_BINORMAL:
422 /* Binormals are really bitangents perpendicular to the normal but s-aligned to the tangent, basically they are the vectors of any two lines on the plain at right angles to the normal and at right angles to each other, like the x,y,z axis.
423 tangent data makes it easier to perform some calculations (a bit like using 2d graph paper instead of the normal of the piece of paper)
424 The only thing they are useful for in fixed function would be working out normals when none are given.
426 TRACE("BI-Normal\n");
427 strided->u.s.binormal.lpData = data;
428 strided->u.s.binormal.dwType = element->Type;
429 strided->u.s.binormal.dwStride = stride;
431 case D3DDECLUSAGE_TESSFACTOR:
432 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
434 TRACE("Tess Factor\n");
435 strided->u.s.tessFactor.lpData = data;
436 strided->u.s.tessFactor.dwType = element->Type;
437 strided->u.s.tessFactor.dwStride = stride;
439 case D3DDECLUSAGE_POSITIONT:
441 switch (element->UsageIndex) {
442 case 0: /* N-patch */
443 strided->u.s.position.lpData = data;
444 strided->u.s.position.dwType = element->Type;
445 strided->u.s.position.dwStride = stride;
447 case 1: /* skinning */
448 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
449 http://xface.blogspot.com/2004_08_01_xface_archive.html
451 TRACE("Skinning positionsT\n");
452 strided->u.s.position2.lpData = data;
453 strided->u.s.position2.dwType = element->Type;
454 strided->u.s.position2.dwStride = stride;
457 /* TODO: change fvf usage to a plain boolean flag */
458 *fvf |= D3DFVF_XYZRHW;
459 /* FIXME: were faking this flag so that we don't transform the data again */
461 case D3DDECLUSAGE_FOG:
462 /* maybe GL_EXT_fog_coord ?
463 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
464 * This extension allows specifying an explicit per-vertex fog
465 * coordinate to be used in fog computations, rather than using a
466 * fragment depth-based fog equation.
470 strided->u.s.fog.lpData = data;
471 strided->u.s.fog.dwType = element->Type;
472 strided->u.s.fog.dwStride = stride;
474 case D3DDECLUSAGE_DEPTH:
476 strided->u.s.depth.lpData = data;
477 strided->u.s.depth.dwType = element->Type;
478 strided->u.s.depth.dwStride = stride;
480 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
482 strided->u.s.sample.lpData = data;
483 strided->u.s.sample.dwType = element->Type;
484 strided->u.s.sample.dwStride = stride;
492 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
494 short LoopThroughTo = 0;
499 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
500 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
502 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
504 /* OK, Now to setup the data locations
505 For the non-created vertex shaders, the VertexShader var holds the real
506 FVF and only stream 0 matters
507 For the created vertex shaders, there is an FVF per stream */
508 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
509 LoopThroughTo = MAX_STREAMS;
514 /* Work through stream by stream */
515 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
516 DWORD stride = This->stateBlock->streamStride[nStream];
520 /* Skip empty streams */
521 if (This->stateBlock->streamSource[nStream] == NULL) continue;
523 /* Retrieve appropriate FVF */
524 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
525 thisFVF = This->stateBlock->fvf;
526 /* Handle memory passed directly as well as vertex buffers */
527 if (This->stateBlock->streamIsUP) {
528 data = (BYTE *)This->stateBlock->streamSource[nStream];
530 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
533 #if 0 /* TODO: Vertex shader support */
534 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
535 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
538 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
539 if (thisFVF == 0) continue;
541 /* Now convert the stream into pointers */
543 /* Shuffle to the beginning of the vertexes to render and index from there */
544 data = data + (BaseVertexIndex * stride);
546 /* Either 3 or 4 floats depending on the FVF */
547 /* FIXME: Can blending data be in a different stream to the position data?
548 and if so using the fixed pipeline how do we handle it */
549 if (thisFVF & D3DFVF_POSITION_MASK) {
550 strided->u.s.position.lpData = data;
551 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
552 strided->u.s.position.dwStride = stride;
553 data += 3 * sizeof(float);
554 if (thisFVF & D3DFVF_XYZRHW) {
555 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
556 data += sizeof(float);
560 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
561 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
562 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
563 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
565 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
566 TRACE("Setting blend Weights to %p \n", data);
567 strided->u.s.blendWeights.lpData = data;
568 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
569 strided->u.s.blendWeights.dwStride = stride;
570 data += numBlends * sizeof(FLOAT);
572 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
573 strided->u.s.blendMatrixIndices.lpData = data;
574 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
575 strided->u.s.blendMatrixIndices.dwStride= stride;
576 data += sizeof(DWORD);
580 /* Normal is always 3 floats */
581 if (thisFVF & D3DFVF_NORMAL) {
582 strided->u.s.normal.lpData = data;
583 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
584 strided->u.s.normal.dwStride = stride;
585 data += 3 * sizeof(FLOAT);
588 /* Pointsize is a single float */
589 if (thisFVF & D3DFVF_PSIZE) {
590 strided->u.s.pSize.lpData = data;
591 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
592 strided->u.s.pSize.dwStride = stride;
593 data += sizeof(FLOAT);
596 /* Diffuse is 4 unsigned bytes */
597 if (thisFVF & D3DFVF_DIFFUSE) {
598 strided->u.s.diffuse.lpData = data;
599 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
600 strided->u.s.diffuse.dwStride = stride;
601 data += sizeof(DWORD);
604 /* Specular is 4 unsigned bytes */
605 if (thisFVF & D3DFVF_SPECULAR) {
606 strided->u.s.specular.lpData = data;
607 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
608 strided->u.s.specular.dwStride = stride;
609 data += sizeof(DWORD);
613 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
614 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
616 /* numTextures indicates the number of texture coordinates supplied */
617 /* However, the first set may not be for stage 0 texture - it all */
618 /* depends on D3DTSS_TEXCOORDINDEX. */
619 /* The number of bytes for each coordinate set is based off */
620 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
622 /* So, for each supplied texture extract the coords */
623 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
625 strided->u.s.texCoords[textureNo].lpData = data;
626 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
627 strided->u.s.texCoords[textureNo].dwStride = stride;
628 numCoords[textureNo] = coordIdxInfo & 0x03;
631 data += sizeof(float);
632 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
633 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
634 data += sizeof(float);
635 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
636 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
637 data += sizeof(float);
638 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
639 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
640 data += sizeof(float);
644 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
649 #if 0 /* TODO: Software Shaders */
650 /* Draw a single vertex using this information */
651 static void draw_vertex(IWineD3DDevice *iface, /* interface */
652 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
653 BOOL isNormal, float nx, float ny, float nz, /* normal */
654 BOOL isDiffuse, float *dRGBA, /* 1st colors */
655 BOOL isSpecular, float *sRGB, /* 2ndry colors */
656 BOOL isPtSize, float ptSize, /* pointSize */
657 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
659 unsigned int textureNo;
661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
663 /* Diffuse -------------------------------- */
666 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
669 /* Specular Colour ------------------------------------------*/
671 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
672 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
673 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
675 VTRACE(("Specular color extensions not supplied\n"));
679 /* Normal -------------------------------- */
681 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
682 glNormal3f(nx, ny, nz);
685 /* Point Size ----------------------------------------------*/
688 /* no such functionality in the fixed function GL pipeline */
689 FIXME("Cannot change ptSize here in openGl\n");
692 /* Texture coords --------------------------- */
693 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
695 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
696 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
700 /* Query tex coords */
701 if (This->stateBlock->textures[textureNo] != NULL) {
703 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
704 if (coordIdx >= MAX_TEXTURES) {
705 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
707 } else if (numcoords[coordIdx] == 0) {
708 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
712 /* Initialize vars */
718 switch (numcoords[coordIdx]) {
719 case 4: q = texcoords[coordIdx].w; /* drop through */
720 case 3: r = texcoords[coordIdx].z; /* drop through */
721 case 2: t = texcoords[coordIdx].y; /* drop through */
722 case 1: s = texcoords[coordIdx].x;
725 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
727 VTRACE(("tex:%d, s=%f\n", textureNo, s));
728 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
729 GLMULTITEXCOORD1F(textureNo, s);
735 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
736 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
737 GLMULTITEXCOORD2F(textureNo, s, t);
743 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
744 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
745 GLMULTITEXCOORD3F(textureNo, s, t, r);
747 glTexCoord3f(s, t, r);
751 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
752 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
753 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
755 glTexCoord4f(s, t, r, q);
759 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
763 } /* End of textures */
765 /* Position -------------------------------- */
767 if (1.0f == rhw || rhw < 0.00001f) {
768 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
771 /* Cannot optimize by dividing through by rhw as rhw is required
772 later for perspective in the GL pipeline for vertex shaders */
773 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
774 glVertex4f(x,y,z,rhw);
778 #endif /* TODO: Software shaders */
781 * Actually draw using the supplied information.
782 * Faster GL version using pointers to data, harder to debug though
783 * Note does not handle vertex shaders yet
785 static void drawStridedFast(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
786 int PrimitiveType, ULONG NumPrimitives,
787 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
788 unsigned int textureNo = 0;
789 GLenum glPrimType = GL_POINTS;
790 int NumVertexes = NumPrimitives;
791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
793 TRACE("Using fast vertex array code\n");
795 /* Vertex Pointers -----------------------------------------*/
796 if (sd->u.s.position.lpData != NULL) {
798 /* Note dwType == float3 or float4 == 2 or 3 */
799 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
800 sd->u.s.position.dwStride,
801 sd->u.s.position.dwType + 1,
802 sd->u.s.position.lpData));
804 /* Disable RHW mode as 'w' coord handling for rhw mode should
805 not impact screen position whereas in GL it does. This may
806 result in very slightly distored textures in rhw mode, but
807 a very minimal different */
808 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
809 sd->u.s.position.dwStride,
810 sd->u.s.position.lpData);
811 checkGLcall("glVertexPointer(...)");
812 glEnableClientState(GL_VERTEX_ARRAY);
813 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
817 glDisableClientState(GL_VERTEX_ARRAY);
818 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
821 /* Blend Data ----------------------------------------------*/
822 if ((sd->u.s.blendWeights.lpData != NULL) ||
823 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
824 #if 1 /* Vertex blend support needs to be added */
825 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
826 DWORD fvf = (sd->u.s.blendWeights.dwType - D3DDECLTYPE_FLOAT1) + 1;
827 int numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == (fvf & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);
829 /* Note dwType == float3 or float4 == 2 or 3 */
830 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
832 sd->u.s.blendWeights.dwStride,
833 sd->u.s.blendWeights.lpData));
834 GL_EXTCALL(glWeightPointerARB)(numBlends, GL_FLOAT,
835 sd->u.s.blendWeights.dwStride,
836 sd->u.s.blendWeights.lpData);
837 checkGLcall("glWeightPointerARB(...)");
838 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
839 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
840 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
843 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
844 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
845 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
846 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
849 FIXME("unsupported blending in openGl\n");
852 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
853 TRACE("TODO ARB_VERTEX_BLEND\n");
854 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
855 TRACE("TODO EXT_VERTEX_WEIGHTING\n");
857 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
858 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
862 /* FIXME: Won't get here as will drop to slow method */
863 FIXME("Blending not supported in fast draw routine\n");
867 /* Normals -------------------------------------------------*/
868 if (sd->u.s.normal.lpData != NULL) {
870 /* Note dwType == float3 or float4 == 2 or 3 */
871 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
872 sd->u.s.normal.dwStride,
873 sd->u.s.normal.lpData));
874 glNormalPointer(GL_FLOAT,
875 sd->u.s.normal.dwStride,
876 sd->u.s.normal.lpData);
877 checkGLcall("glNormalPointer(...)");
878 glEnableClientState(GL_NORMAL_ARRAY);
879 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
883 glDisableClientState(GL_NORMAL_ARRAY);
884 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
886 checkGLcall("glNormal3f(0, 0, 1)");
889 /* Point Size ----------------------------------------------*/
890 if (sd->u.s.pSize.lpData != NULL) {
892 /* no such functionality in the fixed function GL pipeline */
893 /* FIXME: Won't get here as will drop to slow method */
894 FIXME("Cannot change ptSize here in openGl\n");
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 if (sd->u.s.diffuse.lpData != NULL) {
903 /* Note dwType == float3 or float4 == 2 or 3 */
904 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
905 sd->u.s.diffuse.dwStride,
906 sd->u.s.diffuse.lpData));
907 glColorPointer(4, GL_UNSIGNED_BYTE,
908 sd->u.s.diffuse.dwStride,
909 sd->u.s.diffuse.lpData);
910 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
911 glEnableClientState(GL_COLOR_ARRAY);
912 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
916 glDisableClientState(GL_COLOR_ARRAY);
917 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
918 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
919 checkGLcall("glColor4f(1, 1, 1, 1)");
922 /* Specular Colour ------------------------------------------*/
923 if (sd->u.s.specular.lpData != NULL) {
925 /* Note dwType == float3 or float4 == 2 or 3 */
926 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
927 sd->u.s.specular.dwStride,
928 sd->u.s.specular.lpData));
930 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
931 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
932 sd->u.s.specular.dwStride,
933 sd->u.s.specular.lpData);
934 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
935 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
936 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
938 /* Missing specular color is not critical, no warnings */
939 VTRACE(("Specular colour is not supported in this GL implementation\n"));
944 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
945 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
946 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
947 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
948 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
950 /* Missing specular color is not critical, no warnings */
951 VTRACE(("Specular colour is not supported in this GL implementation\n"));
955 /* Texture coords -------------------------------------------*/
956 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
958 /* Select the correct texture stage */
959 GLCLIENTACTIVETEXTURE(textureNo);
961 /* Query tex coords */
962 if (This->stateBlock->textures[textureNo] != NULL) {
963 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
965 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
966 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
967 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
968 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
973 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
974 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
975 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
977 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
978 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
979 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
980 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
984 /* The coords to supply depend completely on the fvf / vertex shader */
988 switch (sd->u.s.texCoords[coordIdx].dwType) {
989 case D3DDECLTYPE_FLOAT1: size = 1, type = GL_FLOAT; break;
990 case D3DDECLTYPE_FLOAT2: size = 2, type = GL_FLOAT; break;
991 case D3DDECLTYPE_FLOAT3: size = 3, type = GL_FLOAT; break;
992 case D3DDECLTYPE_FLOAT4: size = 4, type = GL_FLOAT; break;
993 case D3DDECLTYPE_SHORT2: size = 2, type = GL_SHORT; break;
994 case D3DDECLTYPE_SHORT4: size = 4, type = GL_SHORT; break;
995 case D3DDECLTYPE_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
996 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
997 size = 4; type = GL_UNSIGNED_BYTE;
1000 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1001 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1004 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1005 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1009 /* Ok, Work out which primitive is requested and how many vertexes that
1011 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1013 /* Finally do the drawing */
1014 if (idxData != NULL) {
1016 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1017 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1018 glDrawElements(glPrimType, NumVertexes, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1019 (const char *)idxData + (idxSize * startIdx));
1021 glDrawRangeElements(glPrimType, minIndex, minIndex + NumVertexes - 1, NumVertexes,
1022 idxSize == 2 ? GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1023 (const char *)idxData + (idxSize * startIdx));
1025 checkGLcall("glDrawRangeElements");
1029 /* Note first is now zero as we shuffled along earlier */
1030 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1031 glDrawArrays(glPrimType, 0, NumVertexes);
1032 checkGLcall("glDrawArrays");
1038 * Actually draw using the supplied information.
1039 * Slower GL version which extracts info about each vertex in turn
1041 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1042 int PrimitiveType, ULONG NumPrimitives,
1043 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1045 unsigned int textureNo = 0;
1046 GLenum glPrimType = GL_POINTS;
1047 int NumVertexes = NumPrimitives;
1048 const short *pIdxBufS = NULL;
1049 const long *pIdxBufL = NULL;
1050 LONG SkipnStrides = 0;
1052 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1053 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1054 float rhw = 0.0f; /* rhw */
1055 float ptSize = 0.0f; /* Point size */
1056 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1057 DWORD specularColor = 0; /* Specular Color */
1058 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1060 TRACE("Using slow vertex array code\n");
1062 /* Variable Initialization */
1063 if (idxData != NULL) {
1064 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1065 else pIdxBufL = (const long *) idxData;
1068 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1069 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1071 /* Start drawing in GL */
1072 VTRACE(("glBegin(%x)\n", glPrimType));
1073 glBegin(glPrimType);
1075 /* For each primitive */
1076 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1078 /* Initialize diffuse color */
1079 diffuseColor = 0xFFFFFFFF;
1081 /* For indexed data, we need to go a few more strides in */
1082 if (idxData != NULL) {
1084 /* Indexed so work out the number of strides to skip */
1086 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1087 SkipnStrides = pIdxBufS[startIdx+vx_index];
1089 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1090 SkipnStrides = pIdxBufL[startIdx+vx_index];
1094 /* Position Information ------------------ */
1095 if (sd->u.s.position.lpData != NULL) {
1097 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1102 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1104 /* RHW follows, only if transformed, ie 4 floats were provided */
1105 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1106 rhw = ptrToCoords[3];
1107 VTRACE(("rhw=%f\n", rhw));
1111 /* Blending data -------------------------- */
1112 if (sd->u.s.blendWeights.lpData != NULL) {
1113 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
1114 FIXME("Blending not supported yet\n");
1116 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1117 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1121 /* Vertex Normal Data (untransformed only)- */
1122 if (sd->u.s.normal.lpData != NULL) {
1124 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1125 nx = ptrToCoords[0];
1126 ny = ptrToCoords[1];
1127 nz = ptrToCoords[2];
1128 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1131 /* Point Size ----------------------------- */
1132 if (sd->u.s.pSize.lpData != NULL) {
1134 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1135 ptSize = ptrToCoords[0];
1136 VTRACE(("ptSize=%f\n", ptSize));
1137 FIXME("No support for ptSize yet\n");
1140 /* Diffuse -------------------------------- */
1141 if (sd->u.s.diffuse.lpData != NULL) {
1143 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1144 diffuseColor = ptrToCoords[0];
1145 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1148 /* Specular -------------------------------- */
1149 if (sd->u.s.specular.lpData != NULL) {
1151 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1152 specularColor = ptrToCoords[0];
1153 VTRACE(("specularColor=%lx\n", specularColor));
1156 /* Texture coords --------------------------- */
1157 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1159 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1160 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1164 /* Query tex coords */
1165 if (This->stateBlock->textures[textureNo] != NULL) {
1167 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1168 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1169 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1172 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1174 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1175 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1179 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1181 /* The coords to supply depend completely on the fvf / vertex shader */
1182 switch (coordsToUse) {
1183 case 4: q = ptrToCoords[3]; /* drop through */
1184 case 3: r = ptrToCoords[2]; /* drop through */
1185 case 2: t = ptrToCoords[1]; /* drop through */
1186 case 1: s = ptrToCoords[0];
1189 /* Projected is more 'fun' - Move the last coord to the 'q'
1190 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1191 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1192 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1194 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1195 switch (coordsToUse) {
1196 case 0: /* Drop Through */
1198 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1210 case 4: /* Nop here */
1213 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1214 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1219 /* crude support for non-power2 textures */
1220 if (((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2) {
1221 t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY;
1222 s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX;
1225 switch (coordsToUse) { /* Supply the provided texture coords */
1226 case D3DTTFF_COUNT1:
1227 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1228 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1229 GLMULTITEXCOORD1F(textureNo, s);
1234 case D3DTTFF_COUNT2:
1235 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1236 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1237 GLMULTITEXCOORD2F(textureNo, s, t);
1242 case D3DTTFF_COUNT3:
1243 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1244 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1245 GLMULTITEXCOORD3F(textureNo, s, t, r);
1247 glTexCoord3f(s, t, r);
1250 case D3DTTFF_COUNT4:
1251 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1252 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1253 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1255 glTexCoord4f(s, t, r, q);
1259 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1263 } /* End of textures */
1265 /* Diffuse -------------------------------- */
1266 if (sd->u.s.diffuse.lpData != NULL) {
1267 glColor4ub((diffuseColor >> 16) & 0xFF,
1268 (diffuseColor >> 8) & 0xFF,
1269 (diffuseColor >> 0) & 0xFF,
1270 (diffuseColor >> 24) & 0xFF);
1271 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1272 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1273 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1274 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1275 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1277 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1280 /* Specular ------------------------------- */
1281 if (sd->u.s.diffuse.lpData != NULL) {
1282 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1283 ((specularColor >> 16) & 0xFF) / 255.0f,
1284 ((specularColor >> 8) & 0xFF) / 255.0f,
1285 ((specularColor >> 0) & 0xFF) / 255.0f));
1286 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1287 GL_EXTCALL(glSecondaryColor3ubEXT)(
1288 (specularColor >> 16) & 0xFF,
1289 (specularColor >> 8) & 0xFF,
1290 (specularColor >> 0) & 0xFF);
1292 /* Do not worry if specular colour missing and disable request */
1293 VTRACE(("Specular color extensions not supplied\n"));
1296 if (vx_index == 0) {
1297 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1298 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1300 /* Do not worry if specular colour missing and disable request */
1301 VTRACE(("Specular color extensions not supplied\n"));
1306 /* Normal -------------------------------- */
1307 if (sd->u.s.normal.lpData != NULL) {
1308 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1309 glNormal3f(nx, ny, nz);
1311 if (vx_index == 0) glNormal3f(0, 0, 1);
1314 /* Position -------------------------------- */
1315 if (sd->u.s.position.lpData != NULL) {
1316 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1317 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1318 glVertex3f(x, y, z);
1320 GLfloat w = 1.0 / rhw;
1321 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1322 glVertex4f(x*w, y*w, z*w, w);
1326 /* For non indexed mode, step onto next parts */
1327 if (idxData == NULL) {
1333 checkGLcall("glEnd and previous calls");
1336 #if 0 /* TODO: Software/Hardware vertex blending support */
1338 * Draw with emulated vertex shaders
1339 * Note: strided data is uninitialized, as we need to pass the vertex
1340 * shader directly as ordering irs yet
1342 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1343 int PrimitiveType, ULONG NumPrimitives,
1344 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1346 unsigned int textureNo = 0;
1347 GLenum glPrimType = GL_POINTS;
1348 int NumVertexes = NumPrimitives;
1349 const short *pIdxBufS = NULL;
1350 const long *pIdxBufL = NULL;
1351 LONG SkipnStrides = 0;
1353 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1354 float rhw = 0.0f; /* rhw */
1355 float ptSize = 0.0f; /* Point size */
1356 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1357 int numcoords[8]; /* Number of coords */
1358 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1360 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1362 TRACE("Using slow software vertex shader code\n");
1364 /* Variable Initialization */
1365 if (idxData != NULL) {
1366 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1367 else pIdxBufL = (const long *) idxData;
1370 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1371 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1373 /* Retrieve the VS information */
1374 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1376 /* Start drawing in GL */
1377 VTRACE(("glBegin(%x)\n", glPrimType));
1378 glBegin(glPrimType);
1380 /* For each primitive */
1381 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1383 /* For indexed data, we need to go a few more strides in */
1384 if (idxData != NULL) {
1386 /* Indexed so work out the number of strides to skip */
1388 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1389 SkipnStrides = pIdxBufS[startIdx+vx_index];
1391 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1392 SkipnStrides = pIdxBufL[startIdx+vx_index];
1396 /* Fill the vertex shader input */
1397 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1399 /* Initialize the output fields to the same defaults as it would normally have */
1400 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1401 vertex_shader->output.oD[0].x = 1.0;
1402 vertex_shader->output.oD[0].y = 1.0;
1403 vertex_shader->output.oD[0].z = 1.0;
1404 vertex_shader->output.oD[0].w = 1.0;
1406 /* Now execute the vertex shader */
1407 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1410 TRACE_VECTOR(vertex_shader->output.oPos);
1411 TRACE_VECTOR(vertex_shader->output.oD[0]);
1412 TRACE_VECTOR(vertex_shader->output.oD[1]);
1413 TRACE_VECTOR(vertex_shader->output.oT[0]);
1414 TRACE_VECTOR(vertex_shader->output.oT[1]);
1415 TRACE_VECTOR(vertex_shader->input.V[0]);
1416 TRACE_VECTOR(vertex_shader->data->C[0]);
1417 TRACE_VECTOR(vertex_shader->data->C[1]);
1418 TRACE_VECTOR(vertex_shader->data->C[2]);
1419 TRACE_VECTOR(vertex_shader->data->C[3]);
1420 TRACE_VECTOR(vertex_shader->data->C[4]);
1421 TRACE_VECTOR(vertex_shader->data->C[5]);
1422 TRACE_VECTOR(vertex_shader->data->C[6]);
1423 TRACE_VECTOR(vertex_shader->data->C[7]);
1426 /* Extract out the output */
1427 /*FIXME: Fog coords? */
1428 x = vertex_shader->output.oPos.x;
1429 y = vertex_shader->output.oPos.y;
1430 z = vertex_shader->output.oPos.z;
1431 rhw = vertex_shader->output.oPos.w;
1432 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1434 /** Update textures coords using vertex_shader->output.oT[0->7] */
1435 memset(texcoords, 0x00, sizeof(texcoords));
1436 memset(numcoords, 0x00, sizeof(numcoords));
1437 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1438 if (This->stateBlock->textures[textureNo] != NULL) {
1439 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1440 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1441 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1442 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1443 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1444 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1446 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1447 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1448 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1449 default: numcoords[textureNo] = 4;
1453 numcoords[textureNo] = 0;
1457 /* Draw using this information */
1460 TRUE, 0.0f, 0.0f, 1.0f,
1461 TRUE, (float*) &vertex_shader->output.oD[0],
1462 TRUE, (float*) &vertex_shader->output.oD[1],
1463 FALSE, ptSize, /* FIXME: Change back when supported */
1464 texcoords, numcoords);
1466 /* For non indexed mode, step onto next parts */
1467 if (idxData == NULL) {
1471 } /* for each vertex */
1474 checkGLcall("glEnd and previous calls");
1477 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1478 int PrimitiveType, ULONG NumPrimitives,
1479 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1481 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1488 TRACE("Drawing with hardware vertex shaders\n");
1490 /* Retrieve the VS information */
1491 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1493 /* Enable the Vertex Shader */
1494 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1495 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1496 glEnable(GL_VERTEX_PROGRAM_ARB);
1497 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1499 /* Update the constants */
1500 for (i = 0; i < D3D8_VSHADER_MAX_CONSTANTS; ++i) {
1501 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1502 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1505 /* Set up the vertex.attr[n] inputs */
1506 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1508 /* Ok, Work out which primitive is requested and how many vertexes that
1510 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1512 /* Finally do the drawing */
1513 if (idxData != NULL) {
1515 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1516 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1517 glDrawElements(glPrimType, NumVertexes, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1518 (const char *)idxData + (idxSize * startIdx));
1520 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes - 1, NumVertexes,
1521 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1522 (const char *)idxData + (idxSize * startIdx));
1524 checkGLcall("glDrawRangeElements");
1528 /* Note first is now zero as we shuffled along earlier */
1529 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1530 glDrawArrays(glPrimType, 0, NumVertexes);
1531 checkGLcall("glDrawArrays");
1537 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1539 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1543 /* Leave all the attribs disabled */
1544 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1545 /* MESA does not support it right not */
1546 if (glGetError() != GL_NO_ERROR)
1548 for (i = 0; i < maxAttribs; ++i) {
1549 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1550 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1554 glDisable(GL_VERTEX_PROGRAM_ARB);
1558 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1560 /* Dump out what parts we have supplied */
1561 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1562 TRACE_STRIDED((dataLocations), position);
1563 TRACE_STRIDED((dataLocations), blendWeights);
1564 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1565 TRACE_STRIDED((dataLocations), normal);
1566 TRACE_STRIDED((dataLocations), pSize);
1567 TRACE_STRIDED((dataLocations), diffuse);
1568 TRACE_STRIDED((dataLocations), specular);
1569 TRACE_STRIDED((dataLocations), texCoords[0]);
1570 TRACE_STRIDED((dataLocations), texCoords[1]);
1571 TRACE_STRIDED((dataLocations), texCoords[2]);
1572 TRACE_STRIDED((dataLocations), texCoords[3]);
1573 TRACE_STRIDED((dataLocations), texCoords[4]);
1574 TRACE_STRIDED((dataLocations), texCoords[5]);
1575 TRACE_STRIDED((dataLocations), texCoords[6]);
1576 TRACE_STRIDED((dataLocations), texCoords[7]);
1581 /* loads any dirty textures and returns true if any of the textures are nonpower2 */
1582 BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
1583 BOOL nonPower2 = FALSE;
1585 register IWineD3DBaseTexture *texture;
1586 /* And re-upload any dirty textures */
1587 for (i = 0; i < GL_LIMITS(textures); ++i) {
1588 texture = This->stateBlock->textures[i];
1589 if (texture != NULL) {
1590 if(IWineD3DBaseTexture_GetDirty(texture)) {
1591 /* Load up the texture now */
1592 IWineD3DTexture_PreLoad((IWineD3DTexture *)texture);
1594 if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) {
1595 /* TODO: Is this right, as its cast all texture types to texture8... checkme */
1596 IWineD3DSurface *surface;
1597 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface);
1598 if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
1607 /* Routine common to the draw primitive and draw indexed primitive routines */
1608 void drawPrimitive(IWineD3DDevice *iface,
1609 int PrimitiveType, long NumPrimitives,
1612 long StartVertexIndex,
1615 const void *idxData,
1620 #if 0 /* TODO: vertex and pixel shaders */
1621 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1622 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1625 BOOL useVertexShaderFunction = FALSE;
1626 BOOL isLightingOn = FALSE;
1627 Direct3DVertexStridedData dataLocations;
1629 BOOL nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */
1631 if (This->stateBlock->vertexDecl == NULL) {
1632 /* Work out what the FVF should look like */
1633 rc = initializeFVF(iface, &fvf);
1636 TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1639 /* If we will be using a vertex shader, do some initialization for it */
1640 if (useVertexShaderFunction) {
1641 #if 0 /* TODO: vertex and pixel shaders */
1642 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1643 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1645 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1646 This->devType != D3DDEVTYPE_REF &&
1647 !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1648 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1650 /** init Constants */
1651 if (This->stateBlock->Changed.vertexShaderConstant) {
1652 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1653 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1655 #endif /* TODO: vertex and pixel shaders */
1658 /* Ok, we will be updating the screen from here onwards so grab the lock */
1661 #if 0 /* TODO: vertex and pixel shaders */
1662 /* If we will be using a pixel, do some initialization for it */
1663 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1664 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1665 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1667 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1668 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1669 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1670 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1672 /* init Constants */
1673 if (This->stateBlock->Changed.pixelShaderConstant) {
1674 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1675 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1677 /* Update the constants */
1678 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1679 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1680 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1683 #endif /* TODO: vertex and pixel shaders */
1685 /* Initialize all values to null */
1686 if (useVertexShaderFunction == FALSE) {
1687 memset(&dataLocations, 0x00, sizeof(dataLocations));
1689 /* Convert to strided data */
1690 if (This->stateBlock->vertexDecl != NULL) {
1691 TRACE("================ Vertex Declaration ===================\n");
1692 primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1694 TRACE("================ FVF ===================\n");
1695 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1698 /* write out some debug information*/
1699 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1701 FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1704 /* Setup transform matrices and sort out */
1706 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1707 So make sure lighting is disabled. */
1708 isLightingOn = glIsEnabled(GL_LIGHTING);
1709 glDisable(GL_LIGHTING);
1710 checkGLcall("glDisable(GL_LIGHTING);");
1711 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1713 isLightingOn = primitiveInitState(iface,
1714 fvf & D3DFVF_XYZRHW,
1715 !(fvf & D3DFVF_NORMAL),
1716 useVertexShaderFunction);
1719 /* Now initialize the materials state */
1720 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1722 nonPower2 = drawPrimitiveUploadDirtyTextures(This);
1724 /* Now draw the graphics to the screen */
1725 if (useVertexShaderFunction) {
1727 /* Ideally, we should have software FV and hardware VS, possibly
1728 depending on the device type? */
1731 TRACE("Swap HW vertex shader\n");
1732 #if 0 /* TODO: vertex and pixel shaders */
1733 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1734 idxData, idxSize, minIndex, StartIdx);
1737 /* We will have to use the very, very slow emulation layer */
1738 TRACE("Swap SW vertex shader\n");
1739 #if 0 /* TODO: vertex and pixel shaders */
1740 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1741 idxData, idxSize, minIndex, StartIdx);
1745 } else if ((dataLocations.u.s.pSize.lpData != NULL)
1746 || (dataLocations.u.s.diffuse.lpData != NULL)
1748 /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1750 /* Fixme, Ideally, only use the per-vertex code for software HAL
1751 but until opengl supports all the functions returned to setup
1752 vertex arrays, we need to drop down to the slow mechanism for
1753 certain functions */
1755 /* We will have to use the slow version of GL per vertex setup */
1756 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1757 idxData, idxSize, minIndex, StartIdx);
1761 /* We can use the fast version of GL pointers */
1762 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1763 idxData, idxSize, minIndex, StartIdx);
1766 /* If vertex shaders or no normals, restore previous lighting state */
1767 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1768 if (isLightingOn) glEnable(GL_LIGHTING);
1769 else glDisable(GL_LIGHTING);
1770 TRACE("Restored lighting to original state\n");
1773 #if 0 /* TODO: vertex and pixel shaders */
1778 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1780 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1782 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1786 /* Finshed updating the screen, restore lock */
1788 TRACE("Done all gl drawing\n");
1791 #if defined(SHOW_FRAME_MAKEUP)
1793 if (isDumpingFrames) {
1796 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1797 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1798 TRACE("Saving screenshot %s\n", buffer);
1799 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1800 IWineD3DSurface_UnlockRect(This->renderTarget);
1802 #if defined(SHOW_TEXTURE_MAKEUP)
1804 IWineD3DSurface *pSur;
1806 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1807 if (This->stateBlock->textures[textureNo] != NULL) {
1808 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1809 TRACE("Saving texture %s\n", buffer);
1810 IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur);
1811 IWineD3DSurface_SaveSnapshot(pSur, buffer);
1812 IWineD3DSurface_Release(pSur);