Integrate hardware vertex shaders into the drawing pipeline.
[wine.git] / dlls / wined3d / drawprim.c
blob877cd69f2166cf3f3d169d3a99622039dffe1563
1 /*
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
24 #include "config.h"
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
31 #if 0 /* TODO */
32 extern IWineD3DVertexShaderImpl* VertexShaders[64];
33 extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
34 extern IWineD3DPixelShaderImpl* PixelShaders[64];
36 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
37 #endif
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
42 to stream 0 */
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
54 streams */
55 #endif
56 *FVFbits = This->stateBlock->fvf;
57 #if 0
58 *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
59 #endif
60 return FALSE;
63 /* Issues the glBegin call for gl given the primitive type and count */
64 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
65 DWORD NumPrimitives,
66 GLenum *primType)
68 DWORD NumVertexes = NumPrimitives;
70 switch (PrimitiveType) {
71 case D3DPT_POINTLIST:
72 TRACE("POINTS\n");
73 *primType = GL_POINTS;
74 NumVertexes = NumPrimitives;
75 break;
77 case D3DPT_LINELIST:
78 TRACE("LINES\n");
79 *primType = GL_LINES;
80 NumVertexes = NumPrimitives * 2;
81 break;
83 case D3DPT_LINESTRIP:
84 TRACE("LINE_STRIP\n");
85 *primType = GL_LINE_STRIP;
86 NumVertexes = NumPrimitives + 1;
87 break;
89 case D3DPT_TRIANGLELIST:
90 TRACE("TRIANGLES\n");
91 *primType = GL_TRIANGLES;
92 NumVertexes = NumPrimitives * 3;
93 break;
95 case D3DPT_TRIANGLESTRIP:
96 TRACE("TRIANGLE_STRIP\n");
97 *primType = GL_TRIANGLE_STRIP;
98 NumVertexes = NumPrimitives + 2;
99 break;
101 case D3DPT_TRIANGLEFAN:
102 TRACE("TRIANGLE_FAN\n");
103 *primType = GL_TRIANGLE_FAN;
104 NumVertexes = NumPrimitives + 2;
105 break;
107 default:
108 FIXME("Unhandled primitive\n");
109 *primType = GL_POINTS;
110 break;
112 return NumVertexes;
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");
162 } else {
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
206 mode. */
207 glMatrixMode(GL_MODELVIEW);
208 checkGLcall("glMatrixMode(GL_MODELVIEW)");
209 glLoadIdentity();
210 checkGLcall("glLoadIdentity");
212 glMatrixMode(GL_PROJECTION);
213 checkGLcall("glMatrixMode(GL_PROJECTION)");
214 glLoadIdentity();
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)");
238 } else {
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");
252 } else {
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)
272 instead. */
273 glLoadIdentity();
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
289 requested or not */
290 if (useVS) {
291 glMatrixMode(GL_MODELVIEW);
292 checkGLcall("glMatrixMode");
293 glLoadIdentity();
294 glMatrixMode(GL_PROJECTION);
295 checkGLcall("glMatrixMode");
296 glLoadIdentity();
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;
310 return isLightingOn;
313 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
314 /* We need to deal with frequency data!*/
316 int textureNo =0;
317 BYTE *data = NULL;
318 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
319 IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
320 int i;
321 D3DVERTEXELEMENT9 *element;
322 DWORD stride;
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];
330 } else {
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;
345 break;
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;
351 break;
353 break;
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;
360 break;
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;
366 break;
368 *fvf |= D3DFVF_NORMAL;
369 break;
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;
377 break;
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;
382 break;
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;
387 break;
388 case D3DDECLUSAGE_COLOR:
389 switch (element->UsageIndex) {
390 case 0:/* diffuse */
391 strided->u.s.diffuse.lpData = data;
392 strided->u.s.diffuse.dwType = element->Type;
393 strided->u.s.diffuse.dwStride = stride;
394 break;
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;
401 break;
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;
410 ++textureNo;
411 break;
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 */
416 TRACE("Tangents\n");
417 strided->u.s.tangent.lpData = data;
418 strided->u.s.tangent.dwType = element->Type;
419 strided->u.s.tangent.dwStride = stride;
420 break;
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;
430 break;
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;
438 break;
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;
446 break;
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;
455 break;
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 */
460 break;
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.
468 * */
469 TRACE("Fog\n");
470 strided->u.s.fog.lpData = data;
471 strided->u.s.fog.dwType = element->Type;
472 strided->u.s.fog.dwStride = stride;
473 break;
474 case D3DDECLUSAGE_DEPTH:
475 TRACE("depth\n");
476 strided->u.s.depth.lpData = data;
477 strided->u.s.depth.dwType = element->Type;
478 strided->u.s.depth.dwStride = stride;
479 break;
480 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
481 TRACE("depth\n");
482 strided->u.s.sample.lpData = data;
483 strided->u.s.sample.dwType = element->Type;
484 strided->u.s.sample.dwStride = stride;
485 break;
492 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
494 short LoopThroughTo = 0;
495 short nStream;
496 int numBlends;
497 int numTextures;
498 int textureNo;
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;
510 } else {
511 LoopThroughTo = 1;
514 /* Work through stream by stream */
515 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
516 DWORD stride = This->stateBlock->streamStride[nStream];
517 BYTE *data = NULL;
518 DWORD thisFVF = 0;
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];
529 } else {
530 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
532 } else {
533 #if 0 /* TODO: Vertex shader support */
534 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
535 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
536 #endif
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);
612 /* Texture coords */
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;
630 /* Always one set */
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;
660 float s, t, r, q;
661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
663 /* Diffuse -------------------------------- */
664 if (isDiffuse) {
665 glColor4fv(dRGBA);
666 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
669 /* Specular Colour ------------------------------------------*/
670 if (isSpecular) {
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]));
674 } else {
675 VTRACE(("Specular color extensions not supplied\n"));
679 /* Normal -------------------------------- */
680 if (isNormal) {
681 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
682 glNormal3f(nx, ny, nz);
685 /* Point Size ----------------------------------------------*/
686 if (isPtSize) {
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");
697 continue ;
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));
706 continue;
707 } else if (numcoords[coordIdx] == 0) {
708 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
709 continue;
710 } else {
712 /* Initialize vars */
713 s = 0.0f;
714 t = 0.0f;
715 r = 0.0f;
716 q = 0.0f;
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 */
726 case D3DTTFF_COUNT1:
727 VTRACE(("tex:%d, s=%f\n", textureNo, s));
728 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
729 GLMULTITEXCOORD1F(textureNo, s);
730 } else {
731 glTexCoord1f(s);
733 break;
734 case D3DTTFF_COUNT2:
735 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
736 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
737 GLMULTITEXCOORD2F(textureNo, s, t);
738 } else {
739 glTexCoord2f(s, t);
741 break;
742 case D3DTTFF_COUNT3:
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);
746 } else {
747 glTexCoord3f(s, t, r);
749 break;
750 case D3DTTFF_COUNT4:
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);
754 } else {
755 glTexCoord4f(s, t, r, q);
757 break;
758 default:
759 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
763 } /* End of textures */
765 /* Position -------------------------------- */
766 if (isXYZ) {
767 if (1.0f == rhw || rhw < 0.00001f) {
768 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
769 glVertex3f(x, y, z);
770 } else {
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 */
780 void loadNumberedArrays(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
783 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
784 if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
785 TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
786 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
787 WINED3D_ATR_SIZE(_arrayName), \
788 WINED3D_ATR_GLTYPE(_arrayName), \
789 WINED3D_ATR_NORMALIZED(_arrayName), \
790 sd->u.s._arrayName.dwStride, \
791 sd->u.s._arrayName.lpData)); \
792 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
796 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
797 if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
798 FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
799 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
800 WINED3D_ATR_SIZE(position2), \
801 WINED3D_ATR_GLTYPE(position2), \
802 WINED3D_ATR_NORMALIZED(position2), \
803 sd->u.s.position2.dwStride, \
804 ((char *)sd->u.s.position2.lpData) + \
805 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
806 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
809 /* Generate some lookup tables */
810 /* drop the RHW coord, there must be a nicer way of doing this. */
811 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
812 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
814 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
815 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
816 LOAD_NUMBERED_ARRAY(position,POSITION);
817 LOAD_NUMBERED_ARRAY(normal,NORMAL);
818 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
819 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
820 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
821 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
822 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
823 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
824 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
825 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
826 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
827 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
828 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
829 #if 0 /* TODO: Samplers may allow for more texture coords */
830 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
831 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
832 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
833 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
834 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
835 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
836 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
837 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
838 #endif
839 LOAD_NUMBERED_ARRAY(position,POSITIONT);
840 /* d3d9 types */
841 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
842 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
843 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
844 LOAD_NUMBERED_ARRAY(position2,POSITION2);
845 /* there can be lots of position arrays */
846 LOAD_NUMBERED_POSITION_ARRAY(0);
847 LOAD_NUMBERED_POSITION_ARRAY(1);
848 LOAD_NUMBERED_POSITION_ARRAY(2);
849 LOAD_NUMBERED_POSITION_ARRAY(3);
850 LOAD_NUMBERED_POSITION_ARRAY(4);
851 LOAD_NUMBERED_POSITION_ARRAY(5);
852 LOAD_NUMBERED_POSITION_ARRAY(6);
853 LOAD_NUMBERED_POSITION_ARRAY(7);
854 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
855 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
856 LOAD_NUMBERED_ARRAY(fog,FOG);
857 LOAD_NUMBERED_ARRAY(depth,DEPTH);
858 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
860 #undef LOAD_NUMBERED_ARRAY
863 static void loadVertexData(IWineD3DDevice *iface, Direct3DVertexStridedData *sd) {
864 unsigned int textureNo = 0;
865 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
867 TRACE("Using fast vertex array code\n");
868 /* Blend Data ---------------------------------------------- */
869 if ((sd->u.s.blendWeights.lpData != NULL) ||
870 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
873 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
875 #if 1
876 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
877 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
878 #endif
880 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
881 /* FIXME("TODO\n");*/
882 /* Note dwType == float3 or float4 == 2 or 3 */
884 #if 0
885 /* with this on, the normals appear to be being modified,
886 but the vertices aren't being translated as they should be
887 Maybe the world matrix aren't being setup properly? */
888 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
889 #endif
892 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
893 WINED3D_ATR_SIZE(blendWeights) ,
894 sd->u.s.blendWeights.dwStride,
895 sd->u.s.blendWeights.lpData));
897 GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
898 sd->u.s.blendWeights.dwStride,
899 sd->u.s.blendWeights.lpData);
901 checkGLcall("glWeightPointerARB");
903 if(sd->u.s.blendMatrixIndices.lpData != NULL){
904 static BOOL showfixme = TRUE;
905 if(showfixme){
906 FIXME("blendMatrixIndices support\n");
907 showfixme = FALSE;
913 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
914 /* FIXME("TODO\n");*/
915 #if 0
917 GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
918 sd->u.s.blendWeights.dwStride,
919 sd->u.s.blendWeights.lpData);
920 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
921 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
922 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
923 #endif
925 } else {
926 /* TODO: support blends in fixupVertices */
927 FIXME("unsupported blending in openGl\n");
929 } else {
930 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
931 #if 0 /* TODO: Vertex blending */
932 glDisable(GL_VERTEX_BLEND_ARB);
933 #endif
934 TRACE("ARB_VERTEX_BLEND \n");
935 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
936 TRACE(" EXT_VERTEX_WEIGHTING\n");
937 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
938 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
943 #if 0 /* FOG ----------------------------------------------*/
944 if (sd->u.s.fog.lpData != NULL) {
945 /* TODO: fog*/
946 if (GL_SUPPORT(EXT_FOG_COORD) {
947 glEnableClientState(GL_FOG_COORD_EXT);
948 (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
949 sd->u.s.fog.dwStride,
950 sd->u.s.fog.lpData);
951 } else {
952 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
953 /* FIXME: fixme once */
954 TRACE("Hardware support for FOG is not avaiable, FOG disabled. \n");
956 } else {
957 if (GL_SUPPRT(EXT_FOR_COORD) {
958 /* make sure fog is disabled */
959 glDisableClientState(GL_FOG_COORD_EXT);
962 #endif
964 #if 0 /* tangents ----------------------------------------------*/
965 if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
966 /* TODO: tangents*/
967 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
968 if (sd->u.s.tangent.lpData != NULL) {
969 glEnable(GL_TANGENT_ARRAY_EXT);
970 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
971 sd->u.s.tangent.dwStride,
972 sd->u.s.tangent.lpData);
973 } else {
974 glDisable(GL_TANGENT_ARRAY_EXT);
976 if (sd->u.s.binormal.lpData != NULL) {
977 glEnable(GL_BINORMAL_ARRAY_EXT);
978 (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
979 sd->u.s.binormal.dwStride,
980 sd->u.s.binormal.lpData);
981 } else{
982 glDisable(GL_BINORMAL_ARRAY_EXT);
985 } else {
986 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
987 /* FIXME: fixme once */
988 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled. \n");
990 } else {
991 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
992 /* make sure fog is disabled */
993 glDisable(GL_TANGENT_ARRAY_EXT);
994 glDisable(GL_BINORMAL_ARRAY_EXT);
997 #endif
999 /* Point Size ----------------------------------------------*/
1000 if (sd->u.s.pSize.lpData != NULL) {
1002 /* no such functionality in the fixed function GL pipeline */
1003 TRACE("Cannot change ptSize here in openGl\n");
1004 /* TODO: Implement this function in using shaders if they are available */
1008 /* Vertex Pointers -----------------------------------------*/
1009 if (sd->u.s.position.lpData != NULL) {
1010 /* Note dwType == float3 or float4 == 2 or 3 */
1011 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1012 sd->u.s.position.dwStride,
1013 sd->u.s.position.dwType + 1,
1014 sd->u.s.position.lpData));
1016 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1017 handling for rhw mode should not impact screen position whereas in GL it does.
1018 This may result in very slightly distored textures in rhw mode, but
1019 a very minimal different. There's always the other option of
1020 fixing the view matrix to prevent w from having any effect */
1021 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1022 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1023 checkGLcall("glVertexPointer(...)");
1024 glEnableClientState(GL_VERTEX_ARRAY);
1025 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1027 } else {
1028 glDisableClientState(GL_VERTEX_ARRAY);
1029 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1032 /* Normals -------------------------------------------------*/
1033 if (sd->u.s.normal.lpData != NULL) {
1034 /* Note dwType == float3 or float4 == 2 or 3 */
1035 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1036 sd->u.s.normal.dwStride,
1037 sd->u.s.normal.lpData));
1038 glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1039 sd->u.s.normal.dwStride,
1040 sd->u.s.normal.lpData);
1041 checkGLcall("glNormalPointer(...)");
1042 glEnableClientState(GL_NORMAL_ARRAY);
1043 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1045 } else {
1046 glDisableClientState(GL_NORMAL_ARRAY);
1047 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1048 glNormal3f(0, 0, 1);
1049 checkGLcall("glNormal3f(0, 0, 1)");
1052 /* Diffuse Colour --------------------------------------------*/
1053 /* WARNING: Data here MUST be in RGBA format, so cannot */
1054 /* go directly into fast mode from app pgm, because */
1055 /* directx requires data in BGRA format. */
1056 /* currently fixupVertices swizels the format, but this isn't */
1057 /* very practical when using VBOS */
1058 /* NOTE: Unless we write a vertex shader to swizel the colour */
1059 /* , or the user doesn't care and wants the speed advantage */
1061 if (sd->u.s.diffuse.lpData != NULL) {
1062 /* Note dwType == float3 or float4 == 2 or 3 */
1063 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1064 sd->u.s.diffuse.dwStride,
1065 sd->u.s.diffuse.lpData));
1067 glColorPointer(4, GL_UNSIGNED_BYTE,
1068 sd->u.s.diffuse.dwStride,
1069 sd->u.s.diffuse.lpData);
1070 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1071 glEnableClientState(GL_COLOR_ARRAY);
1072 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1074 } else {
1075 glDisableClientState(GL_COLOR_ARRAY);
1076 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1077 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1078 checkGLcall("glColor4f(1, 1, 1, 1)");
1081 /* Specular Colour ------------------------------------------*/
1082 if (sd->u.s.specular.lpData != NULL) {
1083 TRACE("setting specular colour\n");
1084 /* Note dwType == float3 or float4 == 2 or 3 */
1085 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1086 sd->u.s.specular.dwStride,
1087 sd->u.s.specular.lpData));
1088 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1089 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1090 sd->u.s.specular.dwStride,
1091 sd->u.s.specular.lpData);
1092 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1093 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1094 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1095 } else {
1097 /* Missing specular color is not critical, no warnings */
1098 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1101 } else {
1102 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1104 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1105 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1106 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1107 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1108 } else {
1110 /* Missing specular color is not critical, no warnings */
1111 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1115 /* Texture coords -------------------------------------------*/
1117 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1119 /* Select the correct texture stage */
1120 GLCLIENTACTIVETEXTURE(textureNo);
1121 if (This->stateBlock->textures[textureNo] != NULL) {
1122 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1123 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1124 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1125 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1126 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1127 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1128 continue;
1131 if (coordIdx >= MAX_TEXTURES) {
1132 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1133 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1134 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1136 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1137 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1138 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1139 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1141 } else {
1143 /* The coords to supply depend completely on the fvf / vertex shader */
1144 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1145 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1148 } else {
1149 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1150 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1155 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1156 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1159 if (idxData != NULL /* This crashes sometimes!*/) {
1160 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1161 idxData = idxData == (void *)-1 ? NULL : idxData;
1162 #if 1
1163 #if 0
1164 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1165 glEnableClientState(GL_INDEX_ARRAY);
1166 #endif
1167 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1168 (const char *)idxData+(idxSize * startIdx));
1169 #else /* using drawRangeElements may be faster */
1171 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1172 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1173 (const char *)idxData+(idxSize * startIdx));
1174 #endif
1175 checkGLcall("glDrawRangeElements");
1177 } else {
1179 /* Note first is now zero as we shuffled along earlier */
1180 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1181 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1182 checkGLcall("glDrawArrays");
1186 return;
1190 * Actually draw using the supplied information.
1191 * Slower GL version which extracts info about each vertex in turn
1194 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1195 UINT NumVertexes, GLenum glPrimType,
1196 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1198 unsigned int textureNo = 0;
1199 const short *pIdxBufS = NULL;
1200 const long *pIdxBufL = NULL;
1201 LONG SkipnStrides = 0;
1202 LONG vx_index;
1203 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1204 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1205 float rhw = 0.0f; /* rhw */
1206 float ptSize = 0.0f; /* Point size */
1207 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1208 DWORD specularColor = 0; /* Specular Color */
1209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1211 TRACE("Using slow vertex array code\n");
1213 /* Variable Initialization */
1214 if (idxData != NULL) {
1215 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1216 else pIdxBufL = (const long *) idxData;
1219 /* Start drawing in GL */
1220 VTRACE(("glBegin(%x)\n", glPrimType));
1221 glBegin(glPrimType);
1223 /* For each primitive */
1224 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1226 /* Initialize diffuse color */
1227 diffuseColor = 0xFFFFFFFF;
1229 /* For indexed data, we need to go a few more strides in */
1230 if (idxData != NULL) {
1232 /* Indexed so work out the number of strides to skip */
1233 if (idxSize == 2) {
1234 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1235 SkipnStrides = pIdxBufS[startIdx + vx_index];
1236 } else {
1237 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1238 SkipnStrides = pIdxBufL[startIdx + vx_index];
1242 /* Position Information ------------------ */
1243 if (sd->u.s.position.lpData != NULL) {
1245 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1246 x = ptrToCoords[0];
1247 y = ptrToCoords[1];
1248 z = ptrToCoords[2];
1249 rhw = 1.0;
1250 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1252 /* RHW follows, only if transformed, ie 4 floats were provided */
1253 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1254 rhw = ptrToCoords[3];
1255 VTRACE(("rhw=%f\n", rhw));
1259 /* Blending data -------------------------- */
1260 if (sd->u.s.blendWeights.lpData != NULL) {
1261 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1262 FIXME("Blending not supported yet\n");
1264 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1265 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1269 /* Vertex Normal Data (untransformed only)- */
1270 if (sd->u.s.normal.lpData != NULL) {
1272 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1273 nx = ptrToCoords[0];
1274 ny = ptrToCoords[1];
1275 nz = ptrToCoords[2];
1276 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1279 /* Point Size ----------------------------- */
1280 if (sd->u.s.pSize.lpData != NULL) {
1282 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1283 ptSize = ptrToCoords[0];
1284 VTRACE(("ptSize=%f\n", ptSize));
1285 FIXME("No support for ptSize yet\n");
1288 /* Diffuse -------------------------------- */
1289 if (sd->u.s.diffuse.lpData != NULL) {
1291 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1292 diffuseColor = ptrToCoords[0];
1293 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1296 /* Specular -------------------------------- */
1297 if (sd->u.s.specular.lpData != NULL) {
1299 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1300 specularColor = ptrToCoords[0];
1301 VTRACE(("specularColor=%lx\n", specularColor));
1304 /* Texture coords --------------------------- */
1305 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1307 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1308 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1309 continue ;
1312 /* Query tex coords */
1313 if (This->stateBlock->textures[textureNo] != NULL) {
1315 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1316 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1317 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1319 if (coordIdx > 7) {
1320 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1321 continue;
1322 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1323 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1324 continue;
1325 } else {
1327 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1329 /* The coords to supply depend completely on the fvf / vertex shader */
1330 switch (coordsToUse) {
1331 case 4: q = ptrToCoords[3]; /* drop through */
1332 case 3: r = ptrToCoords[2]; /* drop through */
1333 case 2: t = ptrToCoords[1]; /* drop through */
1334 case 1: s = ptrToCoords[0];
1337 /* Projected is more 'fun' - Move the last coord to the 'q'
1338 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1339 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1340 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1342 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1343 switch (coordsToUse) {
1344 case 0: /* Drop Through */
1345 case 1:
1346 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1347 break;
1348 case 2:
1349 q = t;
1350 t = 0.0;
1351 coordsToUse = 4;
1352 break;
1353 case 3:
1354 q = r;
1355 r = 0.0;
1356 coordsToUse = 4;
1357 break;
1358 case 4: /* Nop here */
1359 break;
1360 default:
1361 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1362 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1367 switch (coordsToUse) { /* Supply the provided texture coords */
1368 case D3DTTFF_COUNT1:
1369 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1370 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1371 GLMULTITEXCOORD1F(textureNo, s);
1372 } else {
1373 glTexCoord1f(s);
1375 break;
1376 case D3DTTFF_COUNT2:
1377 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1378 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1379 GLMULTITEXCOORD2F(textureNo, s, t);
1380 } else {
1381 glTexCoord2f(s, t);
1383 break;
1384 case D3DTTFF_COUNT3:
1385 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1386 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1387 GLMULTITEXCOORD3F(textureNo, s, t, r);
1388 } else {
1389 glTexCoord3f(s, t, r);
1391 break;
1392 case D3DTTFF_COUNT4:
1393 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1394 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1395 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1396 } else {
1397 glTexCoord4f(s, t, r, q);
1399 break;
1400 default:
1401 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1405 } /* End of textures */
1407 /* Diffuse -------------------------------- */
1408 if (sd->u.s.diffuse.lpData != NULL) {
1409 glColor4ub((diffuseColor >> 16) & 0xFF,
1410 (diffuseColor >> 8) & 0xFF,
1411 (diffuseColor >> 0) & 0xFF,
1412 (diffuseColor >> 24) & 0xFF);
1413 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1414 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1415 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1416 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1417 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1418 } else {
1419 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1422 /* Specular ------------------------------- */
1423 if (sd->u.s.diffuse.lpData != NULL) {
1424 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1425 ((specularColor >> 16) & 0xFF) / 255.0f,
1426 ((specularColor >> 8) & 0xFF) / 255.0f,
1427 ((specularColor >> 0) & 0xFF) / 255.0f));
1428 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1429 GL_EXTCALL(glSecondaryColor3ubEXT)(
1430 (specularColor >> 16) & 0xFF,
1431 (specularColor >> 8) & 0xFF,
1432 (specularColor >> 0) & 0xFF);
1433 } else {
1434 /* Do not worry if specular colour missing and disable request */
1435 VTRACE(("Specular color extensions not supplied\n"));
1437 } else {
1438 if (vx_index == 0) {
1439 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1440 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1441 } else {
1442 /* Do not worry if specular colour missing and disable request */
1443 VTRACE(("Specular color extensions not supplied\n"));
1448 /* Normal -------------------------------- */
1449 if (sd->u.s.normal.lpData != NULL) {
1450 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1451 glNormal3f(nx, ny, nz);
1452 } else {
1453 if (vx_index == 0) glNormal3f(0, 0, 1);
1456 /* Position -------------------------------- */
1457 if (sd->u.s.position.lpData != NULL) {
1458 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1459 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1460 glVertex3f(x, y, z);
1461 } else {
1462 GLfloat w = 1.0 / rhw;
1463 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1464 glVertex4f(x*w, y*w, z*w, w);
1468 /* For non indexed mode, step onto next parts */
1469 if (idxData == NULL) {
1470 ++SkipnStrides;
1474 glEnd();
1475 checkGLcall("glEnd and previous calls");
1478 #if 0 /* TODO: Software/Hardware vertex blending support */
1480 * Draw with emulated vertex shaders
1481 * Note: strided data is uninitialized, as we need to pass the vertex
1482 * shader directly as ordering irs yet
1484 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1485 int PrimitiveType, ULONG NumPrimitives,
1486 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1488 unsigned int textureNo = 0;
1489 GLenum glPrimType = GL_POINTS;
1490 int NumVertexes = NumPrimitives;
1491 const short *pIdxBufS = NULL;
1492 const long *pIdxBufL = NULL;
1493 LONG SkipnStrides = 0;
1494 LONG vx_index;
1495 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1496 float rhw = 0.0f; /* rhw */
1497 float ptSize = 0.0f; /* Point size */
1498 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1499 int numcoords[8]; /* Number of coords */
1500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1502 IDirect3DVertexShaderImpl* vertexShader = NULL;
1504 TRACE("Using slow software vertex shader code\n");
1506 /* Variable Initialization */
1507 if (idxData != NULL) {
1508 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1509 else pIdxBufL = (const long *) idxData;
1512 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1513 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1515 /* Retrieve the VS information */
1516 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1518 /* Start drawing in GL */
1519 VTRACE(("glBegin(%x)\n", glPrimType));
1520 glBegin(glPrimType);
1522 /* For each primitive */
1523 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1525 /* For indexed data, we need to go a few more strides in */
1526 if (idxData != NULL) {
1528 /* Indexed so work out the number of strides to skip */
1529 if (idxSize == 2) {
1530 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1531 SkipnStrides = pIdxBufS[startIdx+vx_index];
1532 } else {
1533 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1534 SkipnStrides = pIdxBufL[startIdx+vx_index];
1538 /* Fill the vertex shader input */
1539 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1541 /* Initialize the output fields to the same defaults as it would normally have */
1542 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1543 vertexShader->output.oD[0].x = 1.0;
1544 vertexShader->output.oD[0].y = 1.0;
1545 vertexShader->output.oD[0].z = 1.0;
1546 vertexShader->output.oD[0].w = 1.0;
1548 /* Now execute the vertex shader */
1549 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1552 TRACE_VECTOR(vertexShader->output.oPos);
1553 TRACE_VECTOR(vertexShader->output.oD[0]);
1554 TRACE_VECTOR(vertexShader->output.oD[1]);
1555 TRACE_VECTOR(vertexShader->output.oT[0]);
1556 TRACE_VECTOR(vertexShader->output.oT[1]);
1557 TRACE_VECTOR(vertexShader->input.V[0]);
1558 TRACE_VECTOR(vertexShader->data->C[0]);
1559 TRACE_VECTOR(vertexShader->data->C[1]);
1560 TRACE_VECTOR(vertexShader->data->C[2]);
1561 TRACE_VECTOR(vertexShader->data->C[3]);
1562 TRACE_VECTOR(vertexShader->data->C[4]);
1563 TRACE_VECTOR(vertexShader->data->C[5]);
1564 TRACE_VECTOR(vertexShader->data->C[6]);
1565 TRACE_VECTOR(vertexShader->data->C[7]);
1568 /* Extract out the output */
1569 /* FIXME: Fog coords? */
1570 x = vertexShader->output.oPos.x;
1571 y = vertexShader->output.oPos.y;
1572 z = vertexShader->output.oPos.z;
1573 rhw = vertexShader->output.oPos.w;
1574 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1576 /** Update textures coords using vertexShader->output.oT[0->7] */
1577 memset(texcoords, 0x00, sizeof(texcoords));
1578 memset(numcoords, 0x00, sizeof(numcoords));
1579 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1580 if (This->stateBlock->textures[textureNo] != NULL) {
1581 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1582 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1583 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1584 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1585 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1586 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1587 } else {
1588 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1589 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1590 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1591 default: numcoords[textureNo] = 4;
1594 } else {
1595 numcoords[textureNo] = 0;
1599 /* Draw using this information */
1600 draw_vertex(iface,
1601 TRUE, x, y, z, rhw,
1602 TRUE, 0.0f, 0.0f, 1.0f,
1603 TRUE, (float*) &vertexShader->output.oD[0],
1604 TRUE, (float*) &vertexShader->output.oD[1],
1605 FALSE, ptSize, /* FIXME: Change back when supported */
1606 texcoords, numcoords);
1608 /* For non indexed mode, step onto next parts */
1609 if (idxData == NULL) {
1610 ++SkipnStrides;
1613 } /* for each vertex */
1615 glEnd();
1616 checkGLcall("glEnd and previous calls");
1619 #endif
1621 void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1622 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1625 /* Now draw the graphics to the screen */
1626 if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1627 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1628 /* Ideally, we should have software FV and hardware VS, possibly
1629 depending on the device type? */
1630 #if 0 /* TODO: vertex and pixel shaders */
1631 drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1632 idxData, idxSize, minIndex, StartIdx);
1633 #endif
1635 } else {
1637 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1638 int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1639 int endStride = startStride;
1640 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1642 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1643 if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1644 int t;
1645 if (idxSize == 2) {
1646 unsigned short *index = (unsigned short *)idxData;
1647 index += StartIdx;
1648 for (t = 0 ; t < numberOfIndicies; t++) {
1649 if (startStride > *index)
1650 startStride = *index;
1651 if (endStride < *index)
1652 endStride = *index;
1653 index++;
1655 } else { /* idxSize == 4 */
1656 unsigned int *index = (unsigned int *)idxData;
1657 index += StartIdx;
1658 for (t = 0 ; t < numberOfIndicies; t++) {
1659 if (startStride > *index)
1660 startStride = *index;
1661 if (endStride < *index)
1662 endStride = *index;
1663 index++;
1666 } else {
1667 endStride += numberOfvertices -1;
1669 #endif
1670 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1671 /* pre-transform verticex */
1672 /* TODO: Caching, VBO's etc.. */
1674 /* Generate some fixme's if unsupported functionality is being used */
1675 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1676 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1677 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1678 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1680 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1681 FIXME("Tweening is only valid with vertex shaders\n");
1683 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1684 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1686 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1687 FIXME("Extended attributes are only valid with vertex shaders\n");
1689 #undef BUFFER_OR_DATA
1691 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1692 fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1693 #endif
1695 /* vertex shaders */
1697 /* If the only vertex data used by the shader is supported by OpenGL then*/
1698 if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
1699 && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
1700 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1702 /* Load the vertex data using named arrays */
1703 TRACE("(%p) Loading vertex data\n", This);
1704 loadVertexData(iface, dataLocations);
1706 } else /* Otherwise */
1707 if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1709 /* load the array data using ordinal mapping */
1710 loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1712 } else { /* If this happens we must drawStridedSlow later on */
1713 TRACE("Not loading vertex data\n");
1716 TRACE("Loaded arrays\n");
1718 if (useVertexShaderFunction) {
1719 int i;
1720 GLint errPos;
1722 FIXME("Using vertex shader\n");
1724 /* Bind the vertex program */
1725 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
1726 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1728 /* and enable gl vertex shaders */
1729 glEnable(GL_VERTEX_PROGRAM_ARB);
1730 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1731 TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
1733 /* Update the constants */
1734 for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1735 /* TODO: add support for Integer and Boolean constants */
1736 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1737 TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->vertexShaderConstantF[i *4 ], This->stateBlock->vertexShaderConstantF[i * 4 + 1], This->stateBlock->vertexShaderConstantF[i *4 + 2], This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
1738 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1740 /* TODO: Vertex Shader 8 constants*/
1742 /* always draw strided fast if a vertex shader is being used */
1743 drawStridedFast(iface, numberOfIndicies, glPrimType,
1744 idxData, idxSize, minIndex, StartIdx);
1746 /* check for any errors */
1747 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1748 if (errPos != -1) {
1749 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1752 /* disable any attribs */
1753 if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1754 GLint maxAttribs;
1755 int i;
1756 /* Leave all the attribs disabled */
1757 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1758 /* MESA does not support it right not */
1759 if (glGetError() != GL_NO_ERROR)
1760 maxAttribs = 16;
1761 for (i = 0; i < maxAttribs; i++) {
1762 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1763 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1767 /* Done */
1768 glDisable(GL_VERTEX_PROGRAM_ARB);
1769 } else {
1771 /* DirectX colours are in a different format to opengl colours
1772 so if diffuse or specular are used then we need to use drawStridedSlow
1773 to correct the colours */
1774 if ((dataLocations->u.s.pSize.lpData != NULL)
1775 || (dataLocations->u.s.diffuse.lpData != NULL)
1776 || (dataLocations->u.s.specular.lpData != NULL)) {
1777 /* TODO: replace drawStridedSlow with veretx fixups */
1778 #if 1
1780 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1781 idxData, idxSize, minIndex, StartIdx) ;
1784 * drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1785 * idxData, idxSize, minIndex, StartIdx);
1787 #endif
1788 } else {
1789 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1790 drawStridedFast(iface, numberOfIndicies, glPrimType,
1791 idxData, idxSize, minIndex, StartIdx);
1797 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1799 /* Dump out what parts we have supplied */
1800 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1801 TRACE_STRIDED((dataLocations), position);
1802 TRACE_STRIDED((dataLocations), blendWeights);
1803 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1804 TRACE_STRIDED((dataLocations), normal);
1805 TRACE_STRIDED((dataLocations), pSize);
1806 TRACE_STRIDED((dataLocations), diffuse);
1807 TRACE_STRIDED((dataLocations), specular);
1808 TRACE_STRIDED((dataLocations), texCoords[0]);
1809 TRACE_STRIDED((dataLocations), texCoords[1]);
1810 TRACE_STRIDED((dataLocations), texCoords[2]);
1811 TRACE_STRIDED((dataLocations), texCoords[3]);
1812 TRACE_STRIDED((dataLocations), texCoords[4]);
1813 TRACE_STRIDED((dataLocations), texCoords[5]);
1814 TRACE_STRIDED((dataLocations), texCoords[6]);
1815 TRACE_STRIDED((dataLocations), texCoords[7]);
1816 TRACE_STRIDED((dataLocations), position2);
1817 TRACE_STRIDED((dataLocations), normal2);
1818 TRACE_STRIDED((dataLocations), tangent);
1819 TRACE_STRIDED((dataLocations), binormal);
1820 TRACE_STRIDED((dataLocations), tessFactor);
1821 TRACE_STRIDED((dataLocations), fog);
1822 TRACE_STRIDED((dataLocations), depth);
1823 TRACE_STRIDED((dataLocations), sample);
1825 return;
1829 /* uploads textures and setup texture states ready for rendering */
1830 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1832 unsigned int i;
1834 * OK, here we clear down any old junk iect in the context
1835 * enable the new texture and apply any state changes:
1837 * Loop through all textures
1838 * select texture unit
1839 * if there is a texture bound to that unit then..
1840 * disable all textures types on that unit
1841 * enable and bind the texture that is bound to that unit.
1842 * otherwise disable all texture types on that unit.
1844 /* upload the textures */
1845 for (i = 0; i< GL_LIMITS(textures); ++i) {
1846 /* Bind the texture to the stage here */
1847 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1848 GLACTIVETEXTURE(i);
1849 } else if (0 < i) {
1850 /* This isn't so much a warn as a message to the user about lack of hardware support */
1851 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1854 /* don't bother with textures that have a colorop of disable */
1855 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1856 if (This->stateBlock->textures[i] != NULL) {
1858 glDisable(GL_TEXTURE_1D);
1859 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1860 /* disable all texture states that aren't the selected textures' dimension */
1861 switch(This->stateBlock->textureDimensions[i]) {
1862 case GL_TEXTURE_2D:
1863 glDisable(GL_TEXTURE_3D);
1864 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1865 break;
1866 case GL_TEXTURE_3D:
1867 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1868 glDisable(GL_TEXTURE_2D);
1869 break;
1870 case GLTEXTURECUBEMAP:
1871 glDisable(GL_TEXTURE_2D);
1872 glDisable(GL_TEXTURE_3D);
1873 break;
1875 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1876 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1877 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1878 } else {
1879 glEnable(This->stateBlock->textureDimensions[i]);
1881 /* Load up the texture now */
1882 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1883 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1884 /* this is a stub function representing the state blocks
1885 * being separated here we are only updating the texture
1886 * state changes, other objects and units get updated when
1887 * they change (or need to be updated), e.g. states that
1888 * relate to a context member line the texture unit are
1889 * only updated when the context needs updating
1891 /* Tell the abse texture to sync it's states */
1892 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1895 /* Bind a default texture if no texture has been set, but colour-op is enabled */
1896 else {
1897 glDisable(GL_TEXTURE_2D);
1898 glDisable(GL_TEXTURE_3D);
1899 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1900 glEnable(GL_TEXTURE_1D);
1901 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1902 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1904 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1905 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1906 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1907 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1908 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1909 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1910 /* alphaop */
1911 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1912 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1913 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1914 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1915 } else {
1917 /* no colorop so disable all the texture states */
1918 glDisable(GL_TEXTURE_1D);
1919 glDisable(GL_TEXTURE_2D);
1920 glDisable(GL_TEXTURE_3D);
1921 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1928 /* Routine common to the draw primitive and draw indexed primitive routines */
1929 void drawPrimitive(IWineD3DDevice *iface,
1930 int PrimitiveType,
1931 long NumPrimitives,
1932 /* for Indexed: */
1933 long StartVertexIndex,
1934 UINT numberOfVertices,
1935 long StartIdx,
1936 short idxSize,
1937 const void *idxData,
1938 int minIndex) {
1940 BOOL rc = FALSE;
1941 DWORD fvf = 0;
1942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1943 BOOL useVertexShaderFunction = FALSE;
1944 BOOL isLightingOn = FALSE;
1945 Direct3DVertexStridedData dataLocations;
1946 int useHW = FALSE;
1948 useVertexShaderFunction = This->stateBlock->vertexShader != NULL ? wined3d_settings.vs_mode != VS_NONE ? ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->function != NULL ? TRUE: FALSE : FALSE : FALSE;
1950 if (This->stateBlock->vertexDecl == NULL) {
1951 /* Work out what the FVF should look like */
1952 rc = initializeFVF(iface, &fvf);
1953 if (rc) return;
1954 } else {
1955 TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1958 /* Ok, we will be updating the screen from here onwards so grab the lock */
1959 ENTER_GL();
1961 #if 0 /* TODO: vertex and pixel shaders */
1962 /* If we will be using a pixel, do some initialization for it */
1963 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1964 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1965 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1967 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1968 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1969 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1970 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1972 /* init Constants */
1973 if (This->stateBlock->Changed.pixelShaderConstant) {
1974 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1975 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1977 /* Update the constants */
1978 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1979 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1980 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1983 #endif /* TODO: vertex and pixel shaders */
1985 /* Initialize all values to null */
1986 memset(&dataLocations, 0x00, sizeof(dataLocations));
1987 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
1989 if (This->stateBlock->vertexDecl != NULL) {
1990 TRACE("================ Vertex Declaration ===================\n");
1991 primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1992 } else {
1993 TRACE("================ FVF ===================\n");
1994 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1997 /* write out some debug information*/
1998 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
2000 /* Setup transform matrices and sort out */
2001 if (useHW) {
2002 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2003 So make sure lighting is disabled. */
2004 isLightingOn = glIsEnabled(GL_LIGHTING);
2005 glDisable(GL_LIGHTING);
2006 checkGLcall("glDisable(GL_LIGHTING);");
2007 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2008 } else {
2009 isLightingOn = primitiveInitState(iface,
2010 fvf & D3DFVF_XYZRHW,
2011 !(fvf & D3DFVF_NORMAL),
2012 useVertexShaderFunction);
2015 /* Now initialize the materials state */
2016 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2018 drawPrimitiveUploadTextures(This);
2022 GLenum glPrimType;
2023 /* Ok, Work out which primitive is requested and how many vertexes that
2024 will be */
2025 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2026 #if 0 /* debugging code... just information not an error */
2027 if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2028 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2030 #endif
2031 if (numberOfVertices == 0 )
2032 numberOfVertices = calculatedNumberOfindices;
2033 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2036 /* If vertex shaders or no normals, restore previous lighting state */
2037 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2038 if (isLightingOn) glEnable(GL_LIGHTING);
2039 else glDisable(GL_LIGHTING);
2040 TRACE("Restored lighting to original state\n");
2043 #if 0 /* TODO: vertex and pixel shaders */
2044 if (pixel_shader)
2046 #if 0
2047 GLint errPos;
2048 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2049 if (errPos != -1)
2050 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2051 #endif
2052 glDisable(GL_FRAGMENT_PROGRAM_ARB);
2054 #endif
2056 /* Finshed updating the screen, restore lock */
2057 LEAVE_GL();
2058 TRACE("Done all gl drawing\n");
2060 /* Diagnostics */
2061 #if defined(SHOW_FRAME_MAKEUP)
2063 if (isDumpingFrames) {
2064 D3DLOCKED_RECT r;
2065 char buffer[80];
2066 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
2067 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
2068 TRACE("Saving screenshot %s\n", buffer);
2069 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2070 IWineD3DSurface_UnlockRect(This->renderTarget);
2072 #if defined(SHOW_TEXTURE_MAKEUP)
2074 IWineD3DSurface *pSur;
2075 int textureNo;
2076 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2077 if (This->stateBlock->textures[textureNo] != NULL) {
2078 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
2079 TRACE("Saving texture %s\n", buffer);
2080 IWineD3DTexture_GetSurfaceLevel(This->stateBlock->textures[textureNo], 0, &pSur);
2081 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2082 IWineD3DSurface_Release(pSur);
2086 #endif
2087 ++primCounter;
2090 #endif