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(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
276 checkGLcall("glTranslatef (0.9 / width, -0.9 / 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(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
300 checkGLcall("glTranslatef (0.9 / width, -0.9 / 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 switch (coordsToUse) { /* Supply the provided texture coords */
1220 case D3DTTFF_COUNT1:
1221 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1222 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1223 GLMULTITEXCOORD1F(textureNo, s);
1228 case D3DTTFF_COUNT2:
1229 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1230 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1231 GLMULTITEXCOORD2F(textureNo, s, t);
1236 case D3DTTFF_COUNT3:
1237 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1238 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1239 GLMULTITEXCOORD3F(textureNo, s, t, r);
1241 glTexCoord3f(s, t, r);
1244 case D3DTTFF_COUNT4:
1245 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1246 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1247 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1249 glTexCoord4f(s, t, r, q);
1253 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1257 } /* End of textures */
1259 /* Diffuse -------------------------------- */
1260 if (sd->u.s.diffuse.lpData != NULL) {
1261 glColor4ub((diffuseColor >> 16) & 0xFF,
1262 (diffuseColor >> 8) & 0xFF,
1263 (diffuseColor >> 0) & 0xFF,
1264 (diffuseColor >> 24) & 0xFF);
1265 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1266 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1267 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1268 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1269 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1271 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1274 /* Specular ------------------------------- */
1275 if (sd->u.s.diffuse.lpData != NULL) {
1276 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1277 ((specularColor >> 16) & 0xFF) / 255.0f,
1278 ((specularColor >> 8) & 0xFF) / 255.0f,
1279 ((specularColor >> 0) & 0xFF) / 255.0f));
1280 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1281 GL_EXTCALL(glSecondaryColor3ubEXT)(
1282 (specularColor >> 16) & 0xFF,
1283 (specularColor >> 8) & 0xFF,
1284 (specularColor >> 0) & 0xFF);
1286 /* Do not worry if specular colour missing and disable request */
1287 VTRACE(("Specular color extensions not supplied\n"));
1290 if (vx_index == 0) {
1291 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1292 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1294 /* Do not worry if specular colour missing and disable request */
1295 VTRACE(("Specular color extensions not supplied\n"));
1300 /* Normal -------------------------------- */
1301 if (sd->u.s.normal.lpData != NULL) {
1302 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1303 glNormal3f(nx, ny, nz);
1305 if (vx_index == 0) glNormal3f(0, 0, 1);
1308 /* Position -------------------------------- */
1309 if (sd->u.s.position.lpData != NULL) {
1310 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1311 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1312 glVertex3f(x, y, z);
1314 GLfloat w = 1.0 / rhw;
1315 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1316 glVertex4f(x*w, y*w, z*w, w);
1320 /* For non indexed mode, step onto next parts */
1321 if (idxData == NULL) {
1327 checkGLcall("glEnd and previous calls");
1330 #if 0 /* TODO: Software/Hardware vertex blending support */
1332 * Draw with emulated vertex shaders
1333 * Note: strided data is uninitialized, as we need to pass the vertex
1334 * shader directly as ordering irs yet
1336 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1337 int PrimitiveType, ULONG NumPrimitives,
1338 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1340 unsigned int textureNo = 0;
1341 GLenum glPrimType = GL_POINTS;
1342 int NumVertexes = NumPrimitives;
1343 const short *pIdxBufS = NULL;
1344 const long *pIdxBufL = NULL;
1345 LONG SkipnStrides = 0;
1347 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1348 float rhw = 0.0f; /* rhw */
1349 float ptSize = 0.0f; /* Point size */
1350 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1351 int numcoords[8]; /* Number of coords */
1352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1354 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1356 TRACE("Using slow software vertex shader code\n");
1358 /* Variable Initialization */
1359 if (idxData != NULL) {
1360 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1361 else pIdxBufL = (const long *) idxData;
1364 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1365 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1367 /* Retrieve the VS information */
1368 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1370 /* Start drawing in GL */
1371 VTRACE(("glBegin(%x)\n", glPrimType));
1372 glBegin(glPrimType);
1374 /* For each primitive */
1375 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1377 /* For indexed data, we need to go a few more strides in */
1378 if (idxData != NULL) {
1380 /* Indexed so work out the number of strides to skip */
1382 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1383 SkipnStrides = pIdxBufS[startIdx+vx_index];
1385 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1386 SkipnStrides = pIdxBufL[startIdx+vx_index];
1390 /* Fill the vertex shader input */
1391 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1393 /* Initialize the output fields to the same defaults as it would normally have */
1394 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1395 vertex_shader->output.oD[0].x = 1.0;
1396 vertex_shader->output.oD[0].y = 1.0;
1397 vertex_shader->output.oD[0].z = 1.0;
1398 vertex_shader->output.oD[0].w = 1.0;
1400 /* Now execute the vertex shader */
1401 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1404 TRACE_VECTOR(vertex_shader->output.oPos);
1405 TRACE_VECTOR(vertex_shader->output.oD[0]);
1406 TRACE_VECTOR(vertex_shader->output.oD[1]);
1407 TRACE_VECTOR(vertex_shader->output.oT[0]);
1408 TRACE_VECTOR(vertex_shader->output.oT[1]);
1409 TRACE_VECTOR(vertex_shader->input.V[0]);
1410 TRACE_VECTOR(vertex_shader->data->C[0]);
1411 TRACE_VECTOR(vertex_shader->data->C[1]);
1412 TRACE_VECTOR(vertex_shader->data->C[2]);
1413 TRACE_VECTOR(vertex_shader->data->C[3]);
1414 TRACE_VECTOR(vertex_shader->data->C[4]);
1415 TRACE_VECTOR(vertex_shader->data->C[5]);
1416 TRACE_VECTOR(vertex_shader->data->C[6]);
1417 TRACE_VECTOR(vertex_shader->data->C[7]);
1420 /* Extract out the output */
1421 /*FIXME: Fog coords? */
1422 x = vertex_shader->output.oPos.x;
1423 y = vertex_shader->output.oPos.y;
1424 z = vertex_shader->output.oPos.z;
1425 rhw = vertex_shader->output.oPos.w;
1426 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1428 /** Update textures coords using vertex_shader->output.oT[0->7] */
1429 memset(texcoords, 0x00, sizeof(texcoords));
1430 memset(numcoords, 0x00, sizeof(numcoords));
1431 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1432 if (This->stateBlock->textures[textureNo] != NULL) {
1433 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1434 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1435 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1436 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1437 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1438 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1440 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1441 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1442 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1443 default: numcoords[textureNo] = 4;
1447 numcoords[textureNo] = 0;
1451 /* Draw using this information */
1454 TRUE, 0.0f, 0.0f, 1.0f,
1455 TRUE, (float*) &vertex_shader->output.oD[0],
1456 TRUE, (float*) &vertex_shader->output.oD[1],
1457 FALSE, ptSize, /* FIXME: Change back when supported */
1458 texcoords, numcoords);
1460 /* For non indexed mode, step onto next parts */
1461 if (idxData == NULL) {
1465 } /* for each vertex */
1468 checkGLcall("glEnd and previous calls");
1471 static void drawStridedHardwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1472 int PrimitiveType, ULONG NumPrimitives,
1473 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1475 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1482 TRACE("Drawing with hardware vertex shaders\n");
1484 /* Retrieve the VS information */
1485 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1487 /* Enable the Vertex Shader */
1488 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1489 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1490 glEnable(GL_VERTEX_PROGRAM_ARB);
1491 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1493 /* Update the constants */
1494 for (i = 0; i < D3D8_VSHADER_MAX_CONSTANTS; ++i) {
1495 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->vertexShaderConstant[i]));
1496 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1499 /* Set up the vertex.attr[n] inputs */
1500 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1502 /* Ok, Work out which primitive is requested and how many vertexes that
1504 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1506 /* Finally do the drawing */
1507 if (idxData != NULL) {
1509 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1510 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1511 glDrawElements(glPrimType, NumVertexes, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1512 (const char *)idxData + (idxSize * startIdx));
1514 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes - 1, NumVertexes,
1515 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1516 (const char *)idxData + (idxSize * startIdx));
1518 checkGLcall("glDrawRangeElements");
1522 /* Note first is now zero as we shuffled along earlier */
1523 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1524 glDrawArrays(glPrimType, 0, NumVertexes);
1525 checkGLcall("glDrawArrays");
1531 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1533 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1537 /* Leave all the attribs disabled */
1538 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1539 /* MESA does not support it right not */
1540 if (glGetError() != GL_NO_ERROR)
1542 for (i = 0; i < maxAttribs; ++i) {
1543 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1544 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1548 glDisable(GL_VERTEX_PROGRAM_ARB);
1552 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1554 /* Dump out what parts we have supplied */
1555 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1556 TRACE_STRIDED((dataLocations), position);
1557 TRACE_STRIDED((dataLocations), blendWeights);
1558 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1559 TRACE_STRIDED((dataLocations), normal);
1560 TRACE_STRIDED((dataLocations), pSize);
1561 TRACE_STRIDED((dataLocations), diffuse);
1562 TRACE_STRIDED((dataLocations), specular);
1563 TRACE_STRIDED((dataLocations), texCoords[0]);
1564 TRACE_STRIDED((dataLocations), texCoords[1]);
1565 TRACE_STRIDED((dataLocations), texCoords[2]);
1566 TRACE_STRIDED((dataLocations), texCoords[3]);
1567 TRACE_STRIDED((dataLocations), texCoords[4]);
1568 TRACE_STRIDED((dataLocations), texCoords[5]);
1569 TRACE_STRIDED((dataLocations), texCoords[6]);
1570 TRACE_STRIDED((dataLocations), texCoords[7]);
1575 /* uploads textures and setup texture states ready for rendering */
1576 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1580 * OK, here we clear down any old junk iect in the context
1581 * enable the new texture and apply any state changes:
1583 * Loop through all textures
1584 * select texture unit
1585 * if there is a texture bound to that unit then..
1586 * disable all textures types on that unit
1587 * enable and bind the texture that is bound to that unit.
1588 * otherwise dissable all texture types on that unit.
1590 /* upload the textures */
1591 for (i = 0; i< GL_LIMITS(textures); ++i) {
1592 /* Bind the texture to the stage here */
1593 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1596 /* This isn't so much a warn as a message to the user about lack of hardware support */
1597 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1600 /* don't bother with textures that have a colorop of disable */
1601 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1602 if (This->stateBlock->textures[i] != NULL) {
1604 glDisable(GL_TEXTURE_1D);
1605 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1606 /* disable all texture states that aren't the selected textures' dimension */
1607 switch(This->stateBlock->textureDimensions[i]) {
1609 glDisable(GL_TEXTURE_3D);
1610 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1613 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1614 glDisable(GL_TEXTURE_2D);
1616 case GLTEXTURECUBEMAP:
1617 glDisable(GL_TEXTURE_2D);
1618 glDisable(GL_TEXTURE_3D);
1621 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1622 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1623 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1625 glEnable(This->stateBlock->textureDimensions[i]);
1627 /* Load up the texture now */
1628 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1629 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1630 /* this is a stub function representing the state blocks being seperated here we are only updating the texture state changes, other objects and units get updated when they change (or need to be updated), e.g. states that relate to a context member line the texture unit are only updated when the context needs updating */
1631 /* Tell the abse texture to sync it's states */
1632 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1635 /* Bind a default texture if no texture has been set, but colour-op is enabled */
1637 glDisable(GL_TEXTURE_2D);
1638 glDisable(GL_TEXTURE_3D);
1639 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1640 glEnable(GL_TEXTURE_1D);
1641 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1642 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1644 /** these ops apply to the texture unit, so they are preseved between texture changes, but for now brute force and reapply all
1645 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1646 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1647 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1648 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1649 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1651 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1652 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1653 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1654 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1657 /* no colorop so disable all the texture states */
1658 glDisable(GL_TEXTURE_1D);
1659 glDisable(GL_TEXTURE_2D);
1660 glDisable(GL_TEXTURE_3D);
1661 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1668 /* Routine common to the draw primitive and draw indexed primitive routines */
1669 void drawPrimitive(IWineD3DDevice *iface,
1670 int PrimitiveType, long NumPrimitives,
1673 long StartVertexIndex,
1676 const void *idxData,
1681 #if 0 /* TODO: vertex and pixel shaders */
1682 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1683 IDirect3DPixelShaderImpl *pixel_shader = NULL;
1685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1686 BOOL useVertexShaderFunction = FALSE;
1687 BOOL isLightingOn = FALSE;
1688 Direct3DVertexStridedData dataLocations;
1691 if (This->stateBlock->vertexDecl == NULL) {
1692 /* Work out what the FVF should look like */
1693 rc = initializeFVF(iface, &fvf);
1696 TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1699 /* If we will be using a vertex shader, do some initialization for it */
1700 if (useVertexShaderFunction) {
1701 #if 0 /* TODO: vertex and pixel shaders */
1702 vertex_shader = VERTEX_SHADER(This->stateBlock->VertexShader);
1703 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1705 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1706 This->devType != D3DDEVTYPE_REF &&
1707 !This->stateBlock->renderState[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1708 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1710 /** init Constants */
1711 if (This->stateBlock->Changed.vertexShaderConstant) {
1712 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1713 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->stateBlock->vertexShaderConstant[0], 96);
1715 #endif /* TODO: vertex and pixel shaders */
1718 /* Ok, we will be updating the screen from here onwards so grab the lock */
1721 #if 0 /* TODO: vertex and pixel shaders */
1722 /* If we will be using a pixel, do some initialization for it */
1723 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1724 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1725 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1727 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1728 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1729 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1730 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1732 /* init Constants */
1733 if (This->stateBlock->Changed.pixelShaderConstant) {
1734 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1735 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1737 /* Update the constants */
1738 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1739 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1740 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1743 #endif /* TODO: vertex and pixel shaders */
1745 /* Initialize all values to null */
1746 if (useVertexShaderFunction == FALSE) {
1747 memset(&dataLocations, 0x00, sizeof(dataLocations));
1749 /* Convert to strided data */
1750 if (This->stateBlock->vertexDecl != NULL) {
1751 TRACE("================ Vertex Declaration ===================\n");
1752 primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1754 TRACE("================ FVF ===================\n");
1755 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1758 /* write out some debug information*/
1759 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
1761 FIXME("line %d, drawing using vertex shaders\n", __LINE__);
1764 /* Setup transform matrices and sort out */
1766 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1767 So make sure lighting is disabled. */
1768 isLightingOn = glIsEnabled(GL_LIGHTING);
1769 glDisable(GL_LIGHTING);
1770 checkGLcall("glDisable(GL_LIGHTING);");
1771 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1773 isLightingOn = primitiveInitState(iface,
1774 fvf & D3DFVF_XYZRHW,
1775 !(fvf & D3DFVF_NORMAL),
1776 useVertexShaderFunction);
1779 /* Now initialize the materials state */
1780 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1782 drawPrimitiveUploadTextures(This);
1784 /* Now draw the graphics to the screen */
1785 if (useVertexShaderFunction) {
1787 /* Ideally, we should have software FV and hardware VS, possibly
1788 depending on the device type? */
1791 TRACE("Swap HW vertex shader\n");
1792 #if 0 /* TODO: vertex and pixel shaders */
1793 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1794 idxData, idxSize, minIndex, StartIdx);
1797 /* We will have to use the very, very slow emulation layer */
1798 TRACE("Swap SW vertex shader\n");
1799 #if 0 /* TODO: vertex and pixel shaders */
1800 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1801 idxData, idxSize, minIndex, StartIdx);
1805 } else if ((dataLocations.u.s.pSize.lpData != NULL)
1806 || (dataLocations.u.s.diffuse.lpData != NULL)
1807 /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
1809 /* Fixme, Ideally, only use the per-vertex code for software HAL
1810 but until opengl supports all the functions returned to setup
1811 vertex arrays, we need to drop down to the slow mechanism for
1812 certain functions */
1814 /* We will have to use the slow version of GL per vertex setup */
1815 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1816 idxData, idxSize, minIndex, StartIdx);
1820 /* We can use the fast version of GL pointers */
1821 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1822 idxData, idxSize, minIndex, StartIdx);
1825 /* If vertex shaders or no normals, restore previous lighting state */
1826 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1827 if (isLightingOn) glEnable(GL_LIGHTING);
1828 else glDisable(GL_LIGHTING);
1829 TRACE("Restored lighting to original state\n");
1832 #if 0 /* TODO: vertex and pixel shaders */
1837 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1839 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1841 glDisable(GL_FRAGMENT_PROGRAM_ARB);
1845 /* Finshed updating the screen, restore lock */
1847 TRACE("Done all gl drawing\n");
1850 #if defined(SHOW_FRAME_MAKEUP)
1852 if (isDumpingFrames) {
1855 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1856 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1857 TRACE("Saving screenshot %s\n", buffer);
1858 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
1859 IWineD3DSurface_UnlockRect(This->renderTarget);
1861 #if defined(SHOW_TEXTURE_MAKEUP)
1863 IWineD3DSurface *pSur;
1865 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1866 if (This->stateBlock->textures[textureNo] != NULL) {
1867 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1868 TRACE("Saving texture %s\n", buffer);
1869 IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur);
1870 IWineD3DSurface_SaveSnapshot(pSur, buffer);
1871 IWineD3DSurface_Release(pSur);