Release 20050930.
[wine/gsoc-2012-control.git] / dlls / wined3d / drawprim.c
blobb4b67240f9192aa7389ede479cd58045dcba47b9
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 #ifdef SHOW_FRAME_MAKEUP
32 #include <stdio.h>
33 #endif
35 #if 0 /* TODO */
36 extern IWineD3DVertexShaderImpl* VertexShaders[64];
37 extern IWineD3DVertexDeclarationImpl* VertexShaderDeclarations[64];
38 extern IWineD3DPixelShaderImpl* PixelShaders[64];
40 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
41 #endif
43 /* Returns bits for what is expected from the fixed function pipeline, and whether
44 a vertex shader will be in use. Note the fvf bits returned may be split over
45 multiple streams only if the vertex shader was created, otherwise it all relates
46 to stream 0 */
47 static BOOL initializeFVF(IWineD3DDevice *iface, DWORD *FVFbits)
50 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
52 #if 0 /* TODO: d3d8 call setvertexshader needs to set the FVF in the state block when implemented */
53 /* The first thing to work out is if we are using the fixed function pipeline
54 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
55 is the FVF, or with a shader which was created with no function - in which
56 case there is an FVF per declared stream. If this occurs, we also maintain
57 an 'OR' of all the FVF's together so we know what to expect across all the
58 streams */
59 #endif
60 *FVFbits = This->stateBlock->fvf;
61 #if 0
62 *FVFbits = This->stateBlock->vertexShaderDecl->allFVF;
63 #endif
64 return FALSE;
67 /* Issues the glBegin call for gl given the primitive type and count */
68 static DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
69 DWORD NumPrimitives,
70 GLenum *primType)
72 DWORD NumVertexes = NumPrimitives;
74 switch (PrimitiveType) {
75 case D3DPT_POINTLIST:
76 TRACE("POINTS\n");
77 *primType = GL_POINTS;
78 NumVertexes = NumPrimitives;
79 break;
81 case D3DPT_LINELIST:
82 TRACE("LINES\n");
83 *primType = GL_LINES;
84 NumVertexes = NumPrimitives * 2;
85 break;
87 case D3DPT_LINESTRIP:
88 TRACE("LINE_STRIP\n");
89 *primType = GL_LINE_STRIP;
90 NumVertexes = NumPrimitives + 1;
91 break;
93 case D3DPT_TRIANGLELIST:
94 TRACE("TRIANGLES\n");
95 *primType = GL_TRIANGLES;
96 NumVertexes = NumPrimitives * 3;
97 break;
99 case D3DPT_TRIANGLESTRIP:
100 TRACE("TRIANGLE_STRIP\n");
101 *primType = GL_TRIANGLE_STRIP;
102 NumVertexes = NumPrimitives + 2;
103 break;
105 case D3DPT_TRIANGLEFAN:
106 TRACE("TRIANGLE_FAN\n");
107 *primType = GL_TRIANGLE_FAN;
108 NumVertexes = NumPrimitives + 2;
109 break;
111 default:
112 FIXME("Unhandled primitive\n");
113 *primType = GL_POINTS;
114 break;
116 return NumVertexes;
119 /* Ensure the appropriate material states are set up - only change
120 state if really required */
121 static void init_materials(IWineD3DDevice *iface, BOOL isDiffuseSupplied) {
123 BOOL requires_material_reset = FALSE;
124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
126 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied) {
127 /* If we have not set up the material color tracking, do it now as required */
128 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
129 checkGLcall("glDisable GL_COLOR_MATERIAL");
130 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
131 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
132 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
133 glEnable(GL_COLOR_MATERIAL);
134 checkGLcall("glEnable GL_COLOR_MATERIAL");
135 This->tracking_color = IS_TRACKING;
136 requires_material_reset = TRUE; /* Restore material settings as will be used */
138 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
139 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
140 /* If we are tracking the current color but one isn't supplied, don't! */
141 glDisable(GL_COLOR_MATERIAL);
142 checkGLcall("glDisable GL_COLOR_MATERIAL");
143 This->tracking_color = NEEDS_TRACKING;
144 requires_material_reset = TRUE; /* Restore material settings as will be used */
146 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied) {
147 /* No need to reset material colors since no change to gl_color_material */
148 requires_material_reset = FALSE;
150 } else if (This->tracking_color == NEEDS_DISABLE) {
151 glDisable(GL_COLOR_MATERIAL);
152 checkGLcall("glDisable GL_COLOR_MATERIAL");
153 This->tracking_color = DISABLED_TRACKING;
154 requires_material_reset = TRUE; /* Restore material settings as will be used */
157 /* Reset the material colors which may have been tracking the color*/
158 if (requires_material_reset) {
159 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->stateBlock->material.Ambient);
160 checkGLcall("glMaterialfv");
161 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->stateBlock->material.Diffuse);
162 checkGLcall("glMaterialfv");
163 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
164 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->stateBlock->material.Specular);
165 checkGLcall("glMaterialfv");
166 } else {
167 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
168 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
169 checkGLcall("glMaterialfv");
171 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->stateBlock->material.Emissive);
172 checkGLcall("glMaterialfv");
177 static GLfloat invymat[16] = {
178 1.0f, 0.0f, 0.0f, 0.0f,
179 0.0f, -1.0f, 0.0f, 0.0f,
180 0.0f, 0.0f, 1.0f, 0.0f,
181 0.0f, 0.0f, 0.0f, 1.0f};
183 /* Setup views - Transformed & lit if RHW, else untransformed.
184 Only unlit if Normals are supplied
185 Returns: Whether to restore lighting afterwards */
186 static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
188 BOOL isLightingOn = FALSE;
189 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
191 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
192 set by the appropriate render state. Note Vertex Shader output is already lit */
193 if (vtx_lit || useVS) {
194 isLightingOn = glIsEnabled(GL_LIGHTING);
195 glDisable(GL_LIGHTING);
196 checkGLcall("glDisable(GL_LIGHTING);");
197 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
200 if (!useVS && vtx_transformed) {
202 /* If the last draw was transformed as well, no need to reapply all the matrixes */
203 if (!This->last_was_rhw) {
205 double X, Y, height, width, minZ, maxZ;
206 This->last_was_rhw = TRUE;
208 /* Transformed already into viewport coordinates, so we do not need transform
209 matrices. Reset all matrices to identity and leave the default matrix in world
210 mode. */
211 glMatrixMode(GL_MODELVIEW);
212 checkGLcall("glMatrixMode(GL_MODELVIEW)");
213 glLoadIdentity();
214 checkGLcall("glLoadIdentity");
216 glMatrixMode(GL_PROJECTION);
217 checkGLcall("glMatrixMode(GL_PROJECTION)");
218 glLoadIdentity();
219 checkGLcall("glLoadIdentity");
221 /* Set up the viewport to be full viewport */
222 X = This->stateBlock->viewport.X;
223 Y = This->stateBlock->viewport.Y;
224 height = This->stateBlock->viewport.Height;
225 width = This->stateBlock->viewport.Width;
226 minZ = This->stateBlock->viewport.MinZ;
227 maxZ = This->stateBlock->viewport.MaxZ;
228 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
229 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
230 checkGLcall("glOrtho");
232 /* Window Coord 0 is the middle of the first pixel, so translate by half
233 a pixel (See comment above glTranslate below) */
234 glTranslatef(0.5, 0.5, 0);
235 checkGLcall("glTranslatef(0.5, 0.5, 0)");
236 if (This->renderUpsideDown) {
237 glMultMatrixf(invymat);
238 checkGLcall("glMultMatrixf(invymat)");
242 } else {
244 /* Untransformed, so relies on the view and projection matrices */
246 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
247 /* Only reapply when have to */
248 This->modelview_valid = TRUE;
249 glMatrixMode(GL_MODELVIEW);
250 checkGLcall("glMatrixMode");
252 /* In the general case, the view matrix is the identity matrix */
253 if (This->view_ident) {
254 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
255 checkGLcall("glLoadMatrixf");
256 } else {
257 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
258 checkGLcall("glLoadMatrixf");
259 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
260 checkGLcall("glMultMatrixf");
264 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
265 /* Only reapply when have to */
266 This->proj_valid = TRUE;
267 glMatrixMode(GL_PROJECTION);
268 checkGLcall("glMatrixMode");
270 /* The rule is that the window coordinate 0 does not correspond to the
271 beginning of the first pixel, but the center of the first pixel.
272 As a consequence if you want to correctly draw one line exactly from
273 the left to the right end of the viewport (with all matrices set to
274 be identity), the x coords of both ends of the line would be not
275 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
276 instead. */
277 glLoadIdentity();
279 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
280 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
282 if (This->renderUpsideDown) {
283 glMultMatrixf(invymat);
284 checkGLcall("glMultMatrixf(invymat)");
286 glMultMatrixf((float *) &This->stateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
287 checkGLcall("glLoadMatrixf");
290 /* Vertex Shader output is already transformed, so set up identity matrices */
291 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
292 come along this needs to take into account whether s/w ones were
293 requested or not */
294 if (useVS) {
295 glMatrixMode(GL_MODELVIEW);
296 checkGLcall("glMatrixMode");
297 glLoadIdentity();
298 glMatrixMode(GL_PROJECTION);
299 checkGLcall("glMatrixMode");
300 glLoadIdentity();
301 /* Window Coord 0 is the middle of the first pixel, so translate by half
302 a pixel (See comment above glTranslate above) */
303 glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
304 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
305 if (This->renderUpsideDown) {
306 glMultMatrixf(invymat);
307 checkGLcall("glMultMatrixf(invymat)");
309 This->modelview_valid = FALSE;
310 This->proj_valid = FALSE;
312 This->last_was_rhw = FALSE;
314 return isLightingOn;
317 void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex, DWORD *fvf) {
318 /* We need to deal with frequency data!*/
320 int textureNo =0;
321 BYTE *data = NULL;
322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
323 IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*)This->stateBlock->vertexDecl;
324 int i;
325 D3DVERTEXELEMENT9 *element;
326 DWORD stride;
327 for (i = 0 ; i < vertexDeclaration->declaration9NumElements - 1; ++i) {
329 element = vertexDeclaration->pDeclaration9 + i;
330 TRACE("%p Elements %p %d or %d\n", vertexDeclaration->pDeclaration9, element, i, vertexDeclaration->declaration9NumElements);
331 if (This->stateBlock->streamIsUP) {
332 TRACE("Stream is up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
333 data = (BYTE *)This->stateBlock->streamSource[element->Stream];
334 } else {
335 TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
336 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0);
338 stride = This->stateBlock->streamStride[element->Stream];
339 data += (BaseVertexIndex * stride);
340 data += element->Offset;
341 /* Why can't I just use a lookup table instead of a switch statment? */
342 switch (element->Usage) {
343 case D3DDECLUSAGE_POSITION:
344 switch (element->UsageIndex) {
345 case 0: /* N-patch */
346 strided->u.s.position.lpData = data;
347 strided->u.s.position.dwType = element->Type;
348 strided->u.s.position.dwStride = stride;
349 break;
350 case 1: /* tweened see http://www.gamedev.net/reference/articles/article2017.asp */
351 TRACE("Tweened positions\n");
352 strided->u.s.position2.lpData = data;
353 strided->u.s.position2.dwType = element->Type;
354 strided->u.s.position2.dwStride = stride;
355 break;
357 break;
358 case D3DDECLUSAGE_NORMAL:
359 switch (element->UsageIndex) {
360 case 0: /* N-patch */
361 strided->u.s.normal.lpData = data;
362 strided->u.s.normal.dwType = element->Type;
363 strided->u.s.normal.dwStride = stride;
364 break;
365 case 1: /* skinning */
366 TRACE("Skinning / tween normals\n");
367 strided->u.s.normal2.lpData = data;
368 strided->u.s.normal2.dwType = element->Type;
369 strided->u.s.normal2.dwStride = stride;
370 break;
372 *fvf |= D3DFVF_NORMAL;
373 break;
374 case D3DDECLUSAGE_BLENDINDICES:
375 /* demo @http://www.ati.com/developer/vertexblend.html
376 and http://www.flipcode.com/articles/article_dx8shaders.shtml
378 strided->u.s.blendMatrixIndices.lpData = data;
379 strided->u.s.blendMatrixIndices.dwType = element->Type;
380 strided->u.s.blendMatrixIndices.dwStride= stride;
381 break;
382 case D3DDECLUSAGE_BLENDWEIGHT:
383 strided->u.s.blendWeights.lpData = data;
384 strided->u.s.blendWeights.dwType = element->Type;
385 strided->u.s.blendWeights.dwStride = stride;
386 break;
387 case D3DDECLUSAGE_PSIZE:
388 strided->u.s.pSize.lpData = data;
389 strided->u.s.pSize.dwType = element->Type;
390 strided->u.s.pSize.dwStride = stride;
391 break;
392 case D3DDECLUSAGE_COLOR:
393 switch (element->UsageIndex) {
394 case 0:/* diffuse */
395 strided->u.s.diffuse.lpData = data;
396 strided->u.s.diffuse.dwType = element->Type;
397 strided->u.s.diffuse.dwStride = stride;
398 break;
399 case 1: /* specular */
400 strided->u.s.specular.lpData = data;
401 strided->u.s.specular.dwType = element->Type;
402 strided->u.s.specular.dwStride = stride;
405 break;
406 case D3DDECLUSAGE_TEXCOORD:
407 /* For some odd reason Microsoft decided to sum usage accross all the streams,
408 which means we need to do a count and not just use the usage number */
410 strided->u.s.texCoords[textureNo].lpData = data;
411 strided->u.s.texCoords[textureNo].dwType = element->Type;
412 strided->u.s.texCoords[textureNo].dwStride = stride;
414 ++textureNo;
415 break;
416 case D3DDECLUSAGE_TANGENT:
417 /* Implement tangents and binormals using http://oss.sgi.com/projects/ogl-sample/registry/EXT/coordinate_frame.txt
418 this is easy so long as the OpenGL implementation supports it, otherwise drop back to calculating the
419 normal using tangents where no normal data has been provided */
420 TRACE("Tangents\n");
421 strided->u.s.tangent.lpData = data;
422 strided->u.s.tangent.dwType = element->Type;
423 strided->u.s.tangent.dwStride = stride;
424 break;
425 case D3DDECLUSAGE_BINORMAL:
426 /* 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.
427 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)
428 The only thing they are useful for in fixed function would be working out normals when none are given.
430 TRACE("BI-Normal\n");
431 strided->u.s.binormal.lpData = data;
432 strided->u.s.binormal.dwType = element->Type;
433 strided->u.s.binormal.dwStride = stride;
434 break;
435 case D3DDECLUSAGE_TESSFACTOR:
436 /* a google for D3DDECLUSAGE_TESSFACTOR turns up a whopping 36 entries, 7 of which are from MSDN.
438 TRACE("Tess Factor\n");
439 strided->u.s.tessFactor.lpData = data;
440 strided->u.s.tessFactor.dwType = element->Type;
441 strided->u.s.tessFactor.dwStride = stride;
442 break;
443 case D3DDECLUSAGE_POSITIONT:
445 switch (element->UsageIndex) {
446 case 0: /* N-patch */
447 strided->u.s.position.lpData = data;
448 strided->u.s.position.dwType = element->Type;
449 strided->u.s.position.dwStride = stride;
450 break;
451 case 1: /* skinning */
452 /* see http://rsn.gamedev.net/tutorials/ms3danim.asp
453 http://xface.blogspot.com/2004_08_01_xface_archive.html
455 TRACE("Skinning positionsT\n");
456 strided->u.s.position2.lpData = data;
457 strided->u.s.position2.dwType = element->Type;
458 strided->u.s.position2.dwStride = stride;
459 break;
461 /* TODO: change fvf usage to a plain boolean flag */
462 *fvf |= D3DFVF_XYZRHW;
463 /* FIXME: were faking this flag so that we don't transform the data again */
464 break;
465 case D3DDECLUSAGE_FOG:
466 /* maybe GL_EXT_fog_coord ?
467 * http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt
468 * This extension allows specifying an explicit per-vertex fog
469 * coordinate to be used in fog computations, rather than using a
470 * fragment depth-based fog equation.
472 * */
473 TRACE("Fog\n");
474 strided->u.s.fog.lpData = data;
475 strided->u.s.fog.dwType = element->Type;
476 strided->u.s.fog.dwStride = stride;
477 break;
478 case D3DDECLUSAGE_DEPTH:
479 TRACE("depth\n");
480 strided->u.s.depth.lpData = data;
481 strided->u.s.depth.dwType = element->Type;
482 strided->u.s.depth.dwStride = stride;
483 break;
484 case D3DDECLUSAGE_SAMPLE: /* VertexShader textures */
485 TRACE("depth\n");
486 strided->u.s.sample.lpData = data;
487 strided->u.s.sample.dwType = element->Type;
488 strided->u.s.sample.dwStride = stride;
489 break;
496 static void primitiveConvertToStridedData(IWineD3DDevice *iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
498 short LoopThroughTo = 0;
499 short nStream;
500 int numBlends;
501 int numTextures;
502 int textureNo;
503 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
504 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
508 /* OK, Now to setup the data locations
509 For the non-created vertex shaders, the VertexShader var holds the real
510 FVF and only stream 0 matters
511 For the created vertex shaders, there is an FVF per stream */
512 if (!This->stateBlock->streamIsUP && !(This->stateBlock->vertexShader == NULL)) {
513 LoopThroughTo = MAX_STREAMS;
514 } else {
515 LoopThroughTo = 1;
518 /* Work through stream by stream */
519 for (nStream=0; nStream<LoopThroughTo; ++nStream) {
520 DWORD stride = This->stateBlock->streamStride[nStream];
521 BYTE *data = NULL;
522 DWORD thisFVF = 0;
524 /* Skip empty streams */
525 if (This->stateBlock->streamSource[nStream] == NULL) continue;
527 /* Retrieve appropriate FVF */
528 if (LoopThroughTo == 1) { /* Use FVF, not vertex shader */
529 thisFVF = This->stateBlock->fvf;
530 /* Handle memory passed directly as well as vertex buffers */
531 if (This->stateBlock->streamIsUP) {
532 data = (BYTE *)This->stateBlock->streamSource[nStream];
533 } else {
534 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
536 } else {
537 #if 0 /* TODO: Vertex shader support */
538 thisFVF = This->stateBlock->vertexShaderDecl->fvf[nStream];
539 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0);
540 #endif
542 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
543 if (thisFVF == 0) continue;
545 /* Now convert the stream into pointers */
547 /* Shuffle to the beginning of the vertexes to render and index from there */
548 data = data + (BaseVertexIndex * stride);
550 /* Either 3 or 4 floats depending on the FVF */
551 /* FIXME: Can blending data be in a different stream to the position data?
552 and if so using the fixed pipeline how do we handle it */
553 if (thisFVF & D3DFVF_POSITION_MASK) {
554 strided->u.s.position.lpData = data;
555 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT3;
556 strided->u.s.position.dwStride = stride;
557 data += 3 * sizeof(float);
558 if (thisFVF & D3DFVF_XYZRHW) {
559 strided->u.s.position.dwType = D3DDECLTYPE_FLOAT4;
560 data += sizeof(float);
564 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
565 /** do we have to Check This->stateBlock->renderState[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
566 numBlends = 1 + (((thisFVF & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
567 if(thisFVF & D3DFVF_LASTBETA_UBYTE4) numBlends--;
569 if ((thisFVF & D3DFVF_XYZB5 ) > D3DFVF_XYZRHW) {
570 TRACE("Setting blend Weights to %p \n", data);
571 strided->u.s.blendWeights.lpData = data;
572 strided->u.s.blendWeights.dwType = D3DDECLTYPE_FLOAT1 + numBlends - 1;
573 strided->u.s.blendWeights.dwStride = stride;
574 data += numBlends * sizeof(FLOAT);
576 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
577 strided->u.s.blendMatrixIndices.lpData = data;
578 strided->u.s.blendMatrixIndices.dwType = D3DDECLTYPE_UBYTE4;
579 strided->u.s.blendMatrixIndices.dwStride= stride;
580 data += sizeof(DWORD);
584 /* Normal is always 3 floats */
585 if (thisFVF & D3DFVF_NORMAL) {
586 strided->u.s.normal.lpData = data;
587 strided->u.s.normal.dwType = D3DDECLTYPE_FLOAT3;
588 strided->u.s.normal.dwStride = stride;
589 data += 3 * sizeof(FLOAT);
592 /* Pointsize is a single float */
593 if (thisFVF & D3DFVF_PSIZE) {
594 strided->u.s.pSize.lpData = data;
595 strided->u.s.pSize.dwType = D3DDECLTYPE_FLOAT1;
596 strided->u.s.pSize.dwStride = stride;
597 data += sizeof(FLOAT);
600 /* Diffuse is 4 unsigned bytes */
601 if (thisFVF & D3DFVF_DIFFUSE) {
602 strided->u.s.diffuse.lpData = data;
603 strided->u.s.diffuse.dwType = D3DDECLTYPE_SHORT4;
604 strided->u.s.diffuse.dwStride = stride;
605 data += sizeof(DWORD);
608 /* Specular is 4 unsigned bytes */
609 if (thisFVF & D3DFVF_SPECULAR) {
610 strided->u.s.specular.lpData = data;
611 strided->u.s.specular.dwType = D3DDECLTYPE_SHORT4;
612 strided->u.s.specular.dwStride = stride;
613 data += sizeof(DWORD);
616 /* Texture coords */
617 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
618 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
620 /* numTextures indicates the number of texture coordinates supplied */
621 /* However, the first set may not be for stage 0 texture - it all */
622 /* depends on D3DTSS_TEXCOORDINDEX. */
623 /* The number of bytes for each coordinate set is based off */
624 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
626 /* So, for each supplied texture extract the coords */
627 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
629 strided->u.s.texCoords[textureNo].lpData = data;
630 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT1;
631 strided->u.s.texCoords[textureNo].dwStride = stride;
632 numCoords[textureNo] = coordIdxInfo & 0x03;
634 /* Always one set */
635 data += sizeof(float);
636 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
637 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT2;
638 data += sizeof(float);
639 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
640 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT3;
641 data += sizeof(float);
642 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
643 strided->u.s.texCoords[textureNo].dwType = D3DDECLTYPE_FLOAT4;
644 data += sizeof(float);
648 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
653 #if 0 /* TODO: Software Shaders */
654 /* Draw a single vertex using this information */
655 static void draw_vertex(IWineD3DDevice *iface, /* interface */
656 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
657 BOOL isNormal, float nx, float ny, float nz, /* normal */
658 BOOL isDiffuse, float *dRGBA, /* 1st colors */
659 BOOL isSpecular, float *sRGB, /* 2ndry colors */
660 BOOL isPtSize, float ptSize, /* pointSize */
661 WINED3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
663 unsigned int textureNo;
664 float s, t, r, q;
665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
667 /* Diffuse -------------------------------- */
668 if (isDiffuse) {
669 glColor4fv(dRGBA);
670 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
673 /* Specular Colour ------------------------------------------*/
674 if (isSpecular) {
675 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
676 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
677 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
678 } else {
679 VTRACE(("Specular color extensions not supplied\n"));
683 /* Normal -------------------------------- */
684 if (isNormal) {
685 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
686 glNormal3f(nx, ny, nz);
689 /* Point Size ----------------------------------------------*/
690 if (isPtSize) {
692 /* no such functionality in the fixed function GL pipeline */
693 FIXME("Cannot change ptSize here in openGl\n");
696 /* Texture coords --------------------------- */
697 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
699 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
700 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
701 continue ;
704 /* Query tex coords */
705 if (This->stateBlock->textures[textureNo] != NULL) {
707 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
708 if (coordIdx >= MAX_TEXTURES) {
709 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
710 continue;
711 } else if (numcoords[coordIdx] == 0) {
712 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
713 continue;
714 } else {
716 /* Initialize vars */
717 s = 0.0f;
718 t = 0.0f;
719 r = 0.0f;
720 q = 0.0f;
722 switch (numcoords[coordIdx]) {
723 case 4: q = texcoords[coordIdx].w; /* drop through */
724 case 3: r = texcoords[coordIdx].z; /* drop through */
725 case 2: t = texcoords[coordIdx].y; /* drop through */
726 case 1: s = texcoords[coordIdx].x;
729 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
730 case D3DTTFF_COUNT1:
731 VTRACE(("tex:%d, s=%f\n", textureNo, s));
732 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
733 GLMULTITEXCOORD1F(textureNo, s);
734 } else {
735 glTexCoord1f(s);
737 break;
738 case D3DTTFF_COUNT2:
739 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
740 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
741 GLMULTITEXCOORD2F(textureNo, s, t);
742 } else {
743 glTexCoord2f(s, t);
745 break;
746 case D3DTTFF_COUNT3:
747 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
748 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
749 GLMULTITEXCOORD3F(textureNo, s, t, r);
750 } else {
751 glTexCoord3f(s, t, r);
753 break;
754 case D3DTTFF_COUNT4:
755 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
756 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
757 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
758 } else {
759 glTexCoord4f(s, t, r, q);
761 break;
762 default:
763 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
767 } /* End of textures */
769 /* Position -------------------------------- */
770 if (isXYZ) {
771 if (1.0f == rhw || rhw < 0.00001f) {
772 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
773 glVertex3f(x, y, z);
774 } else {
775 /* Cannot optimize by dividing through by rhw as rhw is required
776 later for perspective in the GL pipeline for vertex shaders */
777 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
778 glVertex4f(x,y,z,rhw);
782 #endif /* TODO: Software shaders */
784 void loadNumberedArrays(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
785 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
787 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
788 if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
789 TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
790 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
791 WINED3D_ATR_SIZE(_arrayName), \
792 WINED3D_ATR_GLTYPE(_arrayName), \
793 WINED3D_ATR_NORMALIZED(_arrayName), \
794 sd->u.s._arrayName.dwStride, \
795 sd->u.s._arrayName.lpData)); \
796 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
800 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
801 if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
802 FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
803 GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
804 WINED3D_ATR_SIZE(position2), \
805 WINED3D_ATR_GLTYPE(position2), \
806 WINED3D_ATR_NORMALIZED(position2), \
807 sd->u.s.position2.dwStride, \
808 ((char *)sd->u.s.position2.lpData) + \
809 WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
810 GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
813 /* Generate some lookup tables */
814 /* drop the RHW coord, there must be a nicer way of doing this. */
815 sd->u.s.position.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
816 sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
818 LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
819 LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
820 LOAD_NUMBERED_ARRAY(position,POSITION);
821 LOAD_NUMBERED_ARRAY(normal,NORMAL);
822 LOAD_NUMBERED_ARRAY(pSize,PSIZE);
823 LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
824 LOAD_NUMBERED_ARRAY(specular,SPECULAR);
825 LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
826 LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
827 LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
828 LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
829 LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
830 LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
831 LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
832 LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
833 #if 0 /* TODO: Samplers may allow for more texture coords */
834 LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
835 LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
836 LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
837 LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
838 LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
839 LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
840 LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
841 LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
842 #endif
843 LOAD_NUMBERED_ARRAY(position,POSITIONT);
844 /* d3d9 types */
845 LOAD_NUMBERED_ARRAY(tangent,TANGENT);
846 LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
847 LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
848 LOAD_NUMBERED_ARRAY(position2,POSITION2);
849 /* there can be lots of position arrays */
850 LOAD_NUMBERED_POSITION_ARRAY(0);
851 LOAD_NUMBERED_POSITION_ARRAY(1);
852 LOAD_NUMBERED_POSITION_ARRAY(2);
853 LOAD_NUMBERED_POSITION_ARRAY(3);
854 LOAD_NUMBERED_POSITION_ARRAY(4);
855 LOAD_NUMBERED_POSITION_ARRAY(5);
856 LOAD_NUMBERED_POSITION_ARRAY(6);
857 LOAD_NUMBERED_POSITION_ARRAY(7);
858 LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
859 LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
860 LOAD_NUMBERED_ARRAY(fog,FOG);
861 LOAD_NUMBERED_ARRAY(depth,DEPTH);
862 LOAD_NUMBERED_ARRAY(sample,SAMPLE);
864 #undef LOAD_NUMBERED_ARRAY
867 static void loadVertexData(IWineD3DDevice *iface, Direct3DVertexStridedData *sd) {
868 unsigned int textureNo = 0;
869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
871 TRACE("Using fast vertex array code\n");
872 /* Blend Data ---------------------------------------------- */
873 if ((sd->u.s.blendWeights.lpData != NULL) ||
874 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
877 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
879 #if 1
880 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
881 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
882 #endif
884 TRACE("Blend %d %p %ld\n", WINED3D_ATR_SIZE(blendWeights), sd->u.s.blendWeights.lpData, sd->u.s.blendWeights.dwStride);
885 /* FIXME("TODO\n");*/
886 /* Note dwType == float3 or float4 == 2 or 3 */
888 #if 0
889 /* with this on, the normals appear to be being modified,
890 but the vertices aren't being translated as they should be
891 Maybe the world matrix aren't being setup properly? */
892 glVertexBlendARB(WINED3D_ATR_SIZE(blendWeights) + 1);
893 #endif
896 VTRACE(("glWeightPointerARB(%ld, GL_FLOAT, %ld, %p)\n",
897 WINED3D_ATR_SIZE(blendWeights) ,
898 sd->u.s.blendWeights.dwStride,
899 sd->u.s.blendWeights.lpData));
901 GL_EXTCALL(glWeightPointerARB)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
902 sd->u.s.blendWeights.dwStride,
903 sd->u.s.blendWeights.lpData);
905 checkGLcall("glWeightPointerARB");
907 if(sd->u.s.blendMatrixIndices.lpData != NULL){
908 static BOOL showfixme = TRUE;
909 if(showfixme){
910 FIXME("blendMatrixIndices support\n");
911 showfixme = FALSE;
917 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
918 /* FIXME("TODO\n");*/
919 #if 0
921 GL_EXTCALL(glVertexWeightPointerEXT)(WINED3D_ATR_SIZE(blendWeights), WINED3D_ATR_GLTYPE(blendWeights),
922 sd->u.s.blendWeights.dwStride,
923 sd->u.s.blendWeights.lpData);
924 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
925 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
926 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
927 #endif
929 } else {
930 /* TODO: support blends in fixupVertices */
931 FIXME("unsupported blending in openGl\n");
933 } else {
934 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
935 #if 0 /* TODO: Vertex blending */
936 glDisable(GL_VERTEX_BLEND_ARB);
937 #endif
938 TRACE("ARB_VERTEX_BLEND \n");
939 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
940 TRACE(" EXT_VERTEX_WEIGHTING\n");
941 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
942 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
947 #if 0 /* FOG ----------------------------------------------*/
948 if (sd->u.s.fog.lpData != NULL) {
949 /* TODO: fog*/
950 if (GL_SUPPORT(EXT_FOG_COORD) {
951 glEnableClientState(GL_FOG_COORD_EXT);
952 (GL_EXTCALL)(FogCoordPointerEXT)(WINED3D_ATR_GLTYPE(fog),
953 sd->u.s.fog.dwStride,
954 sd->u.s.fog.lpData);
955 } else {
956 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
957 /* FIXME: fixme once */
958 TRACE("Hardware support for FOG is not avaiable, FOG disabled. \n");
960 } else {
961 if (GL_SUPPRT(EXT_FOR_COORD) {
962 /* make sure fog is disabled */
963 glDisableClientState(GL_FOG_COORD_EXT);
966 #endif
968 #if 0 /* tangents ----------------------------------------------*/
969 if (sd->u.s.tangent.lpData != NULL || sd->u.s.binormal.lpData != NULL) {
970 /* TODO: tangents*/
971 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
972 if (sd->u.s.tangent.lpData != NULL) {
973 glEnable(GL_TANGENT_ARRAY_EXT);
974 (GL_EXTCALL)(TangentPointerEXT)(WINED3D_ATR_GLTYPE(tangent),
975 sd->u.s.tangent.dwStride,
976 sd->u.s.tangent.lpData);
977 } else {
978 glDisable(GL_TANGENT_ARRAY_EXT);
980 if (sd->u.s.binormal.lpData != NULL) {
981 glEnable(GL_BINORMAL_ARRAY_EXT);
982 (GL_EXTCALL)(BinormalPointerEXT)(WINED3D_ATR_GLTYPE(binormal),
983 sd->u.s.binormal.dwStride,
984 sd->u.s.binormal.lpData);
985 } else{
986 glDisable(GL_BINORMAL_ARRAY_EXT);
989 } else {
990 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
991 /* FIXME: fixme once */
992 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled. \n");
994 } else {
995 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
996 /* make sure fog is disabled */
997 glDisable(GL_TANGENT_ARRAY_EXT);
998 glDisable(GL_BINORMAL_ARRAY_EXT);
1001 #endif
1003 /* Point Size ----------------------------------------------*/
1004 if (sd->u.s.pSize.lpData != NULL) {
1006 /* no such functionality in the fixed function GL pipeline */
1007 TRACE("Cannot change ptSize here in openGl\n");
1008 /* TODO: Implement this function in using shaders if they are available */
1012 /* Vertex Pointers -----------------------------------------*/
1013 if (sd->u.s.position.lpData != NULL) {
1014 /* Note dwType == float3 or float4 == 2 or 3 */
1015 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
1016 sd->u.s.position.dwStride,
1017 sd->u.s.position.dwType + 1,
1018 sd->u.s.position.lpData));
1020 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
1021 handling for rhw mode should not impact screen position whereas in GL it does.
1022 This may result in very slightly distored textures in rhw mode, but
1023 a very minimal different. There's always the other option of
1024 fixing the view matrix to prevent w from having any effect */
1025 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(position),3) */, WINED3D_ATR_GLTYPE(position),
1026 sd->u.s.position.dwStride, sd->u.s.position.lpData);
1027 checkGLcall("glVertexPointer(...)");
1028 glEnableClientState(GL_VERTEX_ARRAY);
1029 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
1031 } else {
1032 glDisableClientState(GL_VERTEX_ARRAY);
1033 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
1036 /* Normals -------------------------------------------------*/
1037 if (sd->u.s.normal.lpData != NULL) {
1038 /* Note dwType == float3 or float4 == 2 or 3 */
1039 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
1040 sd->u.s.normal.dwStride,
1041 sd->u.s.normal.lpData));
1042 glNormalPointer(WINED3D_ATR_GLTYPE(normal),
1043 sd->u.s.normal.dwStride,
1044 sd->u.s.normal.lpData);
1045 checkGLcall("glNormalPointer(...)");
1046 glEnableClientState(GL_NORMAL_ARRAY);
1047 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
1049 } else {
1050 glDisableClientState(GL_NORMAL_ARRAY);
1051 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
1052 glNormal3f(0, 0, 1);
1053 checkGLcall("glNormal3f(0, 0, 1)");
1056 /* Diffuse Colour --------------------------------------------*/
1057 /* WARNING: Data here MUST be in RGBA format, so cannot */
1058 /* go directly into fast mode from app pgm, because */
1059 /* directx requires data in BGRA format. */
1060 /* currently fixupVertices swizels the format, but this isn't */
1061 /* very practical when using VBOS */
1062 /* NOTE: Unless we write a vertex shader to swizel the colour */
1063 /* , or the user doesn't care and wants the speed advantage */
1065 if (sd->u.s.diffuse.lpData != NULL) {
1066 /* Note dwType == float3 or float4 == 2 or 3 */
1067 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1068 sd->u.s.diffuse.dwStride,
1069 sd->u.s.diffuse.lpData));
1071 glColorPointer(4, GL_UNSIGNED_BYTE,
1072 sd->u.s.diffuse.dwStride,
1073 sd->u.s.diffuse.lpData);
1074 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
1075 glEnableClientState(GL_COLOR_ARRAY);
1076 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
1078 } else {
1079 glDisableClientState(GL_COLOR_ARRAY);
1080 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
1081 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1082 checkGLcall("glColor4f(1, 1, 1, 1)");
1085 /* Specular Colour ------------------------------------------*/
1086 if (sd->u.s.specular.lpData != NULL) {
1087 TRACE("setting specular colour\n");
1088 /* Note dwType == float3 or float4 == 2 or 3 */
1089 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
1090 sd->u.s.specular.dwStride,
1091 sd->u.s.specular.lpData));
1092 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1093 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
1094 sd->u.s.specular.dwStride,
1095 sd->u.s.specular.lpData);
1096 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
1097 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1098 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1099 } else {
1101 /* Missing specular color is not critical, no warnings */
1102 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1105 } else {
1106 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1108 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
1109 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
1110 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1111 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
1112 } else {
1114 /* Missing specular color is not critical, no warnings */
1115 VTRACE(("Specular colour is not supported in this GL implementation\n"));
1119 /* Texture coords -------------------------------------------*/
1121 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1123 /* Select the correct texture stage */
1124 GLCLIENTACTIVETEXTURE(textureNo);
1125 if (This->stateBlock->textures[textureNo] != NULL) {
1126 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1127 TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1128 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1129 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1130 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1131 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1132 continue;
1135 if (coordIdx >= MAX_TEXTURES) {
1136 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1137 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1138 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1140 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1141 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
1142 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1143 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1145 } else {
1147 /* The coords to supply depend completely on the fvf / vertex shader */
1148 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
1149 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1152 } else {
1153 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1154 GLMULTITEXCOORD4F(textureNo, 0, 0, 0, 1);
1159 static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
1160 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1163 if (idxData != NULL /* This crashes sometimes!*/) {
1164 TRACE("(%p) : glElements(%x, %d, %ld, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
1165 idxData = idxData == (void *)-1 ? NULL : idxData;
1166 #if 1
1167 #if 0
1168 glIndexPointer(idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idxSize, startIdx);
1169 glEnableClientState(GL_INDEX_ARRAY);
1170 #endif
1171 glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1172 (const char *)idxData+(idxSize * startIdx));
1173 #else /* using drawRangeElements may be faster */
1175 glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
1176 idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
1177 (const char *)idxData+(idxSize * startIdx));
1178 #endif
1179 checkGLcall("glDrawRangeElements");
1181 } else {
1183 /* Note first is now zero as we shuffled along earlier */
1184 TRACE("(%p) : glDrawArrays(%x, 0, %d)\n", This, glPrimitiveType, numberOfVertices);
1185 glDrawArrays(glPrimitiveType, 0, numberOfVertices);
1186 checkGLcall("glDrawArrays");
1190 return;
1194 * Actually draw using the supplied information.
1195 * Slower GL version which extracts info about each vertex in turn
1198 static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1199 UINT NumVertexes, GLenum glPrimType,
1200 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1202 unsigned int textureNo = 0;
1203 const short *pIdxBufS = NULL;
1204 const long *pIdxBufL = NULL;
1205 LONG SkipnStrides = 0;
1206 LONG vx_index;
1207 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1208 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
1209 float rhw = 0.0f; /* rhw */
1210 float ptSize = 0.0f; /* Point size */
1211 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
1212 DWORD specularColor = 0; /* Specular Color */
1213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1215 TRACE("Using slow vertex array code\n");
1217 /* Variable Initialization */
1218 if (idxData != NULL) {
1219 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1220 else pIdxBufL = (const long *) idxData;
1223 /* Start drawing in GL */
1224 VTRACE(("glBegin(%x)\n", glPrimType));
1225 glBegin(glPrimType);
1227 /* For each primitive */
1228 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1230 /* Initialize diffuse color */
1231 diffuseColor = 0xFFFFFFFF;
1233 /* For indexed data, we need to go a few more strides in */
1234 if (idxData != NULL) {
1236 /* Indexed so work out the number of strides to skip */
1237 if (idxSize == 2) {
1238 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1239 SkipnStrides = pIdxBufS[startIdx + vx_index];
1240 } else {
1241 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1242 SkipnStrides = pIdxBufL[startIdx + vx_index];
1246 /* Position Information ------------------ */
1247 if (sd->u.s.position.lpData != NULL) {
1249 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
1250 x = ptrToCoords[0];
1251 y = ptrToCoords[1];
1252 z = ptrToCoords[2];
1253 rhw = 1.0;
1254 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
1256 /* RHW follows, only if transformed, ie 4 floats were provided */
1257 if (sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4) {
1258 rhw = ptrToCoords[3];
1259 VTRACE(("rhw=%f\n", rhw));
1263 /* Blending data -------------------------- */
1264 if (sd->u.s.blendWeights.lpData != NULL) {
1265 /* float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride)); */
1266 FIXME("Blending not supported yet\n");
1268 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1269 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1273 /* Vertex Normal Data (untransformed only)- */
1274 if (sd->u.s.normal.lpData != NULL) {
1276 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1277 nx = ptrToCoords[0];
1278 ny = ptrToCoords[1];
1279 nz = ptrToCoords[2];
1280 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1283 /* Point Size ----------------------------- */
1284 if (sd->u.s.pSize.lpData != NULL) {
1286 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1287 ptSize = ptrToCoords[0];
1288 VTRACE(("ptSize=%f\n", ptSize));
1289 FIXME("No support for ptSize yet\n");
1292 /* Diffuse -------------------------------- */
1293 if (sd->u.s.diffuse.lpData != NULL) {
1295 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1296 diffuseColor = ptrToCoords[0];
1297 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1300 /* Specular -------------------------------- */
1301 if (sd->u.s.specular.lpData != NULL) {
1303 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1304 specularColor = ptrToCoords[0];
1305 VTRACE(("specularColor=%lx\n", specularColor));
1308 /* Texture coords --------------------------- */
1309 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1311 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1312 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1313 continue ;
1316 /* Query tex coords */
1317 if (This->stateBlock->textures[textureNo] != NULL) {
1319 int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
1320 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1321 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1323 if (coordIdx > 7) {
1324 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1325 continue;
1326 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1327 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1328 continue;
1329 } else {
1331 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DDECLTYPE_FLOAT1 etc */
1333 /* The coords to supply depend completely on the fvf / vertex shader */
1334 switch (coordsToUse) {
1335 case 4: q = ptrToCoords[3]; /* drop through */
1336 case 3: r = ptrToCoords[2]; /* drop through */
1337 case 2: t = ptrToCoords[1]; /* drop through */
1338 case 1: s = ptrToCoords[0];
1341 /* Projected is more 'fun' - Move the last coord to the 'q'
1342 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1343 if ((This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1344 (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1346 if (This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1347 switch (coordsToUse) {
1348 case 0: /* Drop Through */
1349 case 1:
1350 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1351 break;
1352 case 2:
1353 q = t;
1354 t = 0.0;
1355 coordsToUse = 4;
1356 break;
1357 case 3:
1358 q = r;
1359 r = 0.0;
1360 coordsToUse = 4;
1361 break;
1362 case 4: /* Nop here */
1363 break;
1364 default:
1365 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1366 This->stateBlock->textureState[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1371 switch (coordsToUse) { /* Supply the provided texture coords */
1372 case D3DTTFF_COUNT1:
1373 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1374 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1375 GLMULTITEXCOORD1F(textureNo, s);
1376 } else {
1377 glTexCoord1f(s);
1379 break;
1380 case D3DTTFF_COUNT2:
1381 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1382 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1383 GLMULTITEXCOORD2F(textureNo, s, t);
1384 } else {
1385 glTexCoord2f(s, t);
1387 break;
1388 case D3DTTFF_COUNT3:
1389 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1390 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1391 GLMULTITEXCOORD3F(textureNo, s, t, r);
1392 } else {
1393 glTexCoord3f(s, t, r);
1395 break;
1396 case D3DTTFF_COUNT4:
1397 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1398 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1399 GLMULTITEXCOORD4F(textureNo, s, t, r, q);
1400 } else {
1401 glTexCoord4f(s, t, r, q);
1403 break;
1404 default:
1405 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1409 } /* End of textures */
1411 /* Diffuse -------------------------------- */
1412 if (sd->u.s.diffuse.lpData != NULL) {
1413 glColor4ub((diffuseColor >> 16) & 0xFF,
1414 (diffuseColor >> 8) & 0xFF,
1415 (diffuseColor >> 0) & 0xFF,
1416 (diffuseColor >> 24) & 0xFF);
1417 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1418 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1419 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1420 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1421 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1422 } else {
1423 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1426 /* Specular ------------------------------- */
1427 if (sd->u.s.diffuse.lpData != NULL) {
1428 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1429 ((specularColor >> 16) & 0xFF) / 255.0f,
1430 ((specularColor >> 8) & 0xFF) / 255.0f,
1431 ((specularColor >> 0) & 0xFF) / 255.0f));
1432 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1433 GL_EXTCALL(glSecondaryColor3ubEXT)(
1434 (specularColor >> 16) & 0xFF,
1435 (specularColor >> 8) & 0xFF,
1436 (specularColor >> 0) & 0xFF);
1437 } else {
1438 /* Do not worry if specular colour missing and disable request */
1439 VTRACE(("Specular color extensions not supplied\n"));
1441 } else {
1442 if (vx_index == 0) {
1443 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1444 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1445 } else {
1446 /* Do not worry if specular colour missing and disable request */
1447 VTRACE(("Specular color extensions not supplied\n"));
1452 /* Normal -------------------------------- */
1453 if (sd->u.s.normal.lpData != NULL) {
1454 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1455 glNormal3f(nx, ny, nz);
1456 } else {
1457 if (vx_index == 0) glNormal3f(0, 0, 1);
1460 /* Position -------------------------------- */
1461 if (sd->u.s.position.lpData != NULL) {
1462 if (1.0f == rhw || ((rhw < 0.0001f) && (rhw > -0.0001f))) {
1463 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1464 glVertex3f(x, y, z);
1465 } else {
1466 GLfloat w = 1.0 / rhw;
1467 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1468 glVertex4f(x*w, y*w, z*w, w);
1472 /* For non indexed mode, step onto next parts */
1473 if (idxData == NULL) {
1474 ++SkipnStrides;
1478 glEnd();
1479 checkGLcall("glEnd and previous calls");
1482 #if 0 /* TODO: Software/Hardware vertex blending support */
1484 * Draw with emulated vertex shaders
1485 * Note: strided data is uninitialized, as we need to pass the vertex
1486 * shader directly as ordering irs yet
1488 void drawStridedSoftwareVS(IWineD3DDevice *iface, Direct3DVertexStridedData *sd,
1489 int PrimitiveType, ULONG NumPrimitives,
1490 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1492 unsigned int textureNo = 0;
1493 GLenum glPrimType = GL_POINTS;
1494 int NumVertexes = NumPrimitives;
1495 const short *pIdxBufS = NULL;
1496 const long *pIdxBufL = NULL;
1497 LONG SkipnStrides = 0;
1498 LONG vx_index;
1499 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1500 float rhw = 0.0f; /* rhw */
1501 float ptSize = 0.0f; /* Point size */
1502 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1503 int numcoords[8]; /* Number of coords */
1504 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1506 IDirect3DVertexShaderImpl* vertexShader = NULL;
1508 TRACE("Using slow software vertex shader code\n");
1510 /* Variable Initialization */
1511 if (idxData != NULL) {
1512 if (idxSize == 2) pIdxBufS = (const short *) idxData;
1513 else pIdxBufL = (const long *) idxData;
1516 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1517 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1519 /* Retrieve the VS information */
1520 vertexShader = (IWineD3DVertexShaderImp *)This->stateBlock->VertexShader;
1522 /* Start drawing in GL */
1523 VTRACE(("glBegin(%x)\n", glPrimType));
1524 glBegin(glPrimType);
1526 /* For each primitive */
1527 for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
1529 /* For indexed data, we need to go a few more strides in */
1530 if (idxData != NULL) {
1532 /* Indexed so work out the number of strides to skip */
1533 if (idxSize == 2) {
1534 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1535 SkipnStrides = pIdxBufS[startIdx+vx_index];
1536 } else {
1537 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1538 SkipnStrides = pIdxBufL[startIdx+vx_index];
1542 /* Fill the vertex shader input */
1543 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertexShader, SkipnStrides);
1545 /* Initialize the output fields to the same defaults as it would normally have */
1546 memset(&vertexShader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1547 vertexShader->output.oD[0].x = 1.0;
1548 vertexShader->output.oD[0].y = 1.0;
1549 vertexShader->output.oD[0].z = 1.0;
1550 vertexShader->output.oD[0].w = 1.0;
1552 /* Now execute the vertex shader */
1553 IDirect3DVertexShaderImpl_ExecuteSW(vertexShader, &vertexShader->input, &vertexShader->output);
1556 TRACE_VECTOR(vertexShader->output.oPos);
1557 TRACE_VECTOR(vertexShader->output.oD[0]);
1558 TRACE_VECTOR(vertexShader->output.oD[1]);
1559 TRACE_VECTOR(vertexShader->output.oT[0]);
1560 TRACE_VECTOR(vertexShader->output.oT[1]);
1561 TRACE_VECTOR(vertexShader->input.V[0]);
1562 TRACE_VECTOR(vertexShader->data->C[0]);
1563 TRACE_VECTOR(vertexShader->data->C[1]);
1564 TRACE_VECTOR(vertexShader->data->C[2]);
1565 TRACE_VECTOR(vertexShader->data->C[3]);
1566 TRACE_VECTOR(vertexShader->data->C[4]);
1567 TRACE_VECTOR(vertexShader->data->C[5]);
1568 TRACE_VECTOR(vertexShader->data->C[6]);
1569 TRACE_VECTOR(vertexShader->data->C[7]);
1572 /* Extract out the output */
1573 /* FIXME: Fog coords? */
1574 x = vertexShader->output.oPos.x;
1575 y = vertexShader->output.oPos.y;
1576 z = vertexShader->output.oPos.z;
1577 rhw = vertexShader->output.oPos.w;
1578 ptSize = vertexShader->output.oPts.x; /* Fixme - Is this right? */
1580 /** Update textures coords using vertexShader->output.oT[0->7] */
1581 memset(texcoords, 0x00, sizeof(texcoords));
1582 memset(numcoords, 0x00, sizeof(numcoords));
1583 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1584 if (This->stateBlock->textures[textureNo] != NULL) {
1585 texcoords[textureNo].x = vertexShader->output.oT[textureNo].x;
1586 texcoords[textureNo].y = vertexShader->output.oT[textureNo].y;
1587 texcoords[textureNo].z = vertexShader->output.oT[textureNo].z;
1588 texcoords[textureNo].w = vertexShader->output.oT[textureNo].w;
1589 if (This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1590 numcoords[textureNo] = This->stateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1591 } else {
1592 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->stateBlock->textures[textureNo])) {
1593 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1594 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1595 default: numcoords[textureNo] = 4;
1598 } else {
1599 numcoords[textureNo] = 0;
1603 /* Draw using this information */
1604 draw_vertex(iface,
1605 TRUE, x, y, z, rhw,
1606 TRUE, 0.0f, 0.0f, 1.0f,
1607 TRUE, (float*) &vertexShader->output.oD[0],
1608 TRUE, (float*) &vertexShader->output.oD[1],
1609 FALSE, ptSize, /* FIXME: Change back when supported */
1610 texcoords, numcoords);
1612 /* For non indexed mode, step onto next parts */
1613 if (idxData == NULL) {
1614 ++SkipnStrides;
1617 } /* for each vertex */
1619 glEnd();
1620 checkGLcall("glEnd and previous calls");
1623 #endif
1625 void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
1626 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
1627 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1629 /* Now draw the graphics to the screen */
1630 if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) {
1631 FIXME("drawing using software vertex shaders (line %d)\n", __LINE__);
1632 /* Ideally, we should have software FV and hardware VS, possibly
1633 depending on the device type? */
1634 #if 0 /* TODO: vertex and pixel shaders */
1635 drawStridedSoftwareVS(iface, dataLocations, PrimitiveType, NumPrimitives,
1636 idxData, idxSize, minIndex, StartIdx);
1637 #endif
1639 } else {
1641 /* TODO: Work out if fixup are required at all (this can be a flag against the vertex declaration) */
1642 int startStride = idxData == NULL ? 0 : idxData == (void *) -1 ? 0 :(idxSize == 2 ? *(((const short *) idxData) + StartIdx) : *((const int *) idxData) + StartIdx);
1643 int endStride = startStride;
1644 TRACE("begin Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1646 #if 0 /* TODO: Vertex fixups (diffuse and specular) */
1647 if (idxData != NULL) { /* index data isn't linear, so lookup the real start and end strides */
1648 int t;
1649 if (idxSize == 2) {
1650 unsigned short *index = (unsigned short *)idxData;
1651 index += StartIdx;
1652 for (t = 0 ; t < numberOfIndicies; t++) {
1653 if (startStride > *index)
1654 startStride = *index;
1655 if (endStride < *index)
1656 endStride = *index;
1657 index++;
1659 } else { /* idxSize == 4 */
1660 unsigned int *index = (unsigned int *)idxData;
1661 index += StartIdx;
1662 for (t = 0 ; t < numberOfIndicies; t++) {
1663 if (startStride > *index)
1664 startStride = *index;
1665 if (endStride < *index)
1666 endStride = *index;
1667 index++;
1670 } else {
1671 endStride += numberOfvertices -1;
1673 #endif
1674 TRACE("end Start stride %d, end stride %d, number of indices%d, number of vertices%d\n", startStride, endStride, numberOfIndicies, numberOfvertices);
1675 /* pre-transform verticex */
1676 /* TODO: Caching, VBO's etc.. */
1678 /* Generate some fixme's if unsupported functionality is being used */
1679 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
1680 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
1681 if (!useVertexShaderFunction && (BUFFER_OR_DATA(blendMatrixIndices) || BUFFER_OR_DATA(blendWeights))) {
1682 FIXME("Blending data is only valid with vertex shaders %p %p\n",dataLocations->u.s.blendWeights.lpData,dataLocations->u.s.blendWeights.lpData);
1684 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
1685 FIXME("Tweening is only valid with vertex shaders\n");
1687 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
1688 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
1690 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
1691 FIXME("Extended attributes are only valid with vertex shaders\n");
1693 #undef BUFFER_OR_DATA
1695 #if 0/* TODO: Vertex fixups (diffuse and specular) */
1696 fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride);
1697 #endif
1699 /* vertex shaders */
1701 /* If the only vertex data used by the shader is supported by OpenGL then*/
1702 if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL
1703 && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)
1704 || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) {
1706 /* Load the vertex data using named arrays */
1707 TRACE("(%p) Loading vertex data\n", This);
1708 loadVertexData(iface, dataLocations);
1710 } else /* Otherwise */
1711 if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1713 /* load the array data using ordinal mapping */
1714 loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap);
1716 } else { /* If this happens we must drawStridedSlow later on */
1717 TRACE("Not loading vertex data\n");
1720 TRACE("Loaded arrays\n");
1722 if (useVertexShaderFunction) {
1723 int i;
1724 GLint errPos;
1726 FIXME("Using vertex shader\n");
1728 /* Bind the vertex program */
1729 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
1730 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
1732 /* and enable gl vertex shaders */
1733 glEnable(GL_VERTEX_PROGRAM_ARB);
1734 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1735 TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
1737 /* Update the constants */
1738 for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
1739 /* TODO: add support for Integer and Boolean constants */
1740 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
1741 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]);
1742 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1744 /* TODO: Vertex Shader 8 constants*/
1746 /* always draw strided fast if a vertex shader is being used */
1747 drawStridedFast(iface, numberOfIndicies, glPrimType,
1748 idxData, idxSize, minIndex, StartIdx);
1750 /* check for any errors */
1751 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1752 if (errPos != -1) {
1753 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1756 /* disable any attribs */
1757 if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
1758 GLint maxAttribs;
1759 int i;
1760 /* Leave all the attribs disabled */
1761 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1762 /* MESA does not support it right not */
1763 if (glGetError() != GL_NO_ERROR)
1764 maxAttribs = 16;
1765 for (i = 0; i < maxAttribs; i++) {
1766 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1767 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1771 /* Done */
1772 glDisable(GL_VERTEX_PROGRAM_ARB);
1773 } else {
1775 /* DirectX colours are in a different format to opengl colours
1776 so if diffuse or specular are used then we need to use drawStridedSlow
1777 to correct the colours */
1778 if ((dataLocations->u.s.pSize.lpData != NULL)
1779 || (dataLocations->u.s.diffuse.lpData != NULL)
1780 || (dataLocations->u.s.specular.lpData != NULL)) {
1781 /* TODO: replace drawStridedSlow with veretx fixups */
1782 #if 1
1784 drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1785 idxData, idxSize, minIndex, StartIdx) ;
1788 * drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType,
1789 * idxData, idxSize, minIndex, StartIdx);
1791 #endif
1792 } else {
1793 /* OpenGL can manage everything in hardware so we can use drawStridedFast */
1794 drawStridedFast(iface, numberOfIndicies, glPrimType,
1795 idxData, idxSize, minIndex, StartIdx);
1801 void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocations,DWORD fvf) {
1803 /* Dump out what parts we have supplied */
1804 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1805 TRACE_STRIDED((dataLocations), position);
1806 TRACE_STRIDED((dataLocations), blendWeights);
1807 TRACE_STRIDED((dataLocations), blendMatrixIndices);
1808 TRACE_STRIDED((dataLocations), normal);
1809 TRACE_STRIDED((dataLocations), pSize);
1810 TRACE_STRIDED((dataLocations), diffuse);
1811 TRACE_STRIDED((dataLocations), specular);
1812 TRACE_STRIDED((dataLocations), texCoords[0]);
1813 TRACE_STRIDED((dataLocations), texCoords[1]);
1814 TRACE_STRIDED((dataLocations), texCoords[2]);
1815 TRACE_STRIDED((dataLocations), texCoords[3]);
1816 TRACE_STRIDED((dataLocations), texCoords[4]);
1817 TRACE_STRIDED((dataLocations), texCoords[5]);
1818 TRACE_STRIDED((dataLocations), texCoords[6]);
1819 TRACE_STRIDED((dataLocations), texCoords[7]);
1820 TRACE_STRIDED((dataLocations), position2);
1821 TRACE_STRIDED((dataLocations), normal2);
1822 TRACE_STRIDED((dataLocations), tangent);
1823 TRACE_STRIDED((dataLocations), binormal);
1824 TRACE_STRIDED((dataLocations), tessFactor);
1825 TRACE_STRIDED((dataLocations), fog);
1826 TRACE_STRIDED((dataLocations), depth);
1827 TRACE_STRIDED((dataLocations), sample);
1829 return;
1833 /* uploads textures and setup texture states ready for rendering */
1834 void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
1836 unsigned int i;
1838 * OK, here we clear down any old junk iect in the context
1839 * enable the new texture and apply any state changes:
1841 * Loop through all textures
1842 * select texture unit
1843 * if there is a texture bound to that unit then..
1844 * disable all textures types on that unit
1845 * enable and bind the texture that is bound to that unit.
1846 * otherwise disable all texture types on that unit.
1848 /* upload the textures */
1849 for (i = 0; i< GL_LIMITS(textures); ++i) {
1850 /* Bind the texture to the stage here */
1851 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1852 GLACTIVETEXTURE(i);
1853 } else if (0 < i) {
1854 /* This isn't so much a warn as a message to the user about lack of hardware support */
1855 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1858 /* don't bother with textures that have a colorop of disable */
1859 if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
1860 if (This->stateBlock->textures[i] != NULL) {
1862 glDisable(GL_TEXTURE_1D);
1863 This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
1864 /* disable all texture states that aren't the selected textures' dimension */
1865 switch(This->stateBlock->textureDimensions[i]) {
1866 case GL_TEXTURE_2D:
1867 glDisable(GL_TEXTURE_3D);
1868 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1869 break;
1870 case GL_TEXTURE_3D:
1871 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1872 glDisable(GL_TEXTURE_2D);
1873 break;
1874 case GLTEXTURECUBEMAP:
1875 glDisable(GL_TEXTURE_2D);
1876 glDisable(GL_TEXTURE_3D);
1877 break;
1879 /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
1880 if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
1881 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1882 } else {
1883 glEnable(This->stateBlock->textureDimensions[i]);
1885 /* Load up the texture now */
1886 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
1887 IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
1888 /* this is a stub function representing the state blocks
1889 * being separated here we are only updating the texture
1890 * state changes, other objects and units get updated when
1891 * they change (or need to be updated), e.g. states that
1892 * relate to a context member line the texture unit are
1893 * only updated when the context needs updating
1895 /* Tell the abse texture to sync it's states */
1896 IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
1899 /* Bind a default texture if no texture has been set, but colour-op is enabled */
1900 else {
1901 glDisable(GL_TEXTURE_2D);
1902 glDisable(GL_TEXTURE_3D);
1903 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1904 glEnable(GL_TEXTURE_1D);
1905 This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
1906 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
1908 /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
1909 dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
1910 set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
1911 This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
1912 This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
1913 This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
1914 /* alphaop */
1915 set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
1916 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
1917 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
1918 This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
1919 } else {
1921 /* no colorop so disable all the texture states */
1922 glDisable(GL_TEXTURE_1D);
1923 glDisable(GL_TEXTURE_2D);
1924 glDisable(GL_TEXTURE_3D);
1925 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1932 /* Routine common to the draw primitive and draw indexed primitive routines */
1933 void drawPrimitive(IWineD3DDevice *iface,
1934 int PrimitiveType,
1935 long NumPrimitives,
1936 /* for Indexed: */
1937 long StartVertexIndex,
1938 UINT numberOfVertices,
1939 long StartIdx,
1940 short idxSize,
1941 const void *idxData,
1942 int minIndex) {
1944 BOOL rc = FALSE;
1945 DWORD fvf = 0;
1946 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1947 BOOL useVertexShaderFunction = FALSE;
1948 BOOL isLightingOn = FALSE;
1949 Direct3DVertexStridedData dataLocations;
1950 int useHW = FALSE;
1952 useVertexShaderFunction = This->stateBlock->vertexShader != NULL ? wined3d_settings.vs_mode != VS_NONE ? ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->function != NULL ? TRUE: FALSE : FALSE : FALSE;
1954 if (This->stateBlock->vertexDecl == NULL) {
1955 /* Work out what the FVF should look like */
1956 rc = initializeFVF(iface, &fvf);
1957 if (rc) return;
1958 } else {
1959 TRACE("(%p) : using vertex declaration %p \n", iface, This->stateBlock->vertexDecl);
1962 /* Ok, we will be updating the screen from here onwards so grab the lock */
1963 ENTER_GL();
1965 #if 0 /* TODO: vertex and pixel shaders */
1966 /* If we will be using a pixel, do some initialization for it */
1967 if ((pixel_shader = PIXEL_SHADER(This->stateBlock->PixelShader))) {
1968 TRACE("drawing with pixel shader handle %p\n", pixel_shader);
1969 memset(&pixel_shader->input, 0, sizeof(PSHADERINPUTDATA8));
1971 GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId));
1972 checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixel_shader->prgId);");
1973 glEnable(GL_FRAGMENT_PROGRAM_ARB);
1974 checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
1976 /* init Constants */
1977 if (This->stateBlock->Changed.pixelShaderConstant) {
1978 TRACE_(d3d_shader)("pixel shader initializing constants %p\n",pixel_shader);
1979 IDirect3DPixelShaderImpl_SetConstantF(pixel_shader, 0, (CONST FLOAT*) &This->stateBlock->pixelShaderConstant[0], 8);
1981 /* Update the constants */
1982 for (i = 0; i < D3D8_PSHADER_MAX_CONSTANTS; ++i) {
1983 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, (GLfloat *)&This->stateBlock->pixelShaderConstant[i]));
1984 checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB");
1987 #endif /* TODO: vertex and pixel shaders */
1989 /* Initialize all values to null */
1990 memset(&dataLocations, 0x00, sizeof(dataLocations));
1991 /* convert the FVF or vertexDeclaration into a strided stream (this should be done when the fvf or declaration is created) */
1993 if (This->stateBlock->vertexDecl != NULL) {
1994 TRACE("================ Vertex Declaration ===================\n");
1995 primitiveDeclarationConvertToStridedData(iface, &dataLocations, StartVertexIndex, &fvf);
1996 } else {
1997 TRACE("================ FVF ===================\n");
1998 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
2001 /* write out some debug information*/
2002 drawPrimitiveTraceDataLocations(&dataLocations, fvf);
2004 /* Setup transform matrices and sort out */
2005 if (useHW) {
2006 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
2007 So make sure lighting is disabled. */
2008 isLightingOn = glIsEnabled(GL_LIGHTING);
2009 glDisable(GL_LIGHTING);
2010 checkGLcall("glDisable(GL_LIGHTING);");
2011 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
2012 } else {
2013 isLightingOn = primitiveInitState(iface,
2014 fvf & D3DFVF_XYZRHW,
2015 !(fvf & D3DFVF_NORMAL),
2016 useVertexShaderFunction);
2019 /* Now initialize the materials state */
2020 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
2022 drawPrimitiveUploadTextures(This);
2026 GLenum glPrimType;
2027 /* Ok, Work out which primitive is requested and how many vertexes that
2028 will be */
2029 UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
2030 #if 0 /* debugging code... just information not an error */
2031 if(numberOfVertices != 0 && numberOfVertices != calculatedNumberOfindices){
2032 FIXME("Number of vertices %u and Caculated number of indicies %u differ\n", numberOfVertices, calculatedNumberOfindices);
2034 #endif
2035 if (numberOfVertices == 0 )
2036 numberOfVertices = calculatedNumberOfindices;
2037 drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
2040 /* If vertex shaders or no normals, restore previous lighting state */
2041 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
2042 if (isLightingOn) glEnable(GL_LIGHTING);
2043 else glDisable(GL_LIGHTING);
2044 TRACE("Restored lighting to original state\n");
2047 #if 0 /* TODO: vertex and pixel shaders */
2048 if (pixel_shader)
2050 #if 0
2051 GLint errPos;
2052 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
2053 if (errPos != -1)
2054 FIXME("HW PixelShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
2055 #endif
2056 glDisable(GL_FRAGMENT_PROGRAM_ARB);
2058 #endif
2060 /* Finshed updating the screen, restore lock */
2061 LEAVE_GL();
2062 TRACE("Done all gl drawing\n");
2064 /* Diagnostics */
2065 #ifdef SHOW_FRAME_MAKEUP
2067 static long int primCounter = 0;
2068 /* NOTE: set primCounter to the value reported by drawprim
2069 before you want to to write frame makeup to /tmp */
2070 if (primCounter >= 0) {
2071 D3DLOCKED_RECT r;
2072 char buffer[80];
2073 IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, D3DLOCK_READONLY);
2074 sprintf(buffer, "/tmp/backbuffer_%ld.tga", primCounter);
2075 TRACE("Saving screenshot %s\n", buffer);
2076 IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
2077 IWineD3DSurface_UnlockRect(This->renderTarget);
2079 #ifdef SHOW_TEXTURE_MAKEUP
2081 IWineD3DSurface *pSur;
2082 int textureNo;
2083 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
2084 if (This->stateBlock->textures[textureNo] != NULL) {
2085 sprintf(buffer, "/tmp/texture_%p_%ld_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
2086 TRACE("Saving texture %s\n", buffer);
2087 if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == D3DRTYPE_TEXTURE) {
2088 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
2089 IWineD3DSurface_SaveSnapshot(pSur, buffer);
2090 IWineD3DSurface_Release(pSur);
2091 } else {
2092 FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
2097 #endif
2099 TRACE("drawprim #%ld\n", primCounter);
2100 ++primCounter;
2102 #endif