Authors: Christian Costa <titan.costa@wanadoo.fr>, Jason Edmeades <us@the-edmeades...
[wine/multimedia.git] / dlls / d3d8 / drawprim.c
bloba14d549c8d8cc84a3bbd80f0a50f524348b9213c
1 /*
2 * D3D8 utils
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2002-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
25 #include <math.h>
26 #include <stdarg.h>
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "wine/debug.h"
36 #include "d3d8_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
39 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
41 extern IDirect3DVertexShaderImpl* VertexShaders[64];
42 extern IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
43 extern IDirect3DPixelShaderImpl* PixelShaders[64];
45 /* Useful holding place for 4 floats */
46 typedef struct _D3DVECTOR_4 {
47 float x;
48 float y;
49 float z;
50 float w;
51 } D3DVECTOR_4;
53 #undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
55 /* Returns bits for what is expected from the fixed function pipeline, and whether
56 a vertex shader will be in use. Note the fvf bits returned may be split over
57 multiple streams only if the vertex shader was created, otherwise it all relates
58 to stream 0 */
59 BOOL initializeFVF(LPDIRECT3DDEVICE8 iface,
60 DWORD *FVFbits, /* What to expect in the FVF across all streams */
61 BOOL *useVertexShaderFunction) /* Should we use the vertex shader */
64 ICOM_THIS(IDirect3DDevice8Impl,iface);
66 /* The first thing to work out is if we are using the fixed function pipeline
67 which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
68 is the FVF, or with a shader which was created with no function - in which
69 case there is an FVF per declared stream. If this occurs, we also maintain
70 an 'OR' of all the FVF's together so we know what to expect across all the
71 streams */
73 if (This->UpdateStateBlock->VertexShader <= VS_HIGHESTFIXEDFXF) {
75 /* Use this as the FVF */
76 *FVFbits = This->UpdateStateBlock->VertexShader;
77 *useVertexShaderFunction = FALSE;
78 TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
80 } else {
82 /* Use created shader */
83 IDirect3DVertexShaderImpl* vertex_shader = NULL;
84 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
86 if (vertex_shader == NULL) {
88 /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
89 ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
90 return TRUE;
92 } else {
94 *FVFbits = This->UpdateStateBlock->vertexShaderDecl->allFVF;
96 if (vertex_shader->function == NULL) {
97 /* No function, so many streams supplied plus FVF definition pre stream */
98 *useVertexShaderFunction = FALSE;
99 TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n",
100 This->StateBlock->VertexShader, *FVFbits);
101 } else {
102 /* Vertex shader needs calling */
103 *useVertexShaderFunction = TRUE;
104 TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
108 return FALSE;
111 /* Issues the glBegin call for gl given the primitive type and count */
112 DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
113 DWORD NumPrimitives,
114 GLenum *primType)
116 DWORD NumVertexes = NumPrimitives;
118 switch (PrimitiveType) {
119 case D3DPT_POINTLIST:
120 TRACE("POINTS\n");
121 *primType = GL_POINTS;
122 NumVertexes = NumPrimitives;
123 break;
125 case D3DPT_LINELIST:
126 TRACE("LINES\n");
127 *primType = GL_LINES;
128 NumVertexes = NumPrimitives * 2;
129 break;
131 case D3DPT_LINESTRIP:
132 TRACE("LINE_STRIP\n");
133 *primType = GL_LINE_STRIP;
134 NumVertexes = NumPrimitives + 1;
135 break;
137 case D3DPT_TRIANGLELIST:
138 TRACE("TRIANGLES\n");
139 *primType = GL_TRIANGLES;
140 NumVertexes = NumPrimitives * 3;
141 break;
143 case D3DPT_TRIANGLESTRIP:
144 TRACE("TRIANGLE_STRIP\n");
145 *primType = GL_TRIANGLE_STRIP;
146 NumVertexes = NumPrimitives + 2;
147 break;
149 case D3DPT_TRIANGLEFAN:
150 TRACE("TRIANGLE_FAN\n");
151 *primType = GL_TRIANGLE_FAN;
152 NumVertexes = NumPrimitives + 2;
153 break;
155 default:
156 FIXME("Unhandled primitive\n");
157 *primType = GL_POINTS;
158 break;
160 return NumVertexes;
163 /* Ensure the appropriate material states are set up - only change
164 state if really required */
165 void init_materials(LPDIRECT3DDEVICE8 iface, BOOL isDiffuseSupplied) {
167 BOOL requires_material_reset = FALSE;
168 ICOM_THIS(IDirect3DDevice8Impl,iface);
170 if (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == TRUE) {
171 /* If we have not set up the material color tracking, do it now as required */
172 glDisable(GL_COLOR_MATERIAL); /* Note: Man pages state must enable AFTER calling glColorMaterial! Required?*/
173 checkGLcall("glDisable GL_COLOR_MATERIAL");
174 TRACE("glColorMaterial Parm=%x\n", This->tracking_parm);
175 glColorMaterial(GL_FRONT_AND_BACK, This->tracking_parm);
176 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
177 glEnable(GL_COLOR_MATERIAL);
178 checkGLcall("glEnable GL_COLOR_MATERIAL");
179 This->tracking_color = IS_TRACKING;
180 requires_material_reset = TRUE; /* Restore material settings as will be used */
182 } else if ((This->tracking_color == IS_TRACKING && isDiffuseSupplied == FALSE) ||
183 (This->tracking_color == NEEDS_TRACKING && isDiffuseSupplied == FALSE)) {
184 /* If we are tracking the current color but one isn't supplied, don't! */
185 glDisable(GL_COLOR_MATERIAL);
186 checkGLcall("glDisable GL_COLOR_MATERIAL");
187 This->tracking_color = NEEDS_TRACKING;
188 requires_material_reset = TRUE; /* Restore material settings as will be used */
190 } else if (This->tracking_color == IS_TRACKING && isDiffuseSupplied == TRUE) {
191 /* No need to reset material colors since no change to gl_color_material */
192 requires_material_reset = FALSE;
194 } else if (This->tracking_color == NEEDS_DISABLE) {
195 glDisable(GL_COLOR_MATERIAL);
196 checkGLcall("glDisable GL_COLOR_MATERIAL");
197 This->tracking_color = DISABLED_TRACKING;
198 requires_material_reset = TRUE; /* Restore material settings as will be used */
201 /* Reset the material colors which may have been tracking the color*/
202 if (requires_material_reset == TRUE) {
203 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->StateBlock->material.Ambient);
204 checkGLcall("glMaterialfv");
205 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->StateBlock->material.Diffuse);
206 checkGLcall("glMaterialfv");
207 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
208 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->StateBlock->material.Specular);
209 checkGLcall("glMaterialfv");
210 } else {
211 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
212 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
213 checkGLcall("glMaterialfv");
215 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->StateBlock->material.Emissive);
216 checkGLcall("glMaterialfv");
221 static GLfloat invymat[16]={
222 1.0f, 0.0f, 0.0f, 0.0f,
223 0.0f, -1.0f, 0.0f, 0.0f,
224 0.0f, 0.0f, 1.0f, 0.0f,
225 0.0f, 0.0f, 0.0f, 1.0f};
227 /* Setup views - Transformed & lit if RHW, else untransformed.
228 Only unlit if Normals are supplied
229 Returns: Whether to restore lighting afterwards */
230 BOOL primitiveInitState(LPDIRECT3DDEVICE8 iface, BOOL vtx_transformed, BOOL vtx_lit, BOOL useVS) {
232 BOOL isLightingOn = FALSE;
233 ICOM_THIS(IDirect3DDevice8Impl,iface);
235 /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
236 set by the appropriate render state. Note Vertex Shader output is already lit */
237 if (vtx_lit || useVS) {
238 isLightingOn = glIsEnabled(GL_LIGHTING);
239 glDisable(GL_LIGHTING);
240 checkGLcall("glDisable(GL_LIGHTING);");
241 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
244 if (!useVS && vtx_transformed) {
246 /* If the last draw was transformed as well, no need to reapply all the matrixes */
247 if (!This->last_was_rhw) {
249 double X, Y, height, width, minZ, maxZ;
250 This->last_was_rhw = TRUE;
252 /* Transformed already into viewport coordinates, so we do not need transform
253 matrices. Reset all matrices to identity and leave the default matrix in world
254 mode. */
255 glMatrixMode(GL_MODELVIEW);
256 checkGLcall("glMatrixMode");
257 glLoadIdentity();
258 checkGLcall("glLoadIdentity");
260 glMatrixMode(GL_PROJECTION);
261 checkGLcall("glMatrixMode");
262 glLoadIdentity();
263 checkGLcall("glLoadIdentity");
265 /* Set up the viewport to be full viewport */
266 X = This->StateBlock->viewport.X;
267 Y = This->StateBlock->viewport.Y;
268 height = This->StateBlock->viewport.Height;
269 width = This->StateBlock->viewport.Width;
270 minZ = This->StateBlock->viewport.MinZ;
271 maxZ = This->StateBlock->viewport.MaxZ;
272 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
273 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
274 checkGLcall("glOrtho");
276 /* Window Coord 0 is the middle of the first pixel, so translate by half
277 a pixel (See comment above glTranslate below) */
278 glTranslatef(0.5, 0.5, 0);
279 checkGLcall("glTranslatef(0.5, 0.5, 0)");
280 if (This->renderUpsideDown) {
281 glMultMatrixf(invymat);
282 checkGLcall("glMultMatrixf(invymat)");
286 } else {
288 /* Untransformed, so relies on the view and projection matrices */
290 if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
291 /* Only reapply when have to */
292 This->modelview_valid = TRUE;
293 glMatrixMode(GL_MODELVIEW);
294 checkGLcall("glMatrixMode");
296 /* In the general case, the view matrix is the identity matrix */
297 if (This->view_ident) {
298 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
299 checkGLcall("glLoadMatrixf");
300 } else {
301 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
302 checkGLcall("glLoadMatrixf");
303 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
304 checkGLcall("glMultMatrixf");
308 if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
309 /* Only reapply when have to */
310 This->proj_valid = TRUE;
311 glMatrixMode(GL_PROJECTION);
312 checkGLcall("glMatrixMode");
314 /* The rule is that the window coordinate 0 does not correspond to the
315 beginning of the first pixel, but the center of the first pixel.
316 As a consequence if you want to correctly draw one line exactly from
317 the left to the right end of the viewport (with all matrices set to
318 be identity), the x coords of both ends of the line would be not
319 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
320 instead. */
321 glLoadIdentity();
322 glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
323 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
325 if (This->renderUpsideDown) {
326 glMultMatrixf(invymat);
327 checkGLcall("glMultMatrixf(invymat)");
329 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
330 checkGLcall("glLoadMatrixf");
333 /* Vertex Shader output is already transformed, so set up identity matrices */
334 /* FIXME: Actually, only true for software emulated ones, so when h/w ones
335 come along this needs to take into account whether s/w ones were
336 requested or not */
337 if (useVS) {
338 glMatrixMode(GL_MODELVIEW);
339 checkGLcall("glMatrixMode");
340 glLoadIdentity();
341 glMatrixMode(GL_PROJECTION);
342 checkGLcall("glMatrixMode");
343 glLoadIdentity();
344 /* Window Coord 0 is the middle of the first pixel, so translate by half
345 a pixel (See comment above glTranslate above) */
346 glTranslatef(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
347 checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
348 if (This->renderUpsideDown) {
349 glMultMatrixf(invymat);
350 checkGLcall("glMultMatrixf(invymat)");
352 This->modelview_valid = FALSE;
353 This->proj_valid = FALSE;
355 This->last_was_rhw = FALSE;
357 return isLightingOn;
360 void primitiveConvertToStridedData(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
362 short LoopThroughTo = 0;
363 short nStream;
364 BOOL canDoViaGLPointers = TRUE;
365 int numBlends;
366 int numTextures;
367 int textureNo;
368 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
369 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
371 ICOM_THIS(IDirect3DDevice8Impl,iface);
373 /* OK, Now to setup the data locations
374 For the non-created vertex shaders, the VertexShader var holds the real
375 FVF and only stream 0 matters
376 For the created vertex shaders, there is an FVF per stream */
377 if (!This->StateBlock->streamIsUP && (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF)) {
378 LoopThroughTo = MAX_STREAMS;
379 } else {
380 LoopThroughTo = 1;
383 /* Work through stream by stream */
384 for (nStream=0; nStream<LoopThroughTo; nStream++) {
385 DWORD stride = This->StateBlock->stream_stride[nStream];
386 BYTE *data = NULL;
387 DWORD thisFVF = 0;
389 /* Skip empty streams */
390 if (This->StateBlock->stream_source[nStream] == NULL) continue;
392 /* Retrieve appropriate FVF */
393 if (LoopThroughTo == 1) { /* VertexShader is FVF */
394 thisFVF = This->UpdateStateBlock->VertexShader;
395 /* Handle memory passed directly as well as vertex buffers */
396 if (This->StateBlock->streamIsUP == TRUE) {
397 data = (BYTE *)This->StateBlock->stream_source[nStream];
398 } else {
399 data = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
401 } else {
402 thisFVF = This->StateBlock->vertexShaderDecl->fvf[nStream];
403 data = ((IDirect3DVertexBuffer8Impl *)This->StateBlock->stream_source[nStream])->allocatedMemory;
405 VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
406 if (thisFVF == 0) continue;
408 /* Now convert the stream into pointers */
410 /* Shuffle to the beginning of the vertexes to render and index from there */
411 data = data + (BaseVertexIndex * stride);
413 /* Either 3 or 4 floats depending on the FVF */
414 /* FIXME: Can blending data be in a different stream to the position data?
415 and if so using the fixed pipeline how do we handle it */
416 if (thisFVF & D3DFVF_POSITION_MASK) {
417 strided->u.s.position.lpData = data;
418 strided->u.s.position.dwType = D3DVSDT_FLOAT3;
419 strided->u.s.position.dwStride = stride;
420 data += 3 * sizeof(float);
421 if (thisFVF & D3DFVF_XYZRHW) {
422 strided->u.s.position.dwType = D3DVSDT_FLOAT4;
423 data += sizeof(float);
427 /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
428 /** do we have to Check This->UpdateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
429 numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 +
430 ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1); /* WARNING can be < 0 because -2 */
431 if (numBlends > 0) {
432 canDoViaGLPointers = FALSE;
433 strided->u.s.blendWeights.lpData = data;
434 strided->u.s.blendWeights.dwType = D3DVSDT_FLOAT1 + (numBlends - 1);
435 strided->u.s.blendWeights.dwStride = stride;
436 data += numBlends * sizeof(FLOAT);
438 if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
439 strided->u.s.blendMatrixIndices.lpData = data;
440 strided->u.s.blendMatrixIndices.dwType = D3DVSDT_UBYTE4;
441 strided->u.s.blendMatrixIndices.dwStride= stride;
442 data += sizeof(DWORD);
446 /* Normal is always 3 floats */
447 if (thisFVF & D3DFVF_NORMAL) {
448 strided->u.s.normal.lpData = data;
449 strided->u.s.normal.dwType = D3DVSDT_FLOAT3;
450 strided->u.s.normal.dwStride = stride;
451 data += 3 * sizeof(FLOAT);
454 /* Pointsize is a single float */
455 if (thisFVF & D3DFVF_PSIZE) {
456 strided->u.s.pSize.lpData = data;
457 strided->u.s.pSize.dwType = D3DVSDT_FLOAT1;
458 strided->u.s.pSize.dwStride = stride;
459 data += sizeof(FLOAT);
462 /* Diffuse is 4 unsigned bytes */
463 if (thisFVF & D3DFVF_DIFFUSE) {
464 strided->u.s.diffuse.lpData = data;
465 strided->u.s.diffuse.dwType = D3DVSDT_SHORT4;
466 strided->u.s.diffuse.dwStride = stride;
467 data += sizeof(DWORD);
470 /* Specular is 4 unsigned bytes */
471 if (thisFVF & D3DFVF_SPECULAR) {
472 strided->u.s.specular.lpData = data;
473 strided->u.s.specular.dwType = D3DVSDT_SHORT4;
474 strided->u.s.specular.dwStride = stride;
475 data += sizeof(DWORD);
478 /* Texture coords */
479 numTextures = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
480 coordIdxInfo = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
482 /* numTextures indicates the number of texture coordinates supplied */
483 /* However, the first set may not be for stage 0 texture - it all */
484 /* depends on D3DTSS_TEXCOORDINDEX. */
485 /* The number of bytes for each coordinate set is based off */
486 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
488 /* So, for each supplied texture extract the coords */
489 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
491 strided->u.s.texCoords[textureNo].lpData = data;
492 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT1;
493 strided->u.s.texCoords[textureNo].dwStride = stride;
494 numCoords[textureNo] = coordIdxInfo & 0x03;
496 /* Always one set */
497 data += sizeof(float);
498 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
499 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT2;
500 data += sizeof(float);
501 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
502 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT3;
503 data += sizeof(float);
504 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
505 strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT4;
506 data += sizeof(float);
510 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
515 /* Draw a single vertex using this information */
516 void draw_vertex(LPDIRECT3DDEVICE8 iface, /* interface */
517 BOOL isXYZ, float x, float y, float z, float rhw, /* xyzn position*/
518 BOOL isNormal, float nx, float ny, float nz, /* normal */
519 BOOL isDiffuse, float *dRGBA, /* 1st colors */
520 BOOL isSpecular, float *sRGB, /* 2ndry colors */
521 BOOL isPtSize, float ptSize, /* pointSize */
522 D3DVECTOR_4 *texcoords, int *numcoords) /* texture info */
524 int textureNo;
525 float s, t, r, q;
526 ICOM_THIS(IDirect3DDevice8Impl,iface);
528 /* Diffuse -------------------------------- */
529 if (isDiffuse == TRUE) {
530 glColor4fv(dRGBA);
531 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
534 /* Specular Colour ------------------------------------------*/
535 if (isSpecular == TRUE) {
536 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
537 GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
538 VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
539 } else {
540 VTRACE(("Specular color extensions not supplied\n"));
544 /* Normal -------------------------------- */
545 if (isNormal == TRUE) {
546 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
547 glNormal3f(nx, ny, nz);
550 /* Point Size ----------------------------------------------*/
551 if (isPtSize == TRUE) {
553 /* no such functionality in the fixed function GL pipeline */
554 FIXME("Cannot change ptSize here in openGl\n");
557 /* Texture coords --------------------------- */
558 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
560 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
561 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
562 continue ;
565 /* Query tex coords */
566 if (This->StateBlock->textures[textureNo] != NULL) {
568 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
569 if (coordIdx > 7) {
570 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
571 continue;
572 } else if (numcoords[coordIdx] == 0) {
573 TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
574 continue;
575 } else {
577 /* Initialize vars */
578 s = 0.0f;
579 t = 0.0f;
580 r = 0.0f;
581 q = 0.0f;
583 switch (numcoords[coordIdx]) {
584 case 4: q = texcoords[coordIdx].w; /* drop through */
585 case 3: r = texcoords[coordIdx].z; /* drop through */
586 case 2: t = texcoords[coordIdx].y; /* drop through */
587 case 1: s = texcoords[coordIdx].x;
590 switch (numcoords[coordIdx]) { /* Supply the provided texture coords */
591 case D3DTTFF_COUNT1:
592 VTRACE(("tex:%d, s=%f\n", textureNo, s));
593 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
594 #if defined(GL_VERSION_1_3)
595 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
596 #else
597 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
598 #endif
599 } else {
600 glTexCoord1f(s);
602 break;
603 case D3DTTFF_COUNT2:
604 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
605 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
606 #if defined(GL_VERSION_1_3)
607 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
608 #else
609 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
610 #endif
611 } else {
612 glTexCoord2f(s, t);
614 break;
615 case D3DTTFF_COUNT3:
616 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
617 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
618 #if defined(GL_VERSION_1_3)
619 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
620 #else
621 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
622 #endif
623 } else {
624 glTexCoord3f(s, t, r);
626 break;
627 case D3DTTFF_COUNT4:
628 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
629 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
630 #if defined(GL_VERSION_1_3)
631 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
632 #else
633 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
634 #endif
635 } else {
636 glTexCoord4f(s, t, r, q);
638 break;
639 default:
640 FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
644 } /* End of textures */
646 /* Position -------------------------------- */
647 if (isXYZ == TRUE) {
648 if (1.0f == rhw || rhw < 0.00001f) {
649 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
650 glVertex3f(x, y, z);
651 } else {
652 /* Cannot optimize by dividing through by rhw as rhw is required
653 later for perspective in the GL pipeline for vertex shaders */
654 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
655 glVertex4f(x,y,z,rhw);
661 * Actually draw using the supplied information.
662 * Faster GL version using pointers to data, harder to debug though
663 * Note does not handle vertex shaders yet
665 void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
666 int PrimitiveType, ULONG NumPrimitives,
667 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
668 int textureNo = 0;
669 GLenum glPrimType = GL_POINTS;
670 int NumVertexes = NumPrimitives;
671 ICOM_THIS(IDirect3DDevice8Impl,iface);
673 TRACE("Using fast vertex array code\n");
675 /* Vertex Pointers -----------------------------------------*/
676 if (sd->u.s.position.lpData != NULL) {
678 /* Note dwType == float3 or float4 == 2 or 3 */
679 VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n",
680 sd->u.s.position.dwStride,
681 sd->u.s.position.dwType + 1,
682 sd->u.s.position.lpData));
684 /* Disable RHW mode as 'w' coord handling for rhw mode should
685 not impact screen position whereas in GL it does. This may
686 result in very slightly distored textures in rhw mode, but
687 a very minimal different */
688 glVertexPointer(3, GL_FLOAT, /* RHW: Was 'sd->u.s.position.dwType + 1' */
689 sd->u.s.position.dwStride,
690 sd->u.s.position.lpData);
691 checkGLcall("glVertexPointer(...)");
692 glEnableClientState(GL_VERTEX_ARRAY);
693 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
695 } else {
697 glDisableClientState(GL_VERTEX_ARRAY);
698 checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
701 /* Blend Data ----------------------------------------------*/
702 if ((sd->u.s.blendWeights.lpData != NULL) ||
703 (sd->u.s.blendMatrixIndices.lpData != NULL)) {
704 /* FIXME: Won't get here as will drop to slow method */
705 FIXME("Blending not supported in fast draw routine\n");
707 #if 0 /* Vertex blend support needs to be added */
708 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
709 /*FIXME("TODO\n");*/
710 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
711 /*FIXME("TODO\n");*/
713 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
714 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
715 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
716 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
718 } else {
719 FIXME("unsupported blending in openGl\n");
721 } else {
722 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
723 FIXME("TODO\n");
724 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
725 FIXME("TODO\n");
727 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
728 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
731 #endif
734 /* Normals -------------------------------------------------*/
735 if (sd->u.s.normal.lpData != NULL) {
737 /* Note dwType == float3 or float4 == 2 or 3 */
738 VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n",
739 sd->u.s.normal.dwStride,
740 sd->u.s.normal.lpData));
741 glNormalPointer(GL_FLOAT,
742 sd->u.s.normal.dwStride,
743 sd->u.s.normal.lpData);
744 checkGLcall("glNormalPointer(...)");
745 glEnableClientState(GL_NORMAL_ARRAY);
746 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
748 } else {
750 glDisableClientState(GL_NORMAL_ARRAY);
751 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
752 glNormal3f(0, 0, 1);
753 checkGLcall("glNormal3f(0, 0, 1)");
756 /* Point Size ----------------------------------------------*/
757 if (sd->u.s.pSize.lpData != NULL) {
759 /* no such functionality in the fixed function GL pipeline */
760 /* FIXME: Won't get here as will drop to slow method */
761 FIXME("Cannot change ptSize here in openGl\n");
764 /* Diffuse Colour ------------------------------------------*/
765 /* WARNING: Data here MUST be in RGBA format, so cannot */
766 /* go directly into fast mode from app pgm, because */
767 /* directx requires data in BGRA format. */
768 if (sd->u.s.diffuse.lpData != NULL) {
770 /* Note dwType == float3 or float4 == 2 or 3 */
771 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
772 sd->u.s.diffuse.dwStride,
773 sd->u.s.diffuse.lpData));
774 glColorPointer(4, GL_UNSIGNED_BYTE,
775 sd->u.s.diffuse.dwStride,
776 sd->u.s.diffuse.lpData);
777 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
778 glEnableClientState(GL_COLOR_ARRAY);
779 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
781 } else {
783 glDisableClientState(GL_COLOR_ARRAY);
784 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
785 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
786 checkGLcall("glColor4f(1, 1, 1, 1)");
789 /* Specular Colour ------------------------------------------*/
790 if (sd->u.s.specular.lpData != NULL) {
792 /* Note dwType == float3 or float4 == 2 or 3 */
793 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n",
794 sd->u.s.specular.dwStride,
795 sd->u.s.specular.lpData));
797 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
798 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
799 sd->u.s.specular.dwStride,
800 sd->u.s.specular.lpData);
801 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
802 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
803 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
804 } else {
805 /* Missing specular color is not critical, no warnings */
806 VTRACE(("Specular colour is not supported in this GL implementation\n"));
809 } else {
811 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
812 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
813 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
814 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
815 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
816 } else {
817 /* Missing specular color is not critical, no warnings */
818 VTRACE(("Specular colour is not supported in this GL implementation\n"));
822 /* Texture coords -------------------------------------------*/
823 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
825 /* Select the correct texture stage */
826 #if defined(GL_VERSION_1_3)
827 glClientActiveTexture(GL_TEXTURE0 + textureNo);
828 #else
829 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
830 #endif
832 /* Query tex coords */
833 if (This->StateBlock->textures[textureNo] != NULL) {
834 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
836 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
837 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
838 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
839 #if defined(GL_VERSION_1_3)
840 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
841 #else
842 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
843 #endif
844 continue;
847 if (coordIdx > 7) {
848 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
849 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
850 #if defined(GL_VERSION_1_3)
851 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
852 #else
853 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
854 #endif
855 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
856 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
857 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
858 #if defined(GL_VERSION_1_3)
859 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
860 #else
861 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
862 #endif
863 } else {
865 /* The coords to supply depend completely on the fvf / vertex shader */
866 GLint size;
867 GLenum type;
869 switch (sd->u.s.texCoords[coordIdx].dwType) {
870 case D3DVSDT_FLOAT1: size = 1, type = GL_FLOAT; break;
871 case D3DVSDT_FLOAT2: size = 2, type = GL_FLOAT; break;
872 case D3DVSDT_FLOAT3: size = 3, type = GL_FLOAT; break;
873 case D3DVSDT_FLOAT4: size = 4, type = GL_FLOAT; break;
874 case D3DVSDT_SHORT2: size = 2, type = GL_SHORT; break;
875 case D3DVSDT_SHORT4: size = 4, type = GL_SHORT; break;
876 case D3DVSDT_UBYTE4: size = 4, type = GL_UNSIGNED_BYTE; break;
877 default: FIXME("Unrecognized data type %ld\n", sd->u.s.texCoords[coordIdx].dwType);
878 size = 4; type = GL_UNSIGNED_BYTE;
881 glTexCoordPointer(size, type, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
882 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
884 } else {
885 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
886 #if defined(GL_VERSION_1_3)
887 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
888 #else
889 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
890 #endif
894 /* Ok, Work out which primitive is requested and how many vertexes that
895 will be */
896 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
898 /* Finally do the drawing */
899 if (idxData != NULL) {
901 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
902 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
903 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
904 (char *)idxData+(idxSize * startIdx));
905 #else
906 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
907 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
908 (char *)idxData+(idxSize * startIdx));
909 #endif
910 checkGLcall("glDrawRangeElements");
912 } else {
914 /* Note first is now zero as we shuffled along earlier */
915 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
916 glDrawArrays(glPrimType, 0, NumVertexes);
917 checkGLcall("glDrawArrays");
923 * Actually draw using the supplied information.
924 * Slower GL version which extracts info about each vertex in turn
926 void drawStridedSlow(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
927 int PrimitiveType, ULONG NumPrimitives,
928 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
930 int textureNo = 0;
931 GLenum glPrimType = GL_POINTS;
932 int NumVertexes = NumPrimitives;
933 const short *pIdxBufS = NULL;
934 const long *pIdxBufL = NULL;
935 LONG SkipnStrides = 0;
936 LONG vx_index;
937 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
938 float nx = 0.0f, ny = 0.0, nz = 0.0f; /* normal x,y,z coordinates */
939 float rhw = 0.0f; /* rhw */
940 float ptSize = 0.0f; /* Point size */
941 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
942 DWORD specularColor = 0; /* Specular Color */
943 ICOM_THIS(IDirect3DDevice8Impl,iface);
945 TRACE("Using slow vertex array code\n");
947 /* Variable Initialization */
948 if (idxData != NULL) {
949 if (idxSize == 2) pIdxBufS = (short *) idxData;
950 else pIdxBufL = (long *) idxData;
953 /* Ok, Work out which primitive is requested and how many vertexes that will be */
954 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
956 /* Start drawing in GL */
957 VTRACE(("glBegin(%x)\n", glPrimType));
958 glBegin(glPrimType);
960 /* For each primitive */
961 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
963 /* Initialize diffuse color */
964 diffuseColor = 0xFFFFFFFF;
966 /* For indexed data, we need to go a few more strides in */
967 if (idxData != NULL) {
969 /* Indexed so work out the number of strides to skip */
970 if (idxSize == 2) {
971 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
972 SkipnStrides = pIdxBufS[startIdx+vx_index];
973 } else {
974 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
975 SkipnStrides = pIdxBufL[startIdx+vx_index];
979 /* Position Information ------------------ */
980 if (sd->u.s.position.lpData != NULL) {
982 float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
983 x = ptrToCoords[0];
984 y = ptrToCoords[1];
985 z = ptrToCoords[2];
986 rhw = 1.0;
987 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
989 /* RHW follows, only if transformed, ie 4 floats were provided */
990 if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
991 rhw = ptrToCoords[3];
992 VTRACE(("rhw=%f\n", rhw));
996 /* Blending data -------------------------- */
997 if (sd->u.s.blendWeights.lpData != NULL) {
998 /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
999 FIXME("Blending not supported yet\n");
1001 if (sd->u.s.blendMatrixIndices.lpData != NULL) {
1002 /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
1006 /* Vertex Normal Data (untransformed only)- */
1007 if (sd->u.s.normal.lpData != NULL) {
1009 float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
1010 nx = ptrToCoords[0];
1011 ny = ptrToCoords[1];
1012 nz = ptrToCoords[2];
1013 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
1016 /* Point Size ----------------------------- */
1017 if (sd->u.s.pSize.lpData != NULL) {
1019 float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
1020 ptSize = ptrToCoords[0];
1021 VTRACE(("ptSize=%f\n", ptSize));
1022 FIXME("No support for ptSize yet\n");
1025 /* Diffuse -------------------------------- */
1026 if (sd->u.s.diffuse.lpData != NULL) {
1028 DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
1029 diffuseColor = ptrToCoords[0];
1030 VTRACE(("diffuseColor=%lx\n", diffuseColor));
1033 /* Specular -------------------------------- */
1034 if (sd->u.s.specular.lpData != NULL) {
1036 DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
1037 specularColor = ptrToCoords[0];
1038 VTRACE(("specularColor=%lx\n", specularColor));
1041 /* Texture coords --------------------------- */
1042 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1044 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
1045 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1046 continue ;
1049 /* Query tex coords */
1050 if (This->StateBlock->textures[textureNo] != NULL) {
1052 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
1053 float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
1054 float s = 0.0, t = 0.0, r = 0.0, q = 0.0;
1056 if (coordIdx > 7) {
1057 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
1058 continue;
1059 } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
1060 TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
1061 continue;
1062 } else {
1064 int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
1066 /* The coords to supply depend completely on the fvf / vertex shader */
1067 switch (coordsToUse) {
1068 case 4: q = ptrToCoords[3]; /* drop through */
1069 case 3: r = ptrToCoords[2]; /* drop through */
1070 case 2: t = ptrToCoords[1]; /* drop through */
1071 case 1: s = ptrToCoords[0];
1074 /* Projected is more 'fun' - Move the last coord to the 'q'
1075 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
1076 if ((This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) &&
1077 (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
1079 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
1080 switch (coordsToUse) {
1081 case 0: /* Drop Through */
1082 case 1:
1083 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
1084 break;
1085 case 2:
1086 q = t;
1087 t = 0.0;
1088 coordsToUse = 4;
1089 break;
1090 case 3:
1091 q = r;
1092 r = 0.0;
1093 coordsToUse = 4;
1094 break;
1095 case 4: /* Nop here */
1096 break;
1097 default:
1098 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
1099 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
1104 switch (coordsToUse) { /* Supply the provided texture coords */
1105 case D3DTTFF_COUNT1:
1106 VTRACE(("tex:%d, s=%f\n", textureNo, s));
1107 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1108 #if defined(GL_VERSION_1_3)
1109 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
1110 #else
1111 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
1112 #endif
1113 } else {
1114 glTexCoord1f(s);
1116 break;
1117 case D3DTTFF_COUNT2:
1118 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
1119 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1120 #if defined(GL_VERSION_1_3)
1121 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
1122 #else
1123 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
1124 #endif
1125 } else {
1126 glTexCoord2f(s, t);
1128 break;
1129 case D3DTTFF_COUNT3:
1130 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
1131 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1132 #if defined(GL_VERSION_1_3)
1133 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
1134 #else
1135 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
1136 #endif
1137 } else {
1138 glTexCoord3f(s, t, r);
1140 break;
1141 case D3DTTFF_COUNT4:
1142 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
1143 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1144 #if defined(GL_VERSION_1_3)
1145 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
1146 #else
1147 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
1148 #endif
1149 } else {
1150 glTexCoord4f(s, t, r, q);
1152 break;
1153 default:
1154 FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
1158 } /* End of textures */
1160 /* Diffuse -------------------------------- */
1161 if (sd->u.s.diffuse.lpData != NULL) {
1162 glColor4ub((diffuseColor >> 16) & 0xFF,
1163 (diffuseColor >> 8) & 0xFF,
1164 (diffuseColor >> 0) & 0xFF,
1165 (diffuseColor >> 24) & 0xFF);
1166 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
1167 ((diffuseColor >> 16) & 0xFF) / 255.0f,
1168 ((diffuseColor >> 8) & 0xFF) / 255.0f,
1169 ((diffuseColor >> 0) & 0xFF) / 255.0f,
1170 ((diffuseColor >> 24) & 0xFF) / 255.0f));
1171 } else {
1172 if (vx_index == 0) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1175 /* Specular ------------------------------- */
1176 if (sd->u.s.diffuse.lpData != NULL) {
1177 VTRACE(("glSecondaryColor4ub: r,g,b=%f,%f,%f\n",
1178 ((specularColor >> 16) & 0xFF) / 255.0f,
1179 ((specularColor >> 8) & 0xFF) / 255.0f,
1180 ((specularColor >> 0) & 0xFF) / 255.0f));
1181 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1182 GL_EXTCALL(glSecondaryColor3ubEXT)(
1183 (specularColor >> 16) & 0xFF,
1184 (specularColor >> 8) & 0xFF,
1185 (specularColor >> 0) & 0xFF);
1186 } else {
1187 /* Do not worry if specular colour missing and disable request */
1188 VTRACE(("Specular color extensions not supplied\n"));
1190 } else {
1191 if (vx_index == 0) {
1192 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1193 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
1194 } else {
1195 /* Do not worry if specular colour missing and disable request */
1196 VTRACE(("Specular color extensions not supplied\n"));
1201 /* Normal -------------------------------- */
1202 if (sd->u.s.normal.lpData != NULL) {
1203 VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
1204 glNormal3f(nx, ny, nz);
1205 } else {
1206 if (vx_index == 0) glNormal3f(0, 0, 1);
1209 /* Position -------------------------------- */
1210 if (sd->u.s.position.lpData != NULL) {
1211 if (1.0f == rhw || rhw < 0.0001f) {
1212 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
1213 glVertex3f(x, y, z);
1214 } else {
1215 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
1216 /* Disable RHW mode as 'w' coord handling for rhw mode should
1217 not impact screen position whereas in GL it does. This may
1218 result in very slightly distored textures in rhw mode, but
1219 a very minimal different. In slow mode a possible 'fix' is
1220 glVertex4f(x*rhw,y*rhw,z*rhw,rhw) but not sure this is right */
1221 glVertex3f(x,y,z);
1225 /* For non indexed mode, step onto next parts */
1226 if (idxData == NULL) {
1227 SkipnStrides += 1;
1231 glEnd();
1232 checkGLcall("glEnd and previous calls");
1236 * Draw with emulated vertex shaders
1237 * Note: strided data is uninitialized, as we need to pass the vertex
1238 * shader directly as ordering irs yet
1240 void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
1241 int PrimitiveType, ULONG NumPrimitives,
1242 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1244 int textureNo = 0;
1245 GLenum glPrimType = GL_POINTS;
1246 int NumVertexes = NumPrimitives;
1247 const short *pIdxBufS = NULL;
1248 const long *pIdxBufL = NULL;
1249 LONG SkipnStrides = 0;
1250 LONG vx_index;
1251 float x = 0.0f, y = 0.0f, z = 0.0f; /* x,y,z coordinates */
1252 float rhw = 0.0f; /* rhw */
1253 float ptSize = 0.0f; /* Point size */
1254 D3DVECTOR_4 texcoords[8]; /* Texture Coords */
1255 int numcoords[8]; /* Number of coords */
1256 ICOM_THIS(IDirect3DDevice8Impl,iface);
1258 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1260 TRACE("Using slow software vertex shader code\n");
1262 /* Variable Initialization */
1263 if (idxData != NULL) {
1264 if (idxSize == 2) pIdxBufS = (short *) idxData;
1265 else pIdxBufL = (long *) idxData;
1268 /* Ok, Work out which primitive is requested and how many vertexes that will be */
1269 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1271 /* Retrieve the VS information */
1272 vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1274 /* Start drawing in GL */
1275 VTRACE(("glBegin(%x)\n", glPrimType));
1276 glBegin(glPrimType);
1278 /* For each primitive */
1279 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
1281 /* For indexed data, we need to go a few more strides in */
1282 if (idxData != NULL) {
1284 /* Indexed so work out the number of strides to skip */
1285 if (idxSize == 2) {
1286 VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
1287 SkipnStrides = pIdxBufS[startIdx+vx_index];
1288 } else {
1289 VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
1290 SkipnStrides = pIdxBufL[startIdx+vx_index];
1294 /* Fill the vertex shader input */
1295 IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides);
1297 /* Initialize the output fields to the same defaults as it would normally have */
1298 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
1299 vertex_shader->output.oD[0].x = 1.0;
1300 vertex_shader->output.oD[0].y = 1.0;
1301 vertex_shader->output.oD[0].z = 1.0;
1302 vertex_shader->output.oD[0].w = 1.0;
1304 /* Now execute the vertex shader */
1305 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
1308 TRACE_VECTOR(vertex_shader->output.oPos);
1309 TRACE_VECTOR(vertex_shader->output.oD[0]);
1310 TRACE_VECTOR(vertex_shader->output.oD[1]);
1311 TRACE_VECTOR(vertex_shader->output.oT[0]);
1312 TRACE_VECTOR(vertex_shader->output.oT[1]);
1313 TRACE_VECTOR(vertex_shader->input.V[0]);
1314 TRACE_VECTOR(vertex_shader->data->C[0]);
1315 TRACE_VECTOR(vertex_shader->data->C[1]);
1316 TRACE_VECTOR(vertex_shader->data->C[2]);
1317 TRACE_VECTOR(vertex_shader->data->C[3]);
1318 TRACE_VECTOR(vertex_shader->data->C[4]);
1319 TRACE_VECTOR(vertex_shader->data->C[5]);
1320 TRACE_VECTOR(vertex_shader->data->C[6]);
1321 TRACE_VECTOR(vertex_shader->data->C[7]);
1324 /* Extract out the output */
1325 /*FIXME: Fog coords? */
1326 x = vertex_shader->output.oPos.x;
1327 y = vertex_shader->output.oPos.y;
1328 z = vertex_shader->output.oPos.z;
1329 rhw = vertex_shader->output.oPos.w;
1330 ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
1332 /** Update textures coords using vertex_shader->output.oT[0->7] */
1333 memset(texcoords, 0x00, sizeof(texcoords));
1334 memset(numcoords, 0x00, sizeof(numcoords));
1335 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1336 if (This->StateBlock->textures[textureNo] != NULL) {
1337 texcoords[textureNo].x = vertex_shader->output.oT[textureNo].x;
1338 texcoords[textureNo].y = vertex_shader->output.oT[textureNo].y;
1339 texcoords[textureNo].z = vertex_shader->output.oT[textureNo].z;
1340 texcoords[textureNo].w = vertex_shader->output.oT[textureNo].w;
1341 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
1342 numcoords[textureNo] = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
1343 } else {
1344 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
1345 case D3DRTYPE_TEXTURE: numcoords[textureNo] = 2; break;
1346 case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo] = 3; break;
1347 default: numcoords[textureNo] = 4;
1350 } else {
1351 numcoords[textureNo] = 0;
1355 /* Draw using this information */
1356 draw_vertex(iface,
1357 TRUE, x, y, z, rhw,
1358 TRUE, 0.0f, 0.0f, 1.0f,
1359 TRUE, (float*) &vertex_shader->output.oD[0],
1360 TRUE, (float*) &vertex_shader->output.oD[1],
1361 FALSE, ptSize, /* FIXME: Change back when supported */
1362 texcoords, numcoords);
1364 /* For non indexed mode, step onto next parts */
1365 if (idxData == NULL) {
1366 SkipnStrides += 1;
1369 } /* for each vertex */
1371 glEnd();
1372 checkGLcall("glEnd and previous calls");
1375 void drawStridedHardwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd,
1376 int PrimitiveType, ULONG NumPrimitives,
1377 const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
1379 IDirect3DVertexShaderImpl* vertex_shader = NULL;
1380 int i;
1381 int NumVertexes;
1382 int glPrimType;
1383 int maxAttribs;
1385 ICOM_THIS(IDirect3DDevice8Impl,iface);
1386 TRACE("Drawing with hardware vertex shaders\n");
1388 /* Retrieve the VS information */
1389 vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader);
1391 /* Enable the Vertex Shader */
1392 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId));
1393 checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);");
1394 glEnable(GL_VERTEX_PROGRAM_ARB);
1395 checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
1397 /* Update the constants */
1398 for (i=0; i<D3D8_VSHADER_MAX_CONSTANTS; i++) {
1399 GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, (GLfloat *)&This->StateBlock->vertexShaderConstant[i]));
1400 checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
1403 /* Set up the vertex.attr[n] inputs */
1404 IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0);
1406 /* Ok, Work out which primitive is requested and how many vertexes that
1407 will be */
1408 NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
1410 /* Finally do the drawing */
1411 if (idxData != NULL) {
1413 TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
1414 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
1415 glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1416 (char *)idxData+(idxSize * startIdx));
1417 #else
1418 glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes,
1419 idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT,
1420 (char *)idxData+(idxSize * startIdx));
1421 #endif
1422 checkGLcall("glDrawRangeElements");
1424 } else {
1426 /* Note first is now zero as we shuffled along earlier */
1427 TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
1428 glDrawArrays(glPrimType, 0, NumVertexes);
1429 checkGLcall("glDrawArrays");
1434 GLint errPos;
1435 glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
1436 if (errPos != -1)
1437 FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) );
1441 /* Leave all the attribs disabled */
1442 glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
1443 /* MESA does not support it right not */
1444 if (glGetError() != GL_NO_ERROR)
1445 maxAttribs = 16;
1446 for (i=0; i<maxAttribs; i++) {
1447 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
1448 checkGLcall("glDisableVertexAttribArrayARB(reg);");
1451 /* Done */
1452 glDisable(GL_VERTEX_PROGRAM_ARB);
1455 /* Routine common to the draw primitive and draw indexed primitive routines */
1456 void drawPrimitive(LPDIRECT3DDEVICE8 iface,
1457 int PrimitiveType, long NumPrimitives,
1459 /* for Indexed: */
1460 long StartVertexIndex,
1461 long StartIdx,
1462 short idxSize,
1463 const void *idxData,
1464 int minIndex) {
1466 BOOL rc = FALSE;
1467 DWORD fvf = 0;
1468 IDirect3DVertexShaderImpl *vertex_shader = NULL;
1469 BOOL useVertexShaderFunction = FALSE;
1470 BOOL isLightingOn = FALSE;
1471 Direct3DVertexStridedData dataLocations;
1472 ICOM_THIS(IDirect3DDevice8Impl,iface);
1473 int i;
1474 int useHW = FALSE;
1476 /* Work out what the FVF should look like */
1477 rc = initializeFVF(iface, &fvf, &useVertexShaderFunction);
1478 if (rc) return;
1480 /* If we will be using a vertex shader, do some initialization for it */
1481 if (useVertexShaderFunction == TRUE) {
1482 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
1483 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
1485 useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) &&
1486 This->devType != D3DDEVTYPE_REF &&
1487 !This->StateBlock->renderstate[D3DRS_SOFTWAREVERTEXPROCESSING] &&
1488 vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING);
1490 /** init Constants */
1491 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
1492 TRACE_(d3d_shader)("vertex shader initializing constants\n");
1493 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
1497 /* Ok, we will be updating the screen from here onwards so grab the lock */
1498 ENTER_GL();
1500 /* Setup transform matrices and sort out */
1501 if (useHW) {
1502 /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect...
1503 So make sure lighting is disabled. */
1504 isLightingOn = glIsEnabled(GL_LIGHTING);
1505 glDisable(GL_LIGHTING);
1506 checkGLcall("glDisable(GL_LIGHTING);");
1507 TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
1508 } else
1509 isLightingOn = primitiveInitState(iface,
1510 fvf & D3DFVF_XYZRHW,
1511 !(fvf & D3DFVF_NORMAL),
1512 useVertexShaderFunction);
1514 /* Initialize all values to null */
1515 if (useVertexShaderFunction == FALSE) {
1516 memset(&dataLocations, 0x00, sizeof(dataLocations));
1518 /* Convert to strided data */
1519 primitiveConvertToStridedData(iface, &dataLocations, StartVertexIndex);
1521 /* Dump out what parts we have supplied */
1522 TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
1523 TRACE_STRIDED((&dataLocations), position);
1524 TRACE_STRIDED((&dataLocations), blendWeights);
1525 TRACE_STRIDED((&dataLocations), blendMatrixIndices);
1526 TRACE_STRIDED((&dataLocations), normal);
1527 TRACE_STRIDED((&dataLocations), pSize);
1528 TRACE_STRIDED((&dataLocations), diffuse);
1529 TRACE_STRIDED((&dataLocations), specular);
1530 TRACE_STRIDED((&dataLocations), texCoords[0]);
1531 TRACE_STRIDED((&dataLocations), texCoords[1]);
1532 TRACE_STRIDED((&dataLocations), texCoords[2]);
1533 TRACE_STRIDED((&dataLocations), texCoords[3]);
1534 TRACE_STRIDED((&dataLocations), texCoords[4]);
1535 TRACE_STRIDED((&dataLocations), texCoords[5]);
1536 TRACE_STRIDED((&dataLocations), texCoords[6]);
1537 TRACE_STRIDED((&dataLocations), texCoords[7]);
1540 /* Now initialize the materials state */
1541 init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
1543 /* And re-upload any dirty textures */
1544 for (i=0; i<GL_LIMITS(textures); i++) {
1546 if ((This->StateBlock->textures[i] != NULL) &&
1547 (IDirect3DBaseTexture8Impl_IsDirty(This->StateBlock->textures[i])))
1549 /* Load up the texture now */
1550 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) This->StateBlock->textures[i]);
1554 /* Now draw the graphics to the screen */
1555 if (useVertexShaderFunction == TRUE) {
1557 /* Ideally, we should have software FV and hardware VS, possibly
1558 depending on the device type? */
1560 if (useHW) {
1561 TRACE("Swap HW vertex shader\n");
1562 drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1563 idxData, idxSize, minIndex, StartIdx);
1564 } else {
1565 /* We will have to use the very, very slow emulation layer */
1566 TRACE("Swap SW vertex shader\n");
1567 drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives,
1568 idxData, idxSize, minIndex, StartIdx);
1571 } else if ((dataLocations.u.s.pSize.lpData != NULL) ||
1572 (dataLocations.u.s.diffuse.lpData != NULL) ||
1573 (dataLocations.u.s.blendWeights.lpData != NULL)) {
1575 /* Fixme, Ideally, only use the per-vertex code for software HAL
1576 but until opengl supports all the functions returned to setup
1577 vertex arrays, we need to drop down to the slow mechanism for
1578 certain functions */
1580 /* We will have to use the slow version of GL per vertex setup */
1581 drawStridedSlow(iface, &dataLocations, PrimitiveType, NumPrimitives,
1582 idxData, idxSize, minIndex, StartIdx);
1584 } else {
1586 /* We can use the fast version of GL pointers */
1587 drawStridedFast(iface, &dataLocations, PrimitiveType, NumPrimitives,
1588 idxData, idxSize, minIndex, StartIdx);
1591 /* If vertex shaders or no normals, restore previous lighting state */
1592 if (useVertexShaderFunction || !(fvf & D3DFVF_NORMAL)) {
1593 if (isLightingOn) glEnable(GL_LIGHTING);
1594 else glDisable(GL_LIGHTING);
1595 TRACE("Restored lighting to original state\n");
1598 /* Finshed updating the screen, restore lock */
1599 LEAVE_GL();
1600 TRACE("Done all gl drawing\n");
1602 /* Diagnostics */
1603 #if defined(SHOW_FRAME_MAKEUP)
1605 if (isDumpingFrames == TRUE) {
1606 D3DLOCKED_RECT r;
1607 char buffer[80];
1608 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->renderTarget, &r, NULL, D3DLOCK_READONLY);
1609 sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter);
1610 TRACE("Saving screenshot %s\n", buffer);
1611 IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->renderTarget, buffer);
1612 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->renderTarget);
1614 #if defined(SHOW_TEXTURE_MAKEUP)
1616 LPDIRECT3DSURFACE8 pSur;
1617 int textureNo;
1618 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
1619 if (This->StateBlock->textures[textureNo] != NULL) {
1620 sprintf(buffer, "/tmp/texture_%ld_%d.ppm", primCounter, textureNo);
1621 TRACE("Saving texture %s (Format:%s)\n", buffer, debug_d3dformat(((IDirect3DBaseTexture8Impl *)This->StateBlock->textures[textureNo])->format));
1622 IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) This->StateBlock->textures[textureNo], 0, &pSur);
1623 IDirect3DSurface8Impl_SaveSnapshot(pSur, buffer);
1624 IDirect3DSurface8Impl_Release(pSur);
1628 #endif
1629 primCounter = primCounter + 1;
1632 #endif