- some cleanup and warning fixes
[wine/hacks.git] / dlls / d3d8 / device.c
blobc200d40890baf8890e49a682baf3ef2aec7fa47f
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <math.h>
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "wine/debug.h"
33 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
34 /*#define GL_GLEXT_PROTOTYPES*/
35 #include "d3d8_private.h"
37 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
38 #undef GL_VERSION_1_4
40 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
41 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
43 /* Some #defines for additional diagnostics */
45 /* Per-vertex trace: */
46 #if 0
47 # define VTRACE(A) TRACE A
48 #else
49 # define VTRACE(A)
50 #endif
53 static IDirect3DVertexShaderImpl* VertexShaders[64];
54 static IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
55 static IDirect3DPixelShaderImpl* PixelShaders[64];
57 /* CreateVertexShader can return > 0xFFFF */
58 #define VS_HIGHESTFIXEDFXF 0xF0000000
61 * Utility functions or macros
63 #define conv_mat(mat,gl_mat) \
64 do { \
65 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
66 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
68 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
69 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
70 } while (0)
72 #define VERTEX_SHADER(Handle) \
73 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
74 #define VERTEX_SHADER_DECL(Handle) \
75 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
76 #define PIXEL_SHADER(Handle) \
77 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
79 #define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
81 /* Routine common to the draw primitive and draw indexed primitive routines */
82 void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
83 int PrimitiveType,
84 long NumPrimitives,
85 BOOL isIndexed,
87 /* For Both:*/
88 D3DFORMAT fvf,
89 const void *vertexBufData,
91 /* for Indexed: */
92 long StartVertexIndex,
93 long StartIdx,
94 short idxBytes,
95 const void *idxData,
96 int minIndex) {
98 int NumVertexes = NumPrimitives;
99 IDirect3DVertexShaderImpl* vertex_shader = NULL;
100 BOOL useVertexShaderFunction = FALSE;
102 ICOM_THIS(IDirect3DDevice8Impl,iface);
104 /* Dont understand how to handle multiple streams, but if a fixed
105 FVF is passed in rather than a handle, it must use stream 0 */
107 if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
108 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
109 if (NULL == vertex_shader) {
110 ERR_(d3d_shader)("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
111 return ;
113 if (NULL == vertex_shader->function) {
114 TRACE_(d3d_shader)("vertex shader declared without program, using FVF pure mode\n");
115 } else {
116 useVertexShaderFunction = TRUE;
118 fvf = (D3DFORMAT) This->UpdateStateBlock->vertexShaderDecl->fvf;
119 TRACE_(d3d_shader)("vertex shader declared FVF: %08lx\n", This->UpdateStateBlock->vertexShaderDecl->fvf);
120 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
122 /** init Constants */
123 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
124 TRACE_(d3d_shader)("vertex shader init Constant\n");
125 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
131 int skip = This->StateBlock->stream_stride[0];
132 GLenum primType = GL_POINTS;
133 BOOL normal;
134 BOOL isRHW;
135 BOOL isPtSize;
136 BOOL isDiffuse;
137 BOOL isSpecular;
138 int numBlends;
139 BOOL isLastUByte4;
140 int numTextures;
141 int textureNo;
142 const char *curVtx = NULL;
143 const short *pIdxBufS = NULL;
144 const long *pIdxBufL = NULL;
145 const char *curPos;
146 BOOL isLightingOn = FALSE;
147 int vx_index;
148 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
149 float s[8], t[8], r[8], q[8]; /* Holding place for tex coords */
150 const char *coordPtr[8]; /* Holding place for the ptr to tex coords */
151 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
154 float x = 0.0f,
155 y = 0.0f,
156 z = 0.0f; /* x,y,z coordinates */
157 float nx = 0.0f,
158 ny =0.0,
159 nz = 0.0f; /* normal x,y,z coordinates */
160 float rhw = 0.0f; /* rhw */
161 float ptSize = 0.0f; /* Point size */
162 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
163 DWORD specularColor = 0; /* Specular Color */
165 ENTER_GL();
167 if (isIndexed) {
168 if (idxBytes == 2) pIdxBufS = (short *) idxData;
169 else pIdxBufL = (long *) idxData;
172 /* Check vertex formats expected ? */
173 /**
174 * FVF parser as seen it
175 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp
177 normal = fvf & D3DFVF_NORMAL;
178 isRHW = fvf & D3DFVF_XYZRHW;
179 isLastUByte4 = fvf & D3DFVF_LASTBETA_UBYTE4;
180 numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */
181 isPtSize = fvf & D3DFVF_PSIZE;
182 isDiffuse = fvf & D3DFVF_DIFFUSE;
183 isSpecular = fvf & D3DFVF_SPECULAR;
184 numTextures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
185 coordIdxInfo = (fvf & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
187 TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d, coordIdxInfo=%x)\n",
188 fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends, coordIdxInfo);
190 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
191 set by the appropriate render state */
192 if (!normal) {
193 isLightingOn = glIsEnabled(GL_LIGHTING);
194 glDisable(GL_LIGHTING);
195 TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
198 if (isRHW) {
199 double X, Y, height, width, minZ, maxZ;
201 * Already transformed vertex do not need transform
202 * matrices. Reset all matrices to identity.
203 * Leave the default matrix in world mode.
205 glMatrixMode(GL_MODELVIEW);
206 checkGLcall("glMatrixMode");
207 glLoadIdentity();
208 checkGLcall("glLoadIdentity");
210 * As seen in d3d7 code:
211 * See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
212 * Correctness Tips section).
214 glTranslatef(0.375f, 0.375f, 0.0f);
218 glMatrixMode(GL_PROJECTION);
219 checkGLcall("glMatrixMode");
220 glLoadIdentity();
221 checkGLcall("glLoadIdentity");
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(0.0, width, height, 0.0, -minZ, -maxZ);*/
230 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
231 checkGLcall("glOrtho");
232 } else {
233 double X, Y, height, width;
234 X = This->StateBlock->viewport.X;
235 Y = This->StateBlock->viewport.Y;
236 height = This->StateBlock->viewport.Height;
237 width = This->StateBlock->viewport.Width;
239 glMatrixMode(GL_MODELVIEW);
240 checkGLcall("glMatrixMode");
241 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
242 checkGLcall("glLoadMatrixf");
243 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
244 checkGLcall("glMultMatrixf");
246 #if 0
248 * OpenGL seems to map font between pixels
249 * well with this it seems better but not perfect
250 * anyone have a better idea ?
252 glTranslatef(0.8f / width, -0.8f / height, 0.0f);
256 #endif
258 glMatrixMode(GL_PROJECTION);
259 checkGLcall("glMatrixMode");
260 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
261 checkGLcall("glLoadMatrixf");
264 /* Set OpenGL to the appropriate Primitive Type */
265 switch (PrimitiveType) {
266 case D3DPT_POINTLIST:
267 TRACE("POINTS\n");
268 primType = GL_POINTS;
269 NumVertexes = NumPrimitives;
270 break;
272 case D3DPT_LINELIST:
273 TRACE("LINES\n");
274 primType = GL_LINES;
275 NumVertexes = NumPrimitives * 2;
276 break;
278 case D3DPT_LINESTRIP:
279 TRACE("LINE_STRIP\n");
280 primType = GL_LINE_STRIP;
281 NumVertexes = NumPrimitives + 1;
282 break;
284 case D3DPT_TRIANGLELIST:
285 TRACE("TRIANGLES\n");
286 primType = GL_TRIANGLES;
287 NumVertexes = NumPrimitives * 3;
288 break;
290 case D3DPT_TRIANGLESTRIP:
291 TRACE("TRIANGLE_STRIP\n");
292 primType = GL_TRIANGLE_STRIP;
293 NumVertexes = NumPrimitives + 2;
294 break;
296 case D3DPT_TRIANGLEFAN:
297 TRACE("TRIANGLE_FAN\n");
298 primType = GL_TRIANGLE_FAN;
299 NumVertexes = NumPrimitives + 2;
300 break;
302 default:
303 FIXME("Unhandled primitive\n");
304 break;
307 /* Fixme, Ideally, only use this per-vertex code for software HAL
308 but until opengl supports all the functions returned to setup
309 vertex arrays, we need to drop down to the slow mechanism for
310 certain functions */
312 if (isPtSize || isDiffuse || useVertexShaderFunction == TRUE || (numBlends > 0)) {
313 TRACE("Using slow per-vertex code\n");
315 /* Enable this one to be able to debug what is going on, but it is slower
316 than the pointer/array version */
317 VTRACE(("glBegin(%x)\n", primType));
318 glBegin(primType);
320 /* Draw the primitives */
321 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
323 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
325 if (!isIndexed) {
326 curPos = curVtx;
327 } else {
328 if (idxBytes == 2) {
329 VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
330 curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
331 } else {
332 VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
333 curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
337 /* Work through the vertex buffer */
338 x = *(float *)curPos;
339 curPos = curPos + sizeof(float);
340 y = *(float *)curPos;
341 curPos = curPos + sizeof(float);
342 z = *(float *)curPos;
343 curPos = curPos + sizeof(float);
344 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
346 /* RHW follows, only if transformed */
347 if (isRHW) {
348 rhw = *(float *)curPos;
349 curPos = curPos + sizeof(float);
350 VTRACE(("rhw=%f\n", rhw));
353 /* Blending data */
354 if (numBlends > 0) {
355 UINT i;
356 D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
357 DWORD skippedBlendLastUByte4 = 0;
359 for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
360 ((float*)&skippedBlend)[i] = *(float *)curPos;
361 curPos = curPos + sizeof(float);
364 if (isLastUByte4) {
365 skippedBlendLastUByte4 = *(DWORD*)curPos;
366 curPos = curPos + sizeof(DWORD);
370 /* Vertex Normal Data (untransformed only) */
371 if (normal) {
372 nx = *(float *)curPos;
373 curPos = curPos + sizeof(float);
374 ny = *(float *)curPos;
375 curPos = curPos + sizeof(float);
376 nz = *(float *)curPos;
377 curPos = curPos + sizeof(float);
378 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
381 if (isPtSize) {
382 ptSize = *(float *)curPos;
383 VTRACE(("ptSize=%f\n", ptSize));
384 curPos = curPos + sizeof(float);
387 if (isDiffuse) {
388 diffuseColor = *(DWORD *)curPos;
389 VTRACE(("diffuseColor=%lx\n", diffuseColor));
390 curPos = curPos + sizeof(DWORD);
393 if (isSpecular) {
394 specularColor = *(DWORD *)curPos;
395 VTRACE(("specularColor=%lx\n", specularColor));
396 curPos = curPos + sizeof(DWORD);
399 /* Texture coords */
400 /* numTextures indicates the number of texture coordinates supplied */
401 /* However, the first set may not be for stage 0 texture - it all */
402 /* depends on D3DTSS_TEXCOORDINDEX. */
403 /* The number of bytes for each coordinate set is based off */
404 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
406 /* Initialize unused coords to unsupplied so we can check later */
407 for (textureNo = numTextures; textureNo < 7; textureNo++) numCoords[textureNo] = -1;
409 /* So, for each supplied texture extract the coords */
410 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
412 numCoords[textureNo] = coordIdxInfo & 0x03;
414 /* Always one set */
415 s[textureNo] = *(float *)curPos;
416 curPos = curPos + sizeof(float);
417 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
418 t[textureNo] = *(float *)curPos;
419 curPos = curPos + sizeof(float);
420 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
421 r[textureNo] = *(float *)curPos;
422 curPos = curPos + sizeof(float);
423 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
424 q[textureNo] = *(float *)curPos;
425 curPos = curPos + sizeof(float);
430 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
433 /* Now use the appropriate set of texture indexes */
434 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
436 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
437 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
438 continue ;
441 /* Query tex coords */
442 if ((This->StateBlock->textures[textureNo] != NULL) &&
443 (useVertexShaderFunction == FALSE)) {
445 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
447 if (coordIdx > 7) {
448 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
449 } else if (coordIdx >= numTextures) {
450 VTRACE(("tex: %d - Skip tex coords, as requested higher than supplied\n", textureNo));
451 } else {
453 int coordsToUse = numCoords[coordIdx];
455 /* If texture transform flags in effect, values passed through to vertex
456 depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
457 if (coordsToUse > 0 &&
458 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
460 /* This indicates how many coords to use regardless of the
461 texture type. However, d3d/opengl fill in the rest appropriately */
462 coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
464 /* BUT - Projected is more 'fun' - Move the last coord to the 'q'
465 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
466 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
467 switch (coordsToUse) {
468 case 0: /* Drop Through */
469 case 1:
470 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
471 break;
472 case 2:
473 q[textureNo] = t[textureNo];
474 t[textureNo] = 0.0;
475 coordsToUse = 4;
476 break;
477 case 3:
478 q[textureNo] = r[textureNo];
479 r[textureNo] = 0.0;
480 coordsToUse = 4;
481 break;
482 case 4: /* Nop here */
483 break;
484 default:
485 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
486 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
491 switch (coordsToUse) { /* Supply the provided texture coords */
492 case D3DFVF_TEXTUREFORMAT1:
493 VTRACE(("tex:%d, s=%f\n", textureNo, s[coordIdx]));
494 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
495 #if defined(GL_VERSION_1_3)
496 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s[coordIdx]);
497 #else
498 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx]);
499 #endif
500 } else {
501 glTexCoord1f(s[coordIdx]);
503 break;
504 case D3DFVF_TEXTUREFORMAT2:
505 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s[coordIdx], t[coordIdx]));
506 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
507 #if defined(GL_VERSION_1_3)
508 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx]);
509 #else
510 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx]);
511 #endif
512 } else {
513 glTexCoord2f(s[coordIdx], t[coordIdx]);
515 break;
516 case D3DFVF_TEXTUREFORMAT3:
517 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx]));
518 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
519 #if defined(GL_VERSION_1_3)
520 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
521 #else
522 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
523 #endif
524 } else {
525 glTexCoord3f(s[coordIdx], t[coordIdx], r[coordIdx]);
527 break;
528 case D3DFVF_TEXTUREFORMAT4:
529 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]));
530 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
531 #if defined(GL_VERSION_1_3)
532 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
533 #else
534 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
535 #endif
536 } else {
537 glTexCoord4f(s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
539 break;
540 default:
541 FIXME("Should not get here as numCoords is two bits only (%x)!\n", numCoords[coordIdx]);
548 /** if vertex shader program specified ... using it */
549 if (TRUE == useVertexShaderFunction) {
552 * this code must become the really
553 * vs input params init
555 * because its possible to use input registers for anything
556 * and some samples use registers for other things than they are
557 * declared
560 /**
561 * no really valid declaration, user defined input register use
562 * so fill input registers as described in vertex shader declaration
564 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
565 (!isIndexed) ? (vx_index * skip) :
566 (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) :
567 ((pIdxBufL[StartIdx + vx_index]) * skip));
569 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
570 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
572 TRACE_VECTOR(vertex_shader->output.oPos);
573 TRACE_VECTOR(vertex_shader->output.oD[0]);
574 TRACE_VECTOR(vertex_shader->output.oD[1]);
575 TRACE_VECTOR(vertex_shader->output.oT[0]);
576 TRACE_VECTOR(vertex_shader->output.oT[1]);
577 TRACE_VECTOR(vertex_shader->input.V[0]);
578 TRACE_VECTOR(vertex_shader->data->C[0]);
579 TRACE_VECTOR(vertex_shader->data->C[1]);
580 TRACE_VECTOR(vertex_shader->data->C[2]);
581 TRACE_VECTOR(vertex_shader->data->C[3]);
582 TRACE_VECTOR(vertex_shader->data->C[4]);
583 TRACE_VECTOR(vertex_shader->data->C[5]);
584 TRACE_VECTOR(vertex_shader->data->C[6]);
585 TRACE_VECTOR(vertex_shader->data->C[7]);
587 x = vertex_shader->output.oPos.x;
588 y = vertex_shader->output.oPos.y;
589 z = vertex_shader->output.oPos.z;
591 if (1.0f != vertex_shader->output.oPos.w || isRHW) {
592 rhw = vertex_shader->output.oPos.w;
594 /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
595 glColor4fv((float*) &vertex_shader->output.oD[0]);
597 /* Requires secondary color extensions to compile... */
598 #if defined(GL_VERSION_1_4)
599 glSecondaryColor3fv((float*) &vertex_shader->output.oD[1]);
600 checkGLcall("glSecondaryColor3fv");
601 #elif defined(GL_EXT_secondary_color)
602 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
603 /*specularColor = D3DCOLORTOCOLORVALUE(vertex_shader->output.oD[1]);*/
604 glSecondaryColor3fvEXT((float*) &vertex_shader->output.oD[1]);
605 checkGLcall("glSecondaryColor3fvEXT");
607 #endif
608 /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
609 for (textureNo = 0; textureNo < 4; ++textureNo) {
610 float s, t, r, q;
612 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
613 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
614 continue ;
616 /* Query tex coords */
617 if (This->StateBlock->textures[textureNo] != NULL) {
618 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
619 case D3DRTYPE_TEXTURE:
620 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
621 s = vertex_shader->output.oT[textureNo].x;
622 t = vertex_shader->output.oT[textureNo].y;
623 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
624 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
625 VTRACE(("Skip tex coords, as being system generated\n"));
626 } else {
627 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
628 #if defined(GL_VERSION_1_3)
629 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
630 #else
631 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
632 #endif
633 /*checkGLcall("glMultiTexCoord2fARB");*/
634 } else {
635 glTexCoord2f(s, t);
636 /*checkGLcall("gTexCoord2f");*/
639 break;
641 case D3DRTYPE_VOLUMETEXTURE:
642 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
643 s = vertex_shader->output.oT[textureNo].x;
644 t = vertex_shader->output.oT[textureNo].y;
645 r = vertex_shader->output.oT[textureNo].z;
646 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
647 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
648 VTRACE(("Skip tex coords, as being system generated\n"));
649 } else {
650 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
651 #if defined(GL_VERSION_1_3)
652 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
653 #else
654 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
655 #endif
656 /*checkGLcall("glMultiTexCoord2fARB");*/
657 } else {
658 glTexCoord3f(s, t, r);
659 /*checkGLcall("gTexCoord3f");*/
662 break;
664 default:
665 /* Avoid compiler warnings, need these vars later for other textures */
666 r = 0.0f; q = 0.0f;
667 FIXME("Unhandled texture type\n");
672 if (1.0f == rhw || rhw < 0.01f) {
673 TRACE_(d3d_shader)("Vertex: glVertex:x,y,z=%f,%f,%f\n", x, y, z);
674 glVertex3f(x, y, z);
675 /*checkGLcall("glVertex3f");*/
676 } else {
677 GLfloat w = 1.0f / rhw;
678 TRACE_(d3d_shader)("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw);
680 /*glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);*/
681 glVertex4f(x * w, y * w, z * w, 1.0f);
682 /*checkGLcall("glVertex4f");*/
684 } else {
685 /**
686 * FALSE == useVertexShaderFunction
687 * using std FVF code
690 /* Handle these vertexes */
691 if (isDiffuse) {
692 glColor4ub((diffuseColor >> 16) & 0xFF,
693 (diffuseColor >> 8) & 0xFF,
694 (diffuseColor >> 0) & 0xFF,
695 (diffuseColor >> 24) & 0xFF);
696 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
697 ((diffuseColor >> 16) & 0xFF) / 255.0f,
698 ((diffuseColor >> 8) & 0xFF) / 255.0f,
699 ((diffuseColor >> 0) & 0xFF) / 255.0f,
700 ((diffuseColor >> 24) & 0xFF) / 255.0f));
703 if (normal) {
704 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
705 glNormal3f(nx, ny, nz);
706 glVertex3f(x, y, z);
707 } else {
708 if (1.0f == rhw || rhw < 0.01f) {
709 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
710 glVertex3f(x, y, z);
711 } else {
712 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
713 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
718 if (!isIndexed) {
719 curVtx = curVtx + skip;
723 glEnd();
724 checkGLcall("glEnd and previous calls");
726 } else {
727 TRACE("Using fast vertex array code\n");
729 /* Faster version, harder to debug */
730 /* Shuffle to the beginning of the vertexes to render and index from there */
731 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
732 curPos = curVtx;
734 /* Set up the vertex pointers */
735 if (isRHW) {
736 glVertexPointer(4, GL_FLOAT, skip, curPos);
737 checkGLcall("glVertexPointer(4, ...)");
738 curPos += 4 * sizeof(float);
739 } else {
740 glVertexPointer(3, GL_FLOAT, skip, curPos);
741 checkGLcall("glVertexPointer(3, ...)");
742 curPos += 3 * sizeof(float);
744 glEnableClientState(GL_VERTEX_ARRAY);
745 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
747 if (numBlends > 0) {
748 /* no such functionality in the fixed function GL pipeline */
749 /* FIXME: Wont get here as will drop to slow method */
750 /* FIXME("Cannot handle blending data here in openGl\n");*/
751 #if 0
752 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
753 /*FIXME("TODO\n");*/
754 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
755 /*FIXME("TODO\n");*/
757 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
758 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
759 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
760 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
762 } else {
763 FIXME("unsupported blending in openGl\n");
765 #endif
766 curPos += numBlends * sizeof(float);
767 } else {
768 #if 0
769 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
770 FIXME("TODO\n");
771 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
772 FIXME("TODO\n");
774 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
775 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
778 #endif
782 if (normal) {
783 glNormalPointer(GL_FLOAT, skip, curPos);
784 checkGLcall("glNormalPointer");
785 glEnableClientState(GL_NORMAL_ARRAY);
786 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
787 curPos += 3 * sizeof(float);
788 } else {
789 glDisableClientState(GL_NORMAL_ARRAY);
790 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
791 glNormal3f(0, 0, 1);
792 checkGLcall("glNormal3f(0, 0, 1)");
795 if (isPtSize) {
796 /* no such functionality in the fixed function GL pipeline */
797 /* FIXME: Wont get here as will drop to slow method */
798 FIXME("Cannot change ptSize here in openGl\n");
799 curPos = curPos + sizeof(float);
802 if (isDiffuse) {
803 glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
804 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
805 glEnableClientState(GL_COLOR_ARRAY);
806 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
807 curPos += sizeof(DWORD);
809 else {
810 glDisableClientState(GL_COLOR_ARRAY);
811 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
812 glColor4f(1, 1, 1, 1);
813 checkGLcall("glColor4f(1, 1, 1, 1)");
816 /* Requires secondary color extensions to compile... */
817 if (isSpecular) {
818 #if defined(GL_VERSION_1_4)
819 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
820 checkGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos)");
821 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
822 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
823 #elif defined(GL_EXT_secondary_color)
824 /* FIXME: check for GL_EXT_secondary_color */
825 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
826 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos);
827 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
828 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
829 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
831 #endif
832 curPos += sizeof(DWORD);
833 } else {
834 #if defined(GL_VERSION_1_4)
835 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
836 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
837 glSecondaryColor3f(0, 0, 0);
838 checkGLcall("glSecondaryColor3f(0, 0, 0)");
839 #else
840 #if 0
841 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
842 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
843 glSecondaryColor3fEXT(0, 0, 0);
844 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
845 #endif
846 #endif
849 /* Texture coords */
850 /* numTextures indicates the number of texture coordinates supplied */
851 /* However, the first set may not be for stage 0 texture - it all */
852 /* depends on D3DTSS_TEXCOORDINDEX. */
853 /* The number of bytes for each coordinate set is based off */
854 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
856 /* Initialize unused coords to unsupplied so we can check later */
857 for (textureNo = numTextures; textureNo < 7; textureNo++) coordPtr[textureNo] = NULL;
859 /* So, for each supplied texture extract the coords */
860 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
862 numCoords[textureNo] = coordIdxInfo & 0x03;
863 coordPtr[textureNo] = curPos;
865 /* Always one set */
866 curPos = curPos + sizeof(float);
867 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
868 curPos = curPos + sizeof(float);
869 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
870 curPos = curPos + sizeof(float);
871 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
872 curPos = curPos + sizeof(float);
876 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
879 /* Now use the appropriate set of texture indexes */
880 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
882 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
883 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
884 continue ;
887 /* Query tex coords */
888 if ((This->StateBlock->textures[textureNo] != NULL) && (useVertexShaderFunction == FALSE)) {
889 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
891 if (coordIdx > 7) {
892 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
893 } else {
894 int numFloats = 0;
895 int coordsToUse = numCoords[coordIdx];
896 #if defined(GL_VERSION_1_3)
897 glClientActiveTexture(GL_TEXTURE0 + textureNo);
898 #else
899 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
900 #endif
902 /* If texture transform flags in effect, values passed through to vertex
903 depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
904 if (coordsToUse > 0 &&
905 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
907 /* This indicates how many coords to use regardless of the
908 texture type. However, d3d/opengl fill in the rest appropriately */
909 coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
911 /* BUT - Projected is more 'fun' - Cant be done for ptr mode.
912 Probably should scan enabled texture units and drop back to
913 slow mode if found? */
914 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
915 FIXME("Cannot handle projected transform state in fast mode\n");
919 switch (coordsToUse) { /* Supply the provided texture coords */
920 case D3DFVF_TEXTUREFORMAT1: numFloats = 1; break;
921 case D3DFVF_TEXTUREFORMAT2: numFloats = 2; break;
922 case D3DFVF_TEXTUREFORMAT3: numFloats = 3; break;
923 case D3DFVF_TEXTUREFORMAT4: numFloats = 4; break;
924 default: numFloats = 0; break;
927 if (numFloats == 0 || coordIdx >= numTextures) {
928 VTRACE(("Skipping as invalid request - numfloats=%d, coordIdx=%d, numTextures=%d\n", numFloats, coordIdx, numTextures));
929 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
930 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
931 } else {
932 VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, coordPtr[coordIdx], numFloats));
933 glTexCoordPointer(numFloats, GL_FLOAT, skip, coordPtr[coordIdx]);
934 checkGLcall("glTexCoordPointer(x, ...)");
935 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
936 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
942 /* Finally do the drawing */
943 if (isIndexed) {
945 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
946 if (idxBytes==2) {
947 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
948 glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
949 (char *)idxData+(2 * StartIdx));
950 #else
951 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
952 GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
953 #endif
954 } else {
955 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
956 glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
957 (char *)idxData+(4 * StartIdx));
958 #else
959 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
960 GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
961 #endif
963 checkGLcall("glDrawRangeElements");
965 } else {
967 /* Note first is now zero as we shuffled along earlier */
968 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
969 glDrawArrays(primType, 0, NumVertexes);
970 checkGLcall("glDrawArrays");
975 /* If no normals, restore previous lighting state */
976 if (!normal) {
977 if (isLightingOn) glEnable(GL_LIGHTING);
978 else glDisable(GL_LIGHTING);
979 TRACE("Restored lighting to original state\n");
983 LEAVE_GL();
985 TRACE("glEnd\n");
988 /* Apply the current values to the specified texture stage */
989 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
990 ICOM_THIS(IDirect3DDevice8Impl,iface);
991 int i = 0;
992 float col[4];
994 /* Make appropriate texture active */
995 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
996 #if defined(GL_VERSION_1_3)
997 glActiveTexture(GL_TEXTURE0 + Stage);
998 #else
999 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1000 #endif
1001 checkGLcall("glActiveTextureARB");
1002 } else if (Stage > 0) {
1003 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1006 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
1007 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
1008 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1011 /* Note the D3DRS value applies to all textures, but GL has one
1012 * per texture, so apply it now ready to be used!
1014 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
1015 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1016 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1018 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1021 /* IDirect3D IUnknown parts follow: */
1022 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1024 ICOM_THIS(IDirect3DDevice8Impl,iface);
1026 if (IsEqualGUID(riid, &IID_IUnknown)
1027 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1028 IDirect3DDevice8Impl_AddRef(iface);
1029 *ppobj = This;
1030 return D3D_OK;
1033 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1034 return E_NOINTERFACE;
1037 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1038 ICOM_THIS(IDirect3DDevice8Impl,iface);
1039 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1040 return ++(This->ref);
1043 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1044 ICOM_THIS(IDirect3DDevice8Impl,iface);
1045 ULONG ref = --This->ref;
1046 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1047 if (ref == 0) {
1048 IDirect3DDevice8Impl_CleanRender(iface);
1049 HeapFree(GetProcessHeap(), 0, This);
1051 return ref;
1054 /* IDirect3DDevice Interface follow: */
1055 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1056 ICOM_THIS(IDirect3DDevice8Impl,iface);
1057 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
1058 return D3D_OK;
1061 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1062 ICOM_THIS(IDirect3DDevice8Impl,iface);
1063 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1065 * pretend we have 32MB of any type of memory queried.
1067 return (1024*1024*32);
1070 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1071 ICOM_THIS(IDirect3DDevice8Impl,iface);
1072 FIXME("(%p) : stub\n", This); return D3D_OK;
1074 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1075 ICOM_THIS(IDirect3DDevice8Impl,iface);
1076 TRACE("(%p) : returning %p\n", This, This->direct3d8);
1078 /* Inc ref count */
1079 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1081 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1082 return D3D_OK;
1084 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1085 ICOM_THIS(IDirect3DDevice8Impl,iface);
1086 FIXME("(%p) : stub, calling idirect3d for now\n", This);
1087 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1088 return D3D_OK;
1090 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1092 HDC hdc;
1093 int bpp = 0;
1095 ICOM_THIS(IDirect3DDevice8Impl,iface);
1096 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
1097 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
1098 pMode->RefreshRate = 85; /*FIXME: How to identify? */
1100 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1101 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1102 DeleteDC(hdc);
1104 switch (bpp) {
1105 case 8: pMode->Format = D3DFMT_R8G8B8; break;
1106 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1107 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
1108 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1109 default:
1110 FIXME("Unrecognized display mode format\n");
1111 pMode->Format = D3DFMT_UNKNOWN;
1114 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
1115 pMode->Format, debug_d3dformat(pMode->Format));
1116 return D3D_OK;
1118 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1119 ICOM_THIS(IDirect3DDevice8Impl,iface);
1120 TRACE("(%p) copying to %p\n", This, pParameters);
1121 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1122 return D3D_OK;
1124 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1125 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
1126 ICOM_THIS(IDirect3DDevice8Impl,iface);
1127 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
1129 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
1130 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
1131 return D3DERR_INVALIDCALL;
1133 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
1134 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
1135 return D3DERR_INVALIDCALL;
1138 This->xHotSpot = XHotSpot;
1139 This->yHotSpot = YHotSpot;
1140 return D3D_OK;
1142 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
1143 ICOM_THIS(IDirect3DDevice8Impl,iface);
1144 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
1145 This->xScreenSpace = XScreenSpace;
1146 This->yScreenSpace = YScreenSpace;
1147 return;
1149 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1150 ICOM_THIS(IDirect3DDevice8Impl,iface);
1151 TRACE("(%p) : visible(%d)\n", This, bShow);
1152 This->bCursorVisible = bShow;
1153 return D3D_OK;
1155 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1156 IDirect3DSwapChain8Impl* object;
1157 ICOM_THIS(IDirect3DDevice8Impl,iface);
1158 FIXME("(%p) : stub\n", This);
1160 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
1161 if (NULL == object) {
1162 return D3DERR_OUTOFVIDEOMEMORY;
1164 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
1165 object->ref = 1;
1167 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
1168 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
1169 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
1171 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
1172 (pPresentationParameters->BackBufferHeight == 0))) {
1173 RECT Rect;
1175 GetClientRect(This->win_handle, &Rect);
1177 if (pPresentationParameters->BackBufferWidth == 0) {
1178 pPresentationParameters->BackBufferWidth = Rect.right;
1179 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1181 if (pPresentationParameters->BackBufferHeight == 0) {
1182 pPresentationParameters->BackBufferHeight = Rect.bottom;
1183 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1187 /* Save the presentation parms now filled in correctly */
1188 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
1190 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1191 pPresentationParameters->BackBufferWidth,
1192 pPresentationParameters->BackBufferHeight,
1193 pPresentationParameters->BackBufferFormat,
1194 pPresentationParameters->MultiSampleType,
1195 TRUE,
1196 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
1198 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1199 pPresentationParameters->BackBufferWidth,
1200 pPresentationParameters->BackBufferHeight,
1201 pPresentationParameters->BackBufferFormat,
1202 pPresentationParameters->MultiSampleType,
1203 TRUE,
1204 (LPDIRECT3DSURFACE8*) &object->backBuffer);
1206 if (pPresentationParameters->EnableAutoDepthStencil) {
1207 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
1208 pPresentationParameters->BackBufferWidth,
1209 pPresentationParameters->BackBufferHeight,
1210 pPresentationParameters->AutoDepthStencilFormat,
1211 D3DMULTISAMPLE_NONE,
1212 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
1213 } else {
1214 object->depthStencilBuffer = NULL;
1217 *pSwapChain = (IDirect3DSwapChain8*) object;
1218 return D3D_OK;
1220 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1221 ICOM_THIS(IDirect3DDevice8Impl,iface);
1222 FIXME("(%p) : stub\n", This); return D3D_OK;
1224 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1225 ICOM_THIS(IDirect3DDevice8Impl,iface);
1226 TRACE("(%p) : complete stub!\n", This);
1228 ENTER_GL();
1230 glXSwapBuffers(This->display, This->drawable);
1231 /* Dont call checkGLcall, as glGetError is not applicable here */
1232 TRACE("glXSwapBuffers called, Starting new frame");
1234 LEAVE_GL();
1236 return D3D_OK;
1238 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
1239 ICOM_THIS(IDirect3DDevice8Impl,iface);
1240 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1241 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1243 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
1244 FIXME("Only one backBuffer currently supported\n");
1245 return D3DERR_INVALIDCALL;
1248 /* Note inc ref on returned surface */
1249 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1251 return D3D_OK;
1253 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1254 ICOM_THIS(IDirect3DDevice8Impl,iface);
1255 FIXME("(%p) : stub\n", This);
1256 return D3D_OK;
1258 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
1259 ICOM_THIS(IDirect3DDevice8Impl,iface);
1260 FIXME("(%p) : stub\n", This);
1261 return;
1263 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1264 ICOM_THIS(IDirect3DDevice8Impl,iface);
1265 FIXME("(%p) : stub\n", This);
1266 return;
1268 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1269 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
1270 IDirect3DTexture8Impl *object;
1271 int i;
1272 UINT tmpW;
1273 UINT tmpH;
1275 ICOM_THIS(IDirect3DDevice8Impl,iface);
1277 /* Allocate the storage for the device */
1278 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, debug_d3dformat(Format), Pool);
1279 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1280 object->lpVtbl = &Direct3DTexture8_Vtbl;
1281 object->Device = This;
1282 object->ResourceType = D3DRTYPE_TEXTURE;
1283 object->ref = 1;
1284 object->width = Width;
1285 object->height = Height;
1286 object->levels = Levels;
1287 object->usage = Usage;
1288 object->format = Format;
1290 /* Calculate levels for mip mapping */
1291 if (Levels == 0) {
1292 object->levels++;
1293 tmpW = Width;
1294 tmpH = Height;
1295 while (tmpW > 1 && tmpH > 1) {
1296 tmpW = max(1, tmpW / 2);
1297 tmpH = max(1, tmpH / 2);
1298 object->levels++;
1300 TRACE("Calculated levels = %d\n", object->levels);
1303 /* Generate all the surfaces */
1304 tmpW = Width;
1305 tmpH = Height;
1306 for (i = 0; i < object->levels; i++)
1308 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1309 object->surfaces[i]->Container = (IUnknown*) object;
1310 object->surfaces[i]->myDesc.Usage = Usage;
1311 object->surfaces[i]->myDesc.Pool = Pool;
1312 /**
1313 * As writen in msdn in IDirect3DTexture8::LockRect
1314 * Textures created in D3DPOOL_DEFAULT are not lockable.
1316 if (D3DPOOL_DEFAULT == Pool) {
1317 object->surfaces[i]->lockable = FALSE;
1320 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1321 tmpW = max(1, tmpW / 2);
1322 tmpH = max(1, tmpH / 2);
1325 *ppTexture = (LPDIRECT3DTEXTURE8) object;
1326 return D3D_OK;
1328 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
1329 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
1330 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
1332 IDirect3DVolumeTexture8Impl *object;
1333 int i;
1334 UINT tmpW;
1335 UINT tmpH;
1336 UINT tmpD;
1338 ICOM_THIS(IDirect3DDevice8Impl,iface);
1340 /* Allocate the storage for it */
1341 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, Width, Height, Depth, Levels, Usage, Format, debug_d3dformat(Format), Pool);
1342 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1343 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1344 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1345 object->Device = This;
1346 object->ref = 1;
1348 object->width = Width;
1349 object->height = Height;
1350 object->depth = Depth;
1351 object->levels = Levels;
1352 object->usage = Usage;
1353 object->format = Format;
1355 /* Calculate levels for mip mapping */
1356 if (Levels == 0) {
1357 object->levels++;
1358 tmpW = Width;
1359 tmpH = Height;
1360 tmpD = Depth;
1361 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1362 tmpW = max(1, tmpW / 2);
1363 tmpH = max(1, tmpH / 2);
1364 tmpD = max(1, tmpD / 2);
1365 object->levels++;
1367 TRACE("Calculated levels = %d\n", object->levels);
1370 /* Generate all the surfaces */
1371 tmpW = Width;
1372 tmpH = Height;
1373 tmpD = Depth;
1375 for (i = 0; i < object->levels; i++)
1377 IDirect3DVolume8Impl* volume;
1379 /* Create the volume - No entry point for this seperately?? */
1380 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1381 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1383 volume->lpVtbl = &Direct3DVolume8_Vtbl;
1384 volume->Device = This;
1385 volume->ResourceType = D3DRTYPE_VOLUME;
1386 volume->Container = (IUnknown*) object;
1387 volume->ref = 1;
1389 volume->myDesc.Width = Width;
1390 volume->myDesc.Height = Height;
1391 volume->myDesc.Depth = Depth;
1392 volume->myDesc.Format = Format;
1393 volume->myDesc.Type = D3DRTYPE_VOLUME;
1394 volume->myDesc.Pool = Pool;
1395 volume->myDesc.Usage = Usage;
1396 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
1397 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
1398 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1400 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
1401 This, Width, Height, Depth, Format, debug_d3dformat(Format),
1402 volume, volume->allocatedMemory, volume->myDesc.Size);
1404 tmpW = max(1, tmpW / 2);
1405 tmpH = max(1, tmpH / 2);
1406 tmpD = max(1, tmpD / 2);
1409 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
1410 return D3D_OK;
1412 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
1413 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
1415 IDirect3DCubeTexture8Impl *object;
1416 ICOM_THIS(IDirect3DDevice8Impl,iface);
1417 int i,j;
1418 UINT tmpW;
1420 /* Allocate the storage for it */
1421 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), Pool);
1422 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1423 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1424 object->ref = 1;
1425 object->Device = This;
1426 object->ResourceType = D3DRTYPE_CUBETEXTURE;
1428 object->edgeLength = EdgeLength;
1429 object->levels = Levels;
1430 object->usage = Usage;
1431 object->format = Format;
1433 /* Calculate levels for mip mapping */
1434 if (Levels == 0) {
1435 object->levels++;
1436 tmpW = EdgeLength;
1437 while (tmpW > 1) {
1438 tmpW = max(1, tmpW / 2);
1439 object->levels++;
1441 TRACE("Calculated levels = %d\n", object->levels);
1444 /* Generate all the surfaces */
1445 tmpW = EdgeLength;
1446 for (i = 0; i < object->levels; i++) {
1447 /* Create the 6 faces */
1448 for (j = 0; j < 6; j++) {
1449 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1450 object->surfaces[j][i]->Container = (IUnknown*) object;
1451 object->surfaces[j][i]->myDesc.Usage = Usage;
1452 object->surfaces[j][i]->myDesc.Pool = Pool;
1453 /**
1454 * As writen in msdn in IDirect3DCubeTexture8::LockRect
1455 * Textures created in D3DPOOL_DEFAULT are not lockable.
1457 if (D3DPOOL_DEFAULT == Pool) {
1458 object->surfaces[j][i]->lockable = FALSE;
1461 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1463 tmpW = max(1, tmpW / 2);
1466 TRACE("(%p) : Iface@%p\n", This, object);
1467 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1468 return D3D_OK;
1470 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1471 IDirect3DVertexBuffer8Impl *object;
1473 ICOM_THIS(IDirect3DDevice8Impl,iface);
1475 /* Allocate the storage for the device */
1476 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1477 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1478 object->Device = This;
1479 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1480 object->ref = 1;
1481 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1482 object->currentDesc.Usage = Usage;
1483 object->currentDesc.Pool = Pool;
1484 object->currentDesc.FVF = FVF;
1485 object->currentDesc.Size = Size;
1487 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1489 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1491 return D3D_OK;
1493 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
1494 IDirect3DIndexBuffer8Impl *object;
1496 ICOM_THIS(IDirect3DDevice8Impl,iface);
1497 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
1499 /* Allocate the storage for the device */
1500 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1501 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1502 object->Device = This;
1503 object->ref = 1;
1504 object->ResourceType = D3DRTYPE_INDEXBUFFER;
1506 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1507 object->currentDesc.Usage = Usage;
1508 object->currentDesc.Pool = Pool;
1509 object->currentDesc.Format = Format;
1510 object->currentDesc.Size = Length;
1512 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1514 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1516 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1518 return D3D_OK;
1520 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
1521 IDirect3DSurface8Impl *object;
1522 ICOM_THIS(IDirect3DDevice8Impl,iface);
1524 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1525 if (NULL == object) {
1526 *ppSurface = NULL;
1527 return D3DERR_OUTOFVIDEOMEMORY;
1529 *ppSurface = (LPDIRECT3DSURFACE8) object;
1530 object->lpVtbl = &Direct3DSurface8_Vtbl;
1531 object->Device = This;
1532 object->ResourceType = D3DRTYPE_SURFACE;
1533 object->Container = (IUnknown*) This;
1535 object->ref = 1;
1536 object->myDesc.Width = Width;
1537 object->myDesc.Height = Height;
1538 object->myDesc.Format = Format;
1539 object->myDesc.Type = D3DRTYPE_SURFACE;
1540 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
1541 object->myDesc.Pool = D3DPOOL_DEFAULT;
1542 object->myDesc.MultiSampleType = MultiSample;
1543 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1544 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1545 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1546 object->lockable = Lockable;
1547 object->locked = FALSE;
1549 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), Lockable, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1550 return D3D_OK;
1552 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
1553 IDirect3DSurface8Impl *object;
1555 ICOM_THIS(IDirect3DDevice8Impl,iface);
1557 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1558 if (NULL == object) {
1559 *ppSurface = NULL;
1560 return D3DERR_OUTOFVIDEOMEMORY;
1562 *ppSurface = (LPDIRECT3DSURFACE8) object;
1563 object->lpVtbl = &Direct3DSurface8_Vtbl;
1564 object->Device = This;
1565 object->ResourceType = D3DRTYPE_SURFACE;
1566 object->Container = (IUnknown*) This;
1568 object->ref = 1;
1569 object->myDesc.Width = Width;
1570 object->myDesc.Height = Height;
1571 object->myDesc.Format = Format;
1572 object->myDesc.Type = D3DRTYPE_SURFACE;
1573 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
1574 object->myDesc.Pool = D3DPOOL_DEFAULT;
1575 object->myDesc.MultiSampleType = MultiSample;
1576 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1577 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1578 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1579 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
1580 object->locked = FALSE;
1582 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
1583 return D3D_OK;
1585 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
1586 IDirect3DSurface8Impl *object;
1588 ICOM_THIS(IDirect3DDevice8Impl,iface);
1590 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1591 *ppSurface = (LPDIRECT3DSURFACE8) object;
1592 object->lpVtbl = &Direct3DSurface8_Vtbl;
1593 object->Device = This;
1594 object->ResourceType = D3DRTYPE_SURFACE;
1595 object->Container = (IUnknown*) This;
1597 object->ref = 1;
1598 object->myDesc.Width = Width;
1599 object->myDesc.Height = Height;
1600 object->myDesc.Format = Format;
1601 object->myDesc.Type = D3DRTYPE_SURFACE;
1602 object->myDesc.Usage = 0;
1603 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
1604 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1605 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1606 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1607 object->lockable = TRUE;
1608 object->locked = FALSE;
1610 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
1611 return D3D_OK;
1613 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
1614 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
1615 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
1617 HRESULT rc = D3D_OK;
1618 IDirect3DBaseTexture8* texture = NULL;
1621 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
1622 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1624 ICOM_THIS(IDirect3DDevice8Impl,iface);
1625 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1626 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1628 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1629 a sample and doesnt seem to break anything as far as I can tell */
1630 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1631 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1632 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1633 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1634 rc = D3DERR_INVALIDCALL;
1636 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1637 TRACE("Converting dest to same format as source, since dest was unknown\n");
1638 dst->myDesc.Format = src->myDesc.Format;
1640 /* Convert container as well */
1641 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1642 if (texture != NULL) {
1643 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1644 /** Releasing texture after GetContainer */
1645 IDirect3DBaseTexture8_Release(texture);
1646 texture = NULL;
1650 /* Quick if complete copy ... */
1651 if (rc == D3D_OK && cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1653 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1655 D3DLOCKED_RECT lrSrc;
1656 D3DLOCKED_RECT lrDst;
1657 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1658 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1659 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1661 /*memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);*/
1662 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1664 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1665 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1666 TRACE("Unlocked src and dst\n");
1668 } else {
1670 FIXME("Wanted to copy all surfaces but size not compatible\n");
1671 rc = D3DERR_INVALIDCALL;
1675 } else {
1677 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1679 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1680 int i;
1681 /* Copy rect by rect */
1682 for (i = 0; i < cRects; i++) {
1683 CONST RECT* r = &pSourceRectsArray[i];
1684 CONST POINT* p = &pDestPointsArray[i];
1685 int copyperline = (r->right - r->left) * bytesPerPixel;
1686 int j;
1687 D3DLOCKED_RECT lrSrc;
1688 D3DLOCKED_RECT lrDst;
1689 RECT dest_rect;
1692 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1694 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1695 dest_rect.left = p->x;
1696 dest_rect.top = p->y;
1697 dest_rect.right = p->x + (r->right - r->left);
1698 dest_rect.left = p->y + (r->bottom - r->top);
1699 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1700 TRACE("Locked src and dst\n");
1702 /* Find where to start */
1703 #if 0
1704 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1705 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
1706 /* Copy line by line */
1707 for (j = 0; j < (r->bottom - r->top); j++) {
1708 memcpy(to + (j * pitchTo), from + (j * pitchFrom), copyperline);
1710 #endif
1712 for (j = 0; j < (r->bottom - r->top); j++) {
1713 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1716 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1717 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1718 TRACE("Unlocked src and dst\n");
1721 } else {
1723 FIXME("Wanted to copy partial surfaces not implemented\n");
1724 rc = D3DERR_INVALIDCALL;
1729 return rc;
1731 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1732 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1733 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1734 D3DRESOURCETYPE srcType;
1735 D3DRESOURCETYPE dstType;
1737 ICOM_THIS(IDirect3DDevice8Impl,iface);
1738 TRACE("(%p) : first try\n", This);
1740 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1741 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1743 if (srcType != dstType) {
1744 return D3DERR_INVALIDCALL;
1746 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1747 return D3DERR_INVALIDCALL;
1749 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1750 return D3DERR_INVALIDCALL;
1752 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1753 /** Only copy Dirty textures */
1754 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1755 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1756 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1757 UINT i, j;
1759 for (i = skipLevels; i < srcLevelCnt; ++i) {
1760 HRESULT hr;
1762 switch (srcType) {
1763 case D3DRTYPE_TEXTURE:
1765 IDirect3DSurface8* srcSur = NULL;
1766 IDirect3DSurface8* dstSur = NULL;
1767 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1768 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1769 /*IDirect3DDevice8_CopyRects*/
1770 IDirect3DSurface8Impl_Release(srcSur);
1771 IDirect3DSurface8Impl_Release(dstSur);
1773 break;
1774 case D3DRTYPE_VOLUMETEXTURE:
1776 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1778 break;
1779 case D3DRTYPE_CUBETEXTURE:
1781 IDirect3DSurface8* srcSur = NULL;
1782 IDirect3DSurface8* dstSur = NULL;
1783 for (j = 0; j < 5; ++j) {
1784 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1785 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1786 /*IDirect3DDevice8_CopyRects*/
1787 IDirect3DSurface8Impl_Release(srcSur);
1788 IDirect3DSurface8Impl_Release(dstSur);
1791 break;
1792 default:
1793 break;
1796 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1799 return D3D_OK;
1801 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1802 HRESULT hr;
1803 D3DLOCKED_RECT lockedRect;
1804 RECT wantedRect;
1805 GLint prev_store;
1806 GLenum prev_read;
1808 ICOM_THIS(IDirect3DDevice8Impl,iface);
1810 FIXME("(%p) : see if behavior correct\n", This);
1812 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1813 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1814 return D3DERR_INVALIDCALL;
1817 wantedRect.left = 0;
1818 wantedRect.top = 0;
1819 wantedRect.right = This->PresentParms.BackBufferWidth;
1820 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1822 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1823 if (FAILED(hr)) {
1824 ERR("(%p) : cannot lock surface\n", This);
1825 return D3DERR_INVALIDCALL;
1828 ENTER_GL();
1832 IDirect3DSurface8Impl* tmp = ((IDirect3DSurface8Impl*) pDestSurface);
1833 FIXME("dest:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
1834 FIXME("dest2:pitch%u\n", lockedRect.Pitch);
1835 FIXME("src:%u,%u\n", This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight);
1836 tmp = This->frontBuffer;
1837 FIXME("src2:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
1841 glFlush();
1842 vcheckGLcall("glFlush");
1843 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1844 vcheckGLcall("glIntegerv");
1845 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1846 vcheckGLcall("glIntegerv");
1848 glReadBuffer(GL_FRONT);
1849 vcheckGLcall("glReadBuffer");
1850 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1851 vcheckGLcall("glPixelStorei");
1852 /* stupid copy */
1854 long j;
1855 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1856 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1857 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1858 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1859 vcheckGLcall("glReadPixels");
1862 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1863 vcheckGLcall("glPixelStorei");
1864 glReadBuffer(prev_read);
1865 vcheckGLcall("glReadBuffer");
1867 LEAVE_GL();
1869 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1870 return hr;
1872 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1873 HRESULT hr;
1875 ICOM_THIS(IDirect3DDevice8Impl,iface);
1877 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1878 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1879 return D3D_OK;
1882 IDirect3DDevice8Impl_CleanRender(iface);
1884 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1885 IDirect3DSurface8Impl* tmp;
1887 TRACE("retoring SetRenderTarget defaults\n");
1889 tmp = This->renderTarget;
1890 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1891 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1892 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1894 tmp = This->stencilBufferTarget;
1895 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1896 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1897 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1899 return D3D_OK;
1902 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1904 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1906 return hr;
1909 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1910 ICOM_THIS(IDirect3DDevice8Impl,iface);
1912 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1914 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1915 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1917 return D3D_OK;
1920 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1921 ICOM_THIS(IDirect3DDevice8Impl,iface);
1923 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1925 /* Note inc ref on returned surface */
1926 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1927 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1929 return D3D_OK;
1932 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1933 ICOM_THIS(IDirect3DDevice8Impl,iface);
1934 TRACE("(%p) : stub\n", This);
1935 return D3D_OK;
1937 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1938 ICOM_THIS(IDirect3DDevice8Impl,iface);
1939 TRACE("(%p)\n", This);
1941 ENTER_GL();
1943 glFlush();
1944 checkGLcall("glFlush");
1946 /* Useful for debugging sometimes!
1947 printf("Hit Enter ...\n");
1948 getchar(); */
1950 if (This->frontBuffer != This->renderTarget) {
1952 GLenum prev_read;
1953 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1954 vcheckGLcall("glIntegerv");
1955 glReadBuffer(GL_BACK);
1956 vcheckGLcall("glReadBuffer");
1958 long j;
1959 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1960 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1961 glReadPixels(0,
1962 This->renderTarget->myDesc.Height - j - 1,
1963 This->renderTarget->myDesc.Width,
1965 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1966 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1967 This->renderTarget->allocatedMemory + j * pitch);
1968 vcheckGLcall("glReadPixels");
1971 glReadBuffer(prev_read);
1972 vcheckGLcall("glReadBuffer");
1975 IDirect3DBaseTexture8* cont = NULL;
1976 HRESULT hr;
1977 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1978 if (SUCCEEDED(hr) && NULL != cont) {
1979 /** always dirtify for now. we must find a better way to see that surface have been modified */
1980 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1981 IDirect3DBaseTexture8_PreLoad(cont);
1982 IDirect3DBaseTexture8_Release(cont);
1983 cont = NULL;
1987 LEAVE_GL();
1988 return D3D_OK;
1990 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1991 ICOM_THIS(IDirect3DDevice8Impl,iface);
1993 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1994 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1995 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1996 GLbitfield glMask = 0;
1997 GLboolean old_ztest;
1998 GLfloat old_z_clear_value;
1999 GLint old_stencil_clear_value;
2000 GLfloat old_color_clear_value[4];
2001 int i;
2002 CONST D3DRECT* curRect;
2004 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
2005 Count, pRects, Flags, Z, Stencil);
2007 ENTER_GL();
2008 if (Count > 0 && pRects) {
2009 glEnable(GL_SCISSOR_TEST);
2010 checkGLcall("glEnable GL_SCISSOR_TEST");
2011 curRect = pRects;
2012 } else {
2013 curRect = NULL;
2016 /* Only set the values up once, as they are not changing */
2017 if (Flags & D3DCLEAR_STENCIL) {
2018 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2019 glClearStencil(Stencil);
2020 checkGLcall("glClearStencil");
2021 glMask = glMask | GL_STENCIL_BUFFER_BIT;
2024 if (Flags & D3DCLEAR_ZBUFFER) {
2025 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
2026 glDepthMask(GL_TRUE);
2027 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2028 glClearDepth(Z);
2029 checkGLcall("glClearDepth");
2030 glMask = glMask | GL_DEPTH_BUFFER_BIT;
2033 if (Flags & D3DCLEAR_TARGET) {
2034 TRACE("Clearing screen with glClear to color %lx\n", Color);
2035 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2036 glClearColor(((Color >> 16) & 0xFF) / 255.0,
2037 ((Color >> 8) & 0xFF) / 255.0,
2038 ((Color >> 0) & 0xFF) / 255.0,
2039 ((Color >> 24) & 0xFF) / 255.0);
2040 checkGLcall("glClearColor");
2041 glMask = glMask | GL_COLOR_BUFFER_BIT;
2044 /* Now process each rect in turn */
2045 for (i = 0; i < Count || i == 0; i++) {
2047 if (curRect) {
2048 /* Note gl uses lower left, width/height */
2049 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
2050 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
2051 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
2052 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
2053 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
2054 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
2055 checkGLcall("glScissor");
2058 /* Clear the selected rectangle (or full screen) */
2059 glClear(glMask);
2060 checkGLcall("glClear");
2062 /* Step to the next rectangle */
2063 if (curRect) curRect = curRect + sizeof(D3DRECT);
2066 /* Restore the old values (why..?) */
2067 if (Flags & D3DCLEAR_STENCIL) {
2068 glClearStencil(old_stencil_clear_value);
2070 if (Flags & D3DCLEAR_ZBUFFER) {
2071 glDepthMask(old_ztest);
2072 glClearDepth(old_z_clear_value);
2074 if (Flags & D3DCLEAR_TARGET) {
2075 glClearColor(old_color_clear_value[0],
2076 old_color_clear_value[1],
2077 old_color_clear_value[2],
2078 old_color_clear_value[3]);
2081 if (Count > 0 && pRects) {
2082 glDisable(GL_SCISSOR_TEST);
2083 checkGLcall("glDisable");
2085 LEAVE_GL();
2087 return D3D_OK;
2089 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2090 ICOM_THIS(IDirect3DDevice8Impl,iface);
2091 D3DMATRIX m;
2092 int k;
2093 float f;
2094 BOOL viewChanged = TRUE;
2095 int Stage;
2097 /* Most of this routine, comments included copied from ddraw tree initially: */
2098 TRACE("(%p) : State=%d\n", This, d3dts);
2100 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
2101 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
2102 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2104 /* Handle recording of state blocks */
2105 if (This->isRecordingState) {
2106 TRACE("Recording... not performing anything\n");
2107 return D3D_OK;
2111 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2113 where ViewMat = Camera space, WorldMat = world space.
2115 In OpenGL, camera and world space is combined into GL_MODELVIEW
2116 matrix. The Projection matrix stay projection matrix. */
2118 /* After reading through both OpenGL and Direct3D documentations, I
2119 thought that D3D matrices were written in 'line major mode' transposed
2120 from OpenGL's 'column major mode'. But I found out that a simple memcpy
2121 works fine to transfer one matrix format to the other (it did not work
2122 when transposing)....
2124 So :
2125 1) are the documentations wrong
2126 2) does the matrix work even if they are not read correctly
2127 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
2128 loading using glLoadMatrix ?
2130 Anyway, I always use 'conv_mat' to transfer the matrices from one format
2131 to the other so that if I ever find out that I need to transpose them, I
2132 will able to do it quickly, only by changing the macro conv_mat. */
2134 if (d3dts < 256) {
2135 switch (d3dts) {
2136 case D3DTS_VIEW:
2137 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
2138 break;
2140 case D3DTS_PROJECTION:
2141 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
2142 break;
2144 case D3DTS_TEXTURE0:
2145 case D3DTS_TEXTURE1:
2146 case D3DTS_TEXTURE2:
2147 case D3DTS_TEXTURE3:
2148 case D3DTS_TEXTURE4:
2149 case D3DTS_TEXTURE5:
2150 case D3DTS_TEXTURE6:
2151 case D3DTS_TEXTURE7:
2152 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2153 break;
2155 default:
2156 FIXME("Unhandled transform state!!\n");
2157 break;
2159 } else {
2160 /**
2161 * Indexed Vertex Blending Matrices 256 -> 511
2162 * where WORLDMATRIX(0) == 256!
2164 /** store it */
2165 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2166 #if 0
2167 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2168 FIXME("TODO\n");
2169 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2170 FIXME("TODO\n");
2172 #endif
2176 * Move the GL operation to outside of switch to make it work
2177 * regardless of transform set order.
2179 ENTER_GL();
2180 if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
2181 glMatrixMode(GL_PROJECTION);
2182 checkGLcall("glMatrixMode");
2183 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
2184 checkGLcall("glLoadMatrixf");
2185 memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
2186 } else {
2187 TRACE("Skipping as projection already correct\n");
2190 glMatrixMode(GL_MODELVIEW);
2191 checkGLcall("glMatrixMode");
2192 viewChanged = FALSE;
2193 if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
2194 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2195 checkGLcall("glLoadMatrixf");
2196 memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
2197 viewChanged = TRUE;
2199 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
2200 if (d3dts == D3DTS_VIEW) {
2202 /* NOTE: We have to reset the positions even if the light/plane is not currently
2203 enabled, since the call to enable it will not reset the position. */
2205 /* Reset lights */
2206 for (k = 0; k < GL_LIMITS(lights); k++) {
2207 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
2208 checkGLcall("glLightfv posn");
2209 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
2210 checkGLcall("glLightfv dirn");
2213 /* Reset Clipping Planes if clipping is enabled */
2214 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2215 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
2216 checkGLcall("glClipPlane");
2219 /* Reapply texture transforms as based off modelview when applied */
2220 for (Stage = 0; Stage < GL_LIMITS(textures); Stage++) {
2222 /* Only applicable if the transforms are not disabled */
2223 if (This->UpdateStateBlock->texture_state[Stage][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
2225 /* Now apply texture transforms if not applying to the dummy textures */
2226 #if defined(GL_VERSION_1_3)
2227 glActiveTexture(GL_TEXTURE0 + Stage);
2228 #else
2229 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2230 #endif
2231 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
2233 glMatrixMode(GL_TEXTURE);
2234 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2235 glLoadIdentity();
2236 } else {
2237 D3DMATRIX fred;
2238 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2239 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2242 checkGLcall("Load matrix for texture");
2244 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2246 } else if ((d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) &&
2247 (This->UpdateStateBlock->texture_state[d3dts - D3DTS_TEXTURE0][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)) {
2248 /* Now apply texture transforms if not applying to the dummy textures */
2249 Stage = d3dts - D3DTS_TEXTURE0;
2251 if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX))) {
2252 memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX));
2254 #if defined(GL_VERSION_1_3)
2255 glActiveTexture(GL_TEXTURE0 + Stage);
2256 #else
2257 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2258 #endif
2259 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
2261 glMatrixMode(GL_TEXTURE);
2262 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2263 glLoadIdentity();
2264 } else {
2265 D3DMATRIX fred;
2266 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2267 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2269 checkGLcall("Load matrix for texture");
2270 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2271 } else {
2272 TRACE("Skipping texture transform as already correct\n");
2275 } else {
2276 TRACE("Skipping view setup as view already correct\n");
2280 * Vertex Blending as described
2281 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
2283 switch (This->UpdateStateBlock->vertex_blend) {
2284 case D3DVBF_DISABLE:
2286 if (viewChanged == TRUE ||
2287 (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
2288 memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
2289 if (viewChanged == FALSE) {
2290 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2291 checkGLcall("glLoadMatrixf");
2293 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
2294 checkGLcall("glMultMatrixf");
2295 } else {
2296 TRACE("Skipping as world already correct\n");
2299 break;
2300 case D3DVBF_1WEIGHTS:
2301 case D3DVBF_2WEIGHTS:
2302 case D3DVBF_3WEIGHTS:
2304 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
2306 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
2307 * so waiting for the values before matrix work
2308 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
2309 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
2310 checkGLcall("glMultMatrixf");
2314 break;
2315 case D3DVBF_TWEENING:
2317 FIXME("valid/correct D3DVBF_TWEENING\n");
2318 f = This->UpdateStateBlock->tween_factor;
2319 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
2320 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
2321 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
2322 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
2323 if (viewChanged == FALSE) {
2324 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2325 checkGLcall("glLoadMatrixf");
2327 glMultMatrixf((float *) &m.u.m[0][0]);
2328 checkGLcall("glMultMatrixf");
2330 break;
2331 case D3DVBF_0WEIGHTS:
2333 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
2334 /* single matrix of weight 1.0f */
2335 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
2336 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
2337 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
2338 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
2339 if (viewChanged == FALSE) {
2340 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2341 checkGLcall("glLoadMatrixf");
2343 glMultMatrixf((float *) &m.u.m[0][0]);
2344 checkGLcall("glMultMatrixf");
2346 break;
2347 default:
2348 break; /* stupid compilator */
2351 LEAVE_GL();
2353 return D3D_OK;
2356 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
2357 ICOM_THIS(IDirect3DDevice8Impl,iface);
2358 TRACE("(%p) : for State %d\n", This, State);
2359 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
2360 return D3D_OK;
2363 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2364 D3DMATRIX *mat = NULL;
2365 D3DMATRIX temp;
2367 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
2368 but works regardless of recording being on.
2369 If this is found to be wrong, change to StateBlock. */
2370 ICOM_THIS(IDirect3DDevice8Impl,iface);
2371 TRACE("(%p) : For state %u\n", This, State);
2373 if (State < HIGHEST_TRANSFORMSTATE)
2375 mat = &This->UpdateStateBlock->transforms[State];
2376 } else {
2377 FIXME("Unhandled transform state!!\n");
2380 /* Copied from ddraw code: */
2381 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
2382 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
2383 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
2384 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
2386 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
2387 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
2388 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
2389 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
2391 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
2392 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
2393 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
2394 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
2396 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
2397 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
2398 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
2399 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
2401 /* Apply change via set transform - will reapply to eg. lights this way */
2402 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
2403 return D3D_OK;
2405 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
2406 ICOM_THIS(IDirect3DDevice8Impl,iface);
2408 TRACE("(%p)\n", This);
2409 This->UpdateStateBlock->Changed.viewport = TRUE;
2410 This->UpdateStateBlock->Set.viewport = TRUE;
2411 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
2413 /* Handle recording of state blocks */
2414 if (This->isRecordingState) {
2415 TRACE("Recording... not performing anything\n");
2416 return D3D_OK;
2419 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2420 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2422 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2423 checkGLcall("glDepthRange");
2424 /* Note: GL requires lower left, DirectX supplies upper left */
2425 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
2426 pViewport->Width, pViewport->Height);
2427 checkGLcall("glViewport");
2430 return D3D_OK;
2433 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
2434 ICOM_THIS(IDirect3DDevice8Impl,iface);
2435 TRACE("(%p)\n", This);
2436 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
2437 return D3D_OK;
2440 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
2441 ICOM_THIS(IDirect3DDevice8Impl,iface);
2443 This->UpdateStateBlock->Changed.material = TRUE;
2444 This->UpdateStateBlock->Set.material = TRUE;
2445 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
2447 /* Handle recording of state blocks */
2448 if (This->isRecordingState) {
2449 TRACE("Recording... not performing anything\n");
2450 return D3D_OK;
2453 ENTER_GL();
2454 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2455 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2456 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2457 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2458 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2460 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
2461 checkGLcall("glMaterialfv");
2462 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
2463 checkGLcall("glMaterialfv");
2465 /* Only change material color if specular is enabled, otherwise it is set to black */
2466 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
2467 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2468 checkGLcall("glMaterialfv");
2470 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
2471 checkGLcall("glMaterialfv");
2472 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
2473 checkGLcall("glMaterialf");
2475 LEAVE_GL();
2476 return D3D_OK;
2478 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
2479 ICOM_THIS(IDirect3DDevice8Impl,iface);
2480 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
2481 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2482 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2483 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2484 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2485 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2486 return D3D_OK;
2489 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
2490 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
2491 float rho;
2492 float quad_att;
2494 ICOM_THIS(IDirect3DDevice8Impl,iface);
2495 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2497 if (Index >= GL_LIMITS(lights)) {
2498 TRACE("Cannot handle more lights than device supports\n");
2499 return D3DERR_INVALIDCALL;
2502 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2503 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2504 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2505 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2506 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2507 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2508 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2510 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
2511 This->UpdateStateBlock->Set.lights[Index] = TRUE;
2512 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
2514 /* Handle recording of state blocks */
2515 if (This->isRecordingState) {
2516 TRACE("Recording... not performing anything\n");
2517 return D3D_OK;
2520 /* Diffuse: */
2521 colRGBA[0] = pLight->Diffuse.r;
2522 colRGBA[1] = pLight->Diffuse.g;
2523 colRGBA[2] = pLight->Diffuse.b;
2524 colRGBA[3] = pLight->Diffuse.a;
2525 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2526 checkGLcall("glLightfv");
2528 /* Specular */
2529 colRGBA[0] = pLight->Specular.r;
2530 colRGBA[1] = pLight->Specular.g;
2531 colRGBA[2] = pLight->Specular.b;
2532 colRGBA[3] = pLight->Specular.a;
2533 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2534 checkGLcall("glLightfv");
2536 /* Ambient */
2537 colRGBA[0] = pLight->Ambient.r;
2538 colRGBA[1] = pLight->Ambient.g;
2539 colRGBA[2] = pLight->Ambient.b;
2540 colRGBA[3] = pLight->Ambient.a;
2541 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2542 checkGLcall("glLightfv");
2544 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2545 glMatrixMode(GL_MODELVIEW);
2546 glPushMatrix();
2547 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2549 /* Attenuation - Are these right? guessing... */
2550 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
2551 checkGLcall("glLightf");
2552 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
2553 checkGLcall("glLightf");
2555 quad_att = 1.4/(pLight->Range*pLight->Range);
2556 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2557 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2558 checkGLcall("glLightf");
2560 switch (pLight->Type) {
2561 case D3DLIGHT_POINT:
2562 /* Position */
2563 This->lightPosn[Index][0] = pLight->Position.x;
2564 This->lightPosn[Index][1] = pLight->Position.y;
2565 This->lightPosn[Index][2] = pLight->Position.z;
2566 This->lightPosn[Index][3] = 1.0;
2567 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2568 checkGLcall("glLightfv");
2570 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2571 checkGLcall("glLightf");
2573 /* FIXME: Range */
2574 break;
2576 case D3DLIGHT_SPOT:
2577 /* Position */
2578 This->lightPosn[Index][0] = pLight->Position.x;
2579 This->lightPosn[Index][1] = pLight->Position.y;
2580 This->lightPosn[Index][2] = pLight->Position.z;
2581 This->lightPosn[Index][3] = 1.0;
2582 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2583 checkGLcall("glLightfv");
2585 /* Direction */
2586 This->lightDirn[Index][0] = pLight->Direction.x;
2587 This->lightDirn[Index][1] = pLight->Direction.y;
2588 This->lightDirn[Index][2] = pLight->Direction.z;
2589 This->lightDirn[Index][3] = 1.0;
2590 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2591 checkGLcall("glLightfv");
2594 * opengl-ish and d3d-ish spot lights use too different models for the
2595 * light "intensity" as a function of the angle towards the main light direction,
2596 * so we only can approximate very roughly.
2597 * however spot lights are rather rarely used in games (if ever used at all).
2598 * furthermore if still used, probably nobody pays attention to such details.
2600 if (pLight->Falloff == 0) {
2601 rho = 6.28f;
2602 } else {
2603 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2605 if (rho < 0.0001) rho = 0.0001f;
2606 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2607 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2609 /* FIXME: Range */
2610 break;
2611 case D3DLIGHT_DIRECTIONAL:
2612 /* Direction */
2613 This->lightPosn[Index][0] = -pLight->Direction.x;
2614 This->lightPosn[Index][1] = -pLight->Direction.y;
2615 This->lightPosn[Index][2] = -pLight->Direction.z;
2616 This->lightPosn[Index][3] = 0.0;
2617 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2618 checkGLcall("glLightfv");
2620 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2621 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2624 break;
2625 default:
2626 FIXME("Unrecognized light type %d\n", pLight->Type);
2629 /* Restore the modelview matrix */
2630 glPopMatrix();
2632 return D3D_OK;
2634 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2635 ICOM_THIS(IDirect3DDevice8Impl,iface);
2636 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2638 if (Index >= GL_LIMITS(lights)) {
2639 TRACE("Cannot handle more lights than device supports\n");
2640 return D3DERR_INVALIDCALL;
2643 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2644 return D3D_OK;
2646 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2647 ICOM_THIS(IDirect3DDevice8Impl,iface);
2648 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2650 if (Index >= GL_LIMITS(lights)) {
2651 TRACE("Cannot handle more lights than device supports\n");
2652 return D3DERR_INVALIDCALL;
2655 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2656 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2657 This->UpdateStateBlock->lightEnable[Index] = Enable;
2659 /* Handle recording of state blocks */
2660 if (This->isRecordingState) {
2661 TRACE("Recording... not performing anything\n");
2662 return D3D_OK;
2665 if (Enable) {
2666 glEnable(GL_LIGHT0 + Index);
2667 checkGLcall("glEnable GL_LIGHT0+Index");
2668 } else {
2669 glDisable(GL_LIGHT0 + Index);
2670 checkGLcall("glDisable GL_LIGHT0+Index");
2672 return D3D_OK;
2674 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2675 ICOM_THIS(IDirect3DDevice8Impl,iface);
2676 TRACE("(%p) : for idx(%ld)\n", This, Index);
2678 if (Index >= GL_LIMITS(lights)) {
2679 TRACE("Cannot handle more lights than device supports\n");
2680 return D3DERR_INVALIDCALL;
2683 *pEnable = This->StateBlock->lightEnable[Index];
2684 return D3D_OK;
2686 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2687 ICOM_THIS(IDirect3DDevice8Impl,iface);
2688 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2690 /* Validate Index */
2691 if (Index >= GL_LIMITS(clipplanes)) {
2692 TRACE("Application has requested clipplane this device doesnt support\n");
2693 return D3DERR_INVALIDCALL;
2696 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2697 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2698 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2699 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2700 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2701 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2703 /* Handle recording of state blocks */
2704 if (This->isRecordingState) {
2705 TRACE("Recording... not performing anything\n");
2706 return D3D_OK;
2709 /* Apply it */
2711 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2712 glMatrixMode(GL_MODELVIEW);
2713 glPushMatrix();
2714 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2716 TRACE("Clipplane [%f,%f,%f,%f]\n",
2717 This->UpdateStateBlock->clipplane[Index][0],
2718 This->UpdateStateBlock->clipplane[Index][1],
2719 This->UpdateStateBlock->clipplane[Index][2],
2720 This->UpdateStateBlock->clipplane[Index][3]);
2721 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2723 glPopMatrix();
2724 checkGLcall("glClipPlane");
2726 return D3D_OK;
2728 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2729 ICOM_THIS(IDirect3DDevice8Impl,iface);
2730 TRACE("(%p) : for idx %ld\n", This, Index);
2732 /* Validate Index */
2733 if (Index >= GL_LIMITS(clipplanes)) {
2734 TRACE("Application has requested clipplane this device doesnt support\n");
2735 return D3DERR_INVALIDCALL;
2738 pPlane[0] = This->StateBlock->clipplane[Index][0];
2739 pPlane[1] = This->StateBlock->clipplane[Index][1];
2740 pPlane[2] = This->StateBlock->clipplane[Index][2];
2741 pPlane[3] = This->StateBlock->clipplane[Index][3];
2742 return D3D_OK;
2744 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2745 ICOM_THIS(IDirect3DDevice8Impl,iface);
2746 DWORD OldValue = This->StateBlock->renderstate[State];
2748 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2749 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2750 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2751 This->UpdateStateBlock->renderstate[State] = Value;
2753 /* Handle recording of state blocks */
2754 if (This->isRecordingState) {
2755 TRACE("Recording... not performing anything\n");
2756 return D3D_OK;
2759 switch (State) {
2760 case D3DRS_FILLMODE :
2761 switch ((D3DFILLMODE) Value) {
2762 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2763 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2764 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2765 default:
2766 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2768 checkGLcall("glPolygonMode (fillmode)");
2769 break;
2771 case D3DRS_LIGHTING :
2772 if (Value) {
2773 glEnable(GL_LIGHTING);
2774 checkGLcall("glEnable GL_LIGHTING");
2775 } else {
2776 glDisable(GL_LIGHTING);
2777 checkGLcall("glDisable GL_LIGHTING");
2779 break;
2781 case D3DRS_ZENABLE :
2782 switch ((D3DZBUFFERTYPE) Value) {
2783 case D3DZB_FALSE:
2784 glDisable(GL_DEPTH_TEST);
2785 checkGLcall("glDisable GL_DEPTH_TEST");
2786 break;
2787 case D3DZB_TRUE:
2788 glEnable(GL_DEPTH_TEST);
2789 checkGLcall("glEnable GL_DEPTH_TEST");
2790 break;
2792 case D3DZB_USEW:
2793 default:
2794 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2796 break;
2798 case D3DRS_CULLMODE :
2800 /* If we are culling "back faces with clockwise vertices" then
2801 set front faces to be counter clockwise and enable culling
2802 of back faces */
2803 switch ((D3DCULL) Value) {
2804 case D3DCULL_NONE:
2805 glDisable(GL_CULL_FACE);
2806 checkGLcall("glDisable GL_CULL_FACE");
2807 break;
2808 case D3DCULL_CW:
2809 glEnable(GL_CULL_FACE);
2810 checkGLcall("glEnable GL_CULL_FACE");
2811 glFrontFace(GL_CCW);
2812 checkGLcall("glFrontFace GL_CCW");
2813 glCullFace(GL_BACK);
2814 break;
2815 case D3DCULL_CCW:
2816 glEnable(GL_CULL_FACE);
2817 checkGLcall("glEnable GL_CULL_FACE");
2818 glFrontFace(GL_CW);
2819 checkGLcall("glFrontFace GL_CW");
2820 glCullFace(GL_BACK);
2821 break;
2822 default:
2823 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2825 break;
2827 case D3DRS_SHADEMODE :
2828 switch ((D3DSHADEMODE) Value) {
2829 case D3DSHADE_FLAT:
2830 glShadeModel(GL_FLAT);
2831 checkGLcall("glShadeModel");
2832 break;
2833 case D3DSHADE_GOURAUD:
2834 glShadeModel(GL_SMOOTH);
2835 checkGLcall("glShadeModel");
2836 break;
2837 case D3DSHADE_PHONG:
2838 FIXME("D3DSHADE_PHONG isnt supported?\n");
2839 return D3DERR_INVALIDCALL;
2840 default:
2841 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2843 break;
2845 case D3DRS_DITHERENABLE :
2846 if (Value) {
2847 glEnable(GL_DITHER);
2848 checkGLcall("glEnable GL_DITHER");
2849 } else {
2850 glDisable(GL_DITHER);
2851 checkGLcall("glDisable GL_DITHER");
2853 break;
2855 case D3DRS_ZWRITEENABLE :
2856 if (Value) {
2857 glDepthMask(1);
2858 checkGLcall("glDepthMask");
2859 } else {
2860 glDepthMask(0);
2861 checkGLcall("glDepthMask");
2863 break;
2865 case D3DRS_ZFUNC :
2867 int glParm = GL_LESS;
2869 switch ((D3DCMPFUNC) Value) {
2870 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2871 case D3DCMP_LESS: glParm=GL_LESS; break;
2872 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2873 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2874 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2875 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2876 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2877 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2878 default:
2879 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2881 glDepthFunc(glParm);
2882 checkGLcall("glDepthFunc");
2884 break;
2886 case D3DRS_AMBIENT :
2888 float col[4];
2889 D3DCOLORTOGLFLOAT4(Value, col);
2890 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2891 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2892 checkGLcall("glLightModel for MODEL_AMBIENT");
2895 break;
2897 case D3DRS_ALPHABLENDENABLE :
2898 if (Value) {
2899 glEnable(GL_BLEND);
2900 checkGLcall("glEnable GL_BLEND");
2901 } else {
2902 glDisable(GL_BLEND);
2903 checkGLcall("glDisable GL_BLEND");
2905 break;
2907 case D3DRS_SRCBLEND :
2908 case D3DRS_DESTBLEND :
2910 int newVal = GL_ZERO;
2911 switch (Value) {
2912 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2913 case D3DBLEND_ONE : newVal = GL_ONE; break;
2914 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2915 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2916 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2917 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2918 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2919 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2920 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2921 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2922 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2924 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2925 This->srcBlend = newVal;
2926 This->dstBlend = newVal;
2927 break;
2929 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2930 This->srcBlend = newVal;
2931 This->dstBlend = newVal;
2932 break;
2933 default:
2934 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2937 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2938 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2939 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2940 glBlendFunc(This->srcBlend, This->dstBlend);
2942 checkGLcall("glBlendFunc");
2944 break;
2946 case D3DRS_ALPHATESTENABLE :
2947 if (Value) {
2948 glEnable(GL_ALPHA_TEST);
2949 checkGLcall("glEnable GL_ALPHA_TEST");
2950 } else {
2951 glDisable(GL_ALPHA_TEST);
2952 checkGLcall("glDisable GL_ALPHA_TEST");
2954 break;
2956 case D3DRS_ALPHAFUNC :
2958 int glParm = GL_LESS;
2959 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2961 switch ((D3DCMPFUNC) Value) {
2962 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2963 case D3DCMP_LESS: glParm = GL_LESS; break;
2964 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2965 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2966 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2967 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2968 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2969 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2970 default:
2971 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2973 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2974 glAlphaFunc(glParm, ref);
2975 This->alphafunc = glParm;
2976 checkGLcall("glAlphaFunc");
2978 break;
2980 case D3DRS_ALPHAREF :
2982 int glParm = This->alphafunc;
2983 float ref = 1.0f;
2985 ref = ((float) Value) / 255.0f;
2986 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2987 glAlphaFunc(glParm, ref);
2988 checkGLcall("glAlphaFunc");
2990 break;
2992 case D3DRS_CLIPPLANEENABLE :
2993 case D3DRS_CLIPPING :
2995 /* Ensure we only do the changed clip planes */
2996 DWORD enable = 0xFFFFFFFF;
2997 DWORD disable = 0x00000000;
2999 /* If enabling / disabling all */
3000 if (State == D3DRS_CLIPPING) {
3001 if (Value) {
3002 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
3003 disable = 0x00;
3004 } else {
3005 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
3006 enable = 0x00;
3008 } else {
3009 enable = Value & ~OldValue;
3010 disable = ~Value & OldValue;
3013 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3014 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3015 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3016 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3017 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3018 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3020 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3021 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3022 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3023 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3024 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3025 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3027 break;
3029 case D3DRS_BLENDOP :
3031 int glParm = GL_FUNC_ADD;
3033 switch ((D3DBLENDOP) Value) {
3034 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3035 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3036 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3037 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3038 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3039 default:
3040 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3042 TRACE("glBlendEquation(%x)\n", glParm);
3043 glBlendEquation(glParm);
3044 checkGLcall("glBlendEquation");
3046 break;
3048 case D3DRS_TEXTUREFACTOR :
3050 int i;
3052 /* Note the texture color applies to all textures whereas
3053 GL_TEXTURE_ENV_COLOR applies to active only */
3054 float col[4];
3055 D3DCOLORTOGLFLOAT4(Value, col);
3056 /* Set the default alpha blend color */
3057 glBlendColor(col[0], col[1], col[2], col[3]);
3058 checkGLcall("glBlendColor");
3060 /* And now the default texture color as well */
3061 for (i = 0; i < GL_LIMITS(textures); i++) {
3063 /* Note the D3DRS value applies to all textures, but GL has one
3064 per texture, so apply it now ready to be used! */
3065 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3066 #if defined(GL_VERSION_1_3)
3067 glActiveTexture(GL_TEXTURE0 + i);
3068 #else
3069 glActiveTextureARB(GL_TEXTURE0_ARB + i);
3070 #endif
3071 checkGLcall("Activate texture.. to update const color");
3072 } else if (i>0) {
3073 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3076 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3077 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3080 break;
3082 case D3DRS_SPECULARENABLE :
3084 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3085 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3086 specular color. This is wrong:
3087 Seperate specular color means the specular colour is maintained seperately, whereas
3088 single color means it is merged in. However in both cases they are being used to
3089 some extent.
3090 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3091 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
3092 yet running 1.4!
3094 if (Value) {
3095 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
3096 checkGLcall("glMaterialfv");
3097 #if defined(GL_VERSION_1_4)
3098 glEnable(GL_COLOR_SUM);
3099 #elif defined(GL_EXT_secondary_color)
3100 glEnable(GL_COLOR_SUM_EXT);
3101 #elif defined(GL_ARB_vertex_program)
3102 glEnable(GL_COLOR_SUM_ARB);
3103 #else
3104 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3105 #endif
3106 checkGLcall("glEnable(GL_COLOR_)\n");
3107 } else {
3108 float black[4] = {0.0, 0.0, 0.0, 0.0};
3110 /* for the case of enabled lighting: */
3111 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3112 checkGLcall("glMaterialfv");
3114 /* for the case of disabled lighting: */
3115 #if defined(GL_VERSION_1_4)
3116 glDisable(GL_COLOR_SUM);
3117 #elif defined(GL_EXT_secondary_color)
3118 glDisable(GL_COLOR_SUM_EXT);
3119 #elif defined(GL_ARB_vertex_program)
3120 glDisable(GL_COLOR_SUM_ARB);
3121 #else
3122 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3123 #endif
3124 checkGLcall("glDisable(GL_COLOR_)\n");
3127 break;
3129 case D3DRS_STENCILENABLE :
3130 if (Value) {
3131 glEnable(GL_STENCIL_TEST);
3132 checkGLcall("glEnable GL_STENCIL_TEST");
3133 } else {
3134 glDisable(GL_STENCIL_TEST);
3135 checkGLcall("glDisable GL_STENCIL_TEST");
3137 break;
3139 case D3DRS_STENCILFUNC :
3141 int glParm = GL_ALWAYS;
3142 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
3143 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
3145 switch ((D3DCMPFUNC) Value) {
3146 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3147 case D3DCMP_LESS: glParm=GL_LESS; break;
3148 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3149 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3150 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3151 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3152 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3153 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3154 default:
3155 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3157 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3158 This->stencilfunc = glParm;
3159 glStencilFunc(glParm, ref, mask);
3160 checkGLcall("glStencilFunc");
3162 break;
3164 case D3DRS_STENCILREF :
3166 int glParm = This->stencilfunc;
3167 int ref = 0;
3168 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
3170 ref = Value;
3171 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3172 glStencilFunc(glParm, ref, mask);
3173 checkGLcall("glStencilFunc");
3175 break;
3177 case D3DRS_STENCILMASK :
3179 int glParm = This->stencilfunc;
3180 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
3181 GLuint mask = Value;
3183 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3184 glStencilFunc(glParm, ref, mask);
3185 checkGLcall("glStencilFunc");
3187 break;
3189 case D3DRS_STENCILFAIL :
3191 GLenum fail ;
3192 GLenum zpass ;
3193 GLenum zfail ;
3195 fail = StencilOp(Value);
3196 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3197 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3198 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3199 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3201 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3202 glStencilOp(fail, zfail, zpass);
3203 checkGLcall("glStencilOp(fail, zfail, zpass);");
3205 break;
3206 case D3DRS_STENCILZFAIL :
3208 GLenum fail ;
3209 GLenum zpass ;
3210 GLenum zfail ;
3212 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3213 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3214 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3215 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3216 zfail = StencilOp(Value);
3218 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3219 glStencilOp(fail, zfail, zpass);
3220 checkGLcall("glStencilOp(fail, zfail, zpass);");
3222 break;
3223 case D3DRS_STENCILPASS :
3225 GLenum fail ;
3226 GLenum zpass ;
3227 GLenum zfail ;
3229 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3230 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3231 zpass = StencilOp(Value);
3232 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3233 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3235 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3236 glStencilOp(fail, zfail, zpass);
3237 checkGLcall("glStencilOp(fail, zfail, zpass);");
3239 break;
3241 case D3DRS_STENCILWRITEMASK :
3243 glStencilMask(Value);
3244 TRACE("glStencilMask(%lu)\n", Value);
3245 checkGLcall("glStencilMask");
3247 break;
3249 case D3DRS_FOGENABLE :
3251 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
3252 glEnable(GL_FOG);
3253 checkGLcall("glEnable GL_FOG\n");
3254 } else {
3255 glDisable(GL_FOG);
3256 checkGLcall("glDisable GL_FOG\n");
3259 break;
3261 case D3DRS_FOGCOLOR :
3263 float col[4];
3264 D3DCOLORTOGLFLOAT4(Value, col);
3265 /* Set the default alpha blend color */
3266 glFogfv(GL_FOG_COLOR, &col[0]);
3267 checkGLcall("glFog GL_FOG_COLOR");
3269 break;
3271 case D3DRS_FOGTABLEMODE :
3273 switch (Value) {
3274 case D3DFOG_NONE: /* I don't know what to do here */ break;
3275 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3276 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3277 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3278 default:
3279 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
3282 break;
3284 case D3DRS_FOGSTART :
3286 float *f = (float*) &Value;
3287 glFogfv(GL_FOG_START, f);
3288 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3289 TRACE("Fog Start == %f\n", *f);
3291 break;
3293 case D3DRS_FOGEND :
3295 float *f = (float*) &Value;
3296 glFogfv(GL_FOG_END, f);
3297 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3298 TRACE("Fog End == %f\n", *f);
3300 break;
3302 case D3DRS_FOGDENSITY :
3304 float *f = (float*) &Value;
3305 glFogfv(GL_FOG_DENSITY, f);
3306 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3308 break;
3310 case D3DRS_VERTEXBLEND :
3312 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3313 TRACE("Vertex Blending state to %ld\n", Value);
3315 break;
3317 case D3DRS_TWEENFACTOR :
3319 This->UpdateStateBlock->tween_factor = *((float*) &Value);
3320 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
3322 break;
3324 case D3DRS_INDEXEDVERTEXBLENDENABLE :
3326 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3328 break;
3330 case D3DRS_COLORVERTEX :
3331 case D3DRS_DIFFUSEMATERIALSOURCE :
3332 case D3DRS_SPECULARMATERIALSOURCE :
3333 case D3DRS_AMBIENTMATERIALSOURCE :
3334 case D3DRS_EMISSIVEMATERIALSOURCE :
3336 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3338 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
3339 glEnable(GL_COLOR_MATERIAL);
3340 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
3342 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3343 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
3344 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
3345 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
3346 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
3348 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3349 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3350 Parm = GL_AMBIENT_AND_DIFFUSE;
3351 } else {
3352 Parm = GL_DIFFUSE;
3354 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3355 Parm = GL_AMBIENT;
3356 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3357 Parm = GL_EMISSION;
3358 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3359 Parm = GL_SPECULAR;
3360 } else {
3361 Parm = -1;
3364 if (Parm == -1) {
3365 glDisable(GL_COLOR_MATERIAL);
3366 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3367 } else {
3368 TRACE("glColorMaterial Parm=%d\n", Parm);
3369 glColorMaterial(GL_FRONT_AND_BACK, Parm);
3370 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
3373 } else {
3374 glDisable(GL_COLOR_MATERIAL);
3375 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3378 break;
3380 case D3DRS_LINEPATTERN :
3382 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
3383 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
3385 if (pattern->wRepeatFactor) {
3386 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
3387 checkGLcall("glLineStipple(repeat, linepattern)\n");
3388 glEnable(GL_LINE_STIPPLE);
3389 checkGLcall("glEnable(GL_LINE_STIPPLE);\n");
3390 } else {
3391 glDisable(GL_LINE_STIPPLE);
3392 checkGLcall("glDisable(GL_LINE_STIPPLE);\n");
3395 break;
3397 case D3DRS_ZBIAS :
3399 if (Value) {
3400 TRACE("ZBias value %f\n", *((float*)&Value));
3401 glPolygonOffset(0, -*((float*)&Value));
3402 checkGLcall("glPolygonOffset(0, -Value)");
3403 glEnable(GL_POLYGON_OFFSET_FILL);
3404 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3405 glEnable(GL_POLYGON_OFFSET_LINE);
3406 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3407 glEnable(GL_POLYGON_OFFSET_POINT);
3408 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3409 } else {
3410 glDisable(GL_POLYGON_OFFSET_FILL);
3411 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3412 glDisable(GL_POLYGON_OFFSET_LINE);
3413 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3414 glDisable(GL_POLYGON_OFFSET_POINT);
3415 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3418 break;
3420 case D3DRS_NORMALIZENORMALS :
3421 if (Value) {
3422 glEnable(GL_NORMALIZE);
3423 checkGLcall("glEnable(GL_NORMALIZE);");
3424 } else {
3425 glDisable(GL_NORMALIZE);
3426 checkGLcall("glDisable(GL_NORMALIZE);");
3428 break;
3430 case D3DRS_POINTSIZE :
3431 TRACE("Set point size to %f\n", *((float*)&Value));
3432 glPointSize(*((float*)&Value));
3433 checkGLcall("glPointSize(...);\n");
3434 break;
3436 case D3DRS_POINTSIZE_MIN :
3437 #if defined(GL_VERSION_1_4)
3438 glPointParameterf(GL_POINT_SIZE_MIN, *((float*)&Value));
3439 checkGLcall("glPointParameterf(...);\n");
3440 #elif defined(GL_EXT_point_parameters)
3441 glPointParameterfEXT(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
3442 checkGLcall("glPointParameterfEXT(...);\n");
3443 #elif defined(GL_ARB_point_parameters)
3444 glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, *((float*)&Value));
3445 checkGLcall("glPointParameterfARB(...);\n");
3446 #else
3447 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
3448 #endif
3449 break;
3451 case D3DRS_POINTSIZE_MAX :
3452 #if defined(GL_VERSION_1_4)
3453 glPointParameterf(GL_POINT_SIZE_MAX, *((float*)&Value));
3454 checkGLcall("glPointParameterf(...);\n");
3455 #elif defined(GL_EXT_point_parameters)
3456 glPointParameterfEXT(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
3457 checkGLcall("glPointParameterfEXT(...);\n");
3458 #elif defined(GL_ARB_point_parameters)
3459 glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, *((float*)&Value));
3460 checkGLcall("glPointParameterfARB(...);\n");
3461 #else
3462 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
3463 #endif
3464 break;
3466 case D3DRS_POINTSCALE_A :
3467 case D3DRS_POINTSCALE_B :
3468 case D3DRS_POINTSCALE_C :
3469 case D3DRS_POINTSCALEENABLE :
3471 /* If enabled, supply the parameters, otherwise fall back to defaults */
3472 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
3473 GLfloat att[3] = {1.0, 0.0, 0.0};
3474 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
3475 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
3476 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
3478 #if defined(GL_VERSION_1_4)
3479 glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, att);
3480 checkGLcall("glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, ...);\n");
3481 #elif defined(GL_EXT_point_parameters)
3482 glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, att);
3483 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
3484 #elif defined(GL_ARB_point_parameters)
3485 glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3486 checkGLcall("glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, ...);\n");
3487 #else
3488 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
3489 #endif
3490 } else {
3491 GLfloat att[3] = {1.0, 0.0, 0.0};
3492 #if defined(GL_VERSION_1_4)
3493 glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, att);
3494 checkGLcall("glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, ...);\n");
3495 #elif defined(GL_EXT_point_parameters)
3496 glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, att);
3497 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
3498 #elif defined(GL_ARB_point_parameters)
3499 glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3500 checkGLcall("glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, ...);\n");
3501 #else
3502 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
3503 #endif
3505 break;
3508 case D3DRS_COLORWRITEENABLE :
3509 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3510 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3511 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3512 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3513 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3514 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
3515 Value & D3DCOLORWRITEENABLE_GREEN,
3516 Value & D3DCOLORWRITEENABLE_BLUE,
3517 Value & D3DCOLORWRITEENABLE_ALPHA);
3518 checkGLcall("glColorMask(...)\n");
3519 break;
3521 /* Unhandled yet...! */
3522 case D3DRS_LASTPIXEL :
3523 case D3DRS_ZVISIBLE :
3524 case D3DRS_EDGEANTIALIAS :
3525 case D3DRS_RANGEFOGENABLE :
3526 case D3DRS_WRAP0 :
3527 case D3DRS_WRAP1 :
3528 case D3DRS_WRAP2 :
3529 case D3DRS_WRAP3 :
3530 case D3DRS_WRAP4 :
3531 case D3DRS_WRAP5 :
3532 case D3DRS_WRAP6 :
3533 case D3DRS_WRAP7 :
3534 case D3DRS_FOGVERTEXMODE :
3535 case D3DRS_LOCALVIEWER :
3536 case D3DRS_SOFTWAREVERTEXPROCESSING :
3537 case D3DRS_POINTSPRITEENABLE :
3538 case D3DRS_MULTISAMPLEANTIALIAS :
3539 case D3DRS_MULTISAMPLEMASK :
3540 case D3DRS_PATCHEDGESTYLE :
3541 case D3DRS_PATCHSEGMENTS :
3542 case D3DRS_DEBUGMONITORTOKEN :
3543 case D3DRS_POSITIONORDER :
3544 case D3DRS_NORMALORDER :
3545 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3546 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3547 break;
3548 default:
3549 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3552 return D3D_OK;
3554 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3555 ICOM_THIS(IDirect3DDevice8Impl,iface);
3556 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3557 *pValue = This->StateBlock->renderstate[State];
3558 return D3D_OK;
3560 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3561 ICOM_THIS(IDirect3DDevice8Impl,iface);
3563 TRACE("(%p)\n", This);
3565 return IDirect3DDeviceImpl_BeginStateBlock(This);
3567 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3568 IDirect3DStateBlockImpl* pSB;
3569 ICOM_THIS(IDirect3DDevice8Impl,iface);
3570 HRESULT res;
3572 TRACE("(%p)\n", This);
3574 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3575 *pToken = (DWORD) pSB;
3576 return res;
3579 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3580 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3581 ICOM_THIS(IDirect3DDevice8Impl,iface);
3583 TRACE("(%p)\n", This);
3585 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3588 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3589 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3590 ICOM_THIS(IDirect3DDevice8Impl,iface);
3592 TRACE("(%p)\n", This);
3594 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3596 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3597 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3598 ICOM_THIS(IDirect3DDevice8Impl,iface);
3600 TRACE("(%p)\n", This);
3602 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3605 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3606 IDirect3DStateBlockImpl* pSB;
3607 ICOM_THIS(IDirect3DDevice8Impl,iface);
3608 HRESULT res;
3610 TRACE("(%p) : for type %d\n", This, Type);
3612 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3613 *pToken = (DWORD) pSB;
3614 return res;
3617 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3618 ICOM_THIS(IDirect3DDevice8Impl,iface);
3619 FIXME("(%p) : stub\n", This); return D3D_OK;
3621 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3622 ICOM_THIS(IDirect3DDevice8Impl,iface);
3623 FIXME("(%p) : stub\n", This); return D3D_OK;
3625 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3626 ICOM_THIS(IDirect3DDevice8Impl,iface);
3627 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3628 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3629 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3630 return D3D_OK;
3632 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3634 IDirect3DBaseTexture8 *oldTxt;
3635 BOOL reapplyStates = TRUE;
3637 ICOM_THIS(IDirect3DDevice8Impl,iface);
3638 D3DRESOURCETYPE textureType;
3640 oldTxt = This->UpdateStateBlock->textures[Stage];
3641 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3643 /* Reject invalid texture units */
3644 if (Stage >= GL_LIMITS(textures)) {
3645 TRACE("Attempt to access invalid texture rejected\n");
3646 return D3DERR_INVALIDCALL;
3649 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3650 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3651 This->UpdateStateBlock->textures[Stage] = pTexture;
3653 /* Handle recording of state blocks */
3654 if (This->isRecordingState) {
3655 TRACE("Recording... not performing anything\n");
3656 return D3D_OK;
3659 /* Make appropriate texture active */
3660 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3661 #if defined(GL_VERSION_1_3)
3662 glActiveTexture(GL_TEXTURE0 + Stage);
3663 #else
3664 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3665 #endif
3666 checkGLcall("glActiveTextureARB");
3667 } else if (Stage>0) {
3668 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3671 /* Decrement the count of the previous texture */
3672 if (NULL != oldTxt) {
3673 IDirect3DBaseTexture8Impl_Release(oldTxt);
3676 if (NULL != pTexture) {
3677 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3679 /* Now setup the texture appropraitly */
3680 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3682 if (textureType == D3DRTYPE_TEXTURE) {
3683 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3684 TRACE("Skipping setting texture as old == new\n");
3685 reapplyStates = FALSE;
3686 } else {
3687 /* Standard 2D texture */
3688 TRACE("Standard 2d texture\n");
3689 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3691 /* Load up the texture now */
3692 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3694 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3695 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3696 TRACE("Skipping setting texture as old == new\n");
3697 reapplyStates = FALSE;
3698 } else {
3699 /* Standard 3D (volume) texture */
3700 TRACE("Standard 3d texture\n");
3701 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3703 /* Load up the texture now */
3704 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3706 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3707 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3708 TRACE("Skipping setting texture as old == new\n");
3709 reapplyStates = FALSE;
3710 } else {
3711 /* Standard Cube texture */
3712 TRACE("Standard Cube texture\n");
3713 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3715 /* Load up the texture now */
3716 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3718 } else {
3719 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3721 } else {
3722 TRACE("Setting to no texture (ie default texture)\n");
3723 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3724 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3725 checkGLcall("glBindTexture");
3726 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3729 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3730 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3731 if (reapplyStates) {
3732 setupTextureStates(iface, Stage);
3735 return D3D_OK;
3738 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3739 ICOM_THIS(IDirect3DDevice8Impl,iface);
3740 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3741 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3742 return D3D_OK;
3745 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3746 ICOM_THIS(IDirect3DDevice8Impl,iface);
3748 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3750 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value=%ld\n", This, Stage, Type, Value);
3752 /* Reject invalid texture units */
3753 if (Stage >= GL_LIMITS(textures)) {
3754 TRACE("Attempt to access invalid texture rejected\n");
3755 return D3DERR_INVALIDCALL;
3758 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3759 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3760 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3762 /* Handle recording of state blocks */
3763 if (This->isRecordingState) {
3764 TRACE("Recording... not performing anything\n");
3765 return D3D_OK;
3768 /* Make appropriate texture active */
3769 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3770 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3771 #if defined(GL_VERSION_1_3)
3772 glActiveTexture(GL_TEXTURE0 + Stage);
3773 vcheckGLcall("glActiveTexture");
3774 #else
3775 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3776 vcheckGLcall("glActiveTextureARB");
3777 #endif
3778 } else if (Stage > 0) {
3779 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3782 switch (Type) {
3784 case D3DTSS_MINFILTER :
3785 case D3DTSS_MIPFILTER :
3787 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3788 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3789 GLint realVal = GL_LINEAR;
3791 if (ValueMIN == D3DTEXF_POINT) {
3792 /* GL_NEAREST_* */
3793 if (ValueMIP == D3DTEXF_POINT) {
3794 realVal = GL_NEAREST_MIPMAP_NEAREST;
3795 } else if (ValueMIP == D3DTEXF_LINEAR) {
3796 realVal = GL_NEAREST_MIPMAP_LINEAR;
3797 } else if (ValueMIP == D3DTEXF_NONE) {
3798 realVal = GL_NEAREST;
3799 } else {
3800 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3801 realVal = GL_NEAREST_MIPMAP_LINEAR;
3803 } else if (ValueMIN == D3DTEXF_LINEAR) {
3804 /* GL_LINEAR_* */
3805 if (ValueMIP == D3DTEXF_POINT) {
3806 realVal = GL_LINEAR_MIPMAP_NEAREST;
3807 } else if (ValueMIP == D3DTEXF_LINEAR) {
3808 realVal = GL_LINEAR_MIPMAP_LINEAR;
3809 } else if (ValueMIP == D3DTEXF_NONE) {
3810 realVal = GL_LINEAR;
3811 } else {
3812 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3813 realVal = GL_LINEAR_MIPMAP_LINEAR;
3815 } else if (ValueMIN == D3DTEXF_NONE) {
3816 /* Doesnt really make sense - Windows just seems to disable
3817 mipmapping when this occurs */
3818 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3819 realVal = GL_LINEAR;
3821 } else {
3822 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3823 realVal = GL_LINEAR_MIPMAP_LINEAR;
3826 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3827 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3828 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3830 break;
3832 case D3DTSS_MAXANISOTROPY :
3834 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3835 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3836 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3839 break;
3841 case D3DTSS_MAGFILTER :
3842 if (Value == D3DTEXF_POINT) {
3843 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3844 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3845 } else if (Value == D3DTEXF_LINEAR) {
3846 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3847 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3848 } else {
3849 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3851 break;
3853 case D3DTSS_ALPHAOP :
3854 case D3DTSS_COLOROP :
3857 if (Value == D3DTOP_DISABLE) {
3858 /* TODO: Disable by making this and all later levels disabled */
3859 if (Type == D3DTSS_COLOROP) {
3860 glDisable(GL_TEXTURE_1D);
3861 checkGLcall("Disable GL_TEXTURE_1D");
3862 glDisable(GL_TEXTURE_2D);
3863 checkGLcall("Disable GL_TEXTURE_2D");
3864 glDisable(GL_TEXTURE_3D);
3865 checkGLcall("Disable GL_TEXTURE_3D");
3867 break; /* Dont bother setting the texture operations */
3868 } else {
3869 /* Enable only the appropriate texture dimension */
3870 if (Type == D3DTSS_COLOROP) {
3871 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3872 glEnable(GL_TEXTURE_1D);
3873 checkGLcall("Enable GL_TEXTURE_1D");
3874 } else {
3875 glDisable(GL_TEXTURE_1D);
3876 checkGLcall("Disable GL_TEXTURE_1D");
3878 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3879 glEnable(GL_TEXTURE_2D);
3880 checkGLcall("Enable GL_TEXTURE_2D");
3881 } else {
3882 glDisable(GL_TEXTURE_2D);
3883 checkGLcall("Disable GL_TEXTURE_2D");
3885 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3886 glEnable(GL_TEXTURE_3D);
3887 checkGLcall("Enable GL_TEXTURE_3D");
3888 } else {
3889 glDisable(GL_TEXTURE_3D);
3890 checkGLcall("Disable GL_TEXTURE_3D");
3892 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3893 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3894 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3895 } else {
3896 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3897 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3901 /* Drop through... (Except disable case) */
3902 case D3DTSS_COLORARG0 :
3903 case D3DTSS_COLORARG1 :
3904 case D3DTSS_COLORARG2 :
3905 case D3DTSS_ALPHAARG0 :
3906 case D3DTSS_ALPHAARG1 :
3907 case D3DTSS_ALPHAARG2 :
3909 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3910 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3911 if (isAlphaArg) {
3912 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3913 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3914 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3915 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3916 } else {
3917 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3918 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3919 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3920 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3923 break;
3926 case D3DTSS_ADDRESSU :
3927 case D3DTSS_ADDRESSV :
3928 case D3DTSS_ADDRESSW :
3930 GLint wrapParm = GL_REPEAT;
3931 switch (Value) {
3932 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3933 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3934 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3935 #if defined(GL_VERSION_1_4)
3936 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3937 #elif defined(GL_ARB_texture_mirrored_repeat)
3938 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3939 #else
3940 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3941 #endif
3942 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3943 default:
3944 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3945 wrapParm = GL_REPEAT;
3948 switch (Type) {
3949 case D3DTSS_ADDRESSU:
3950 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3951 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3952 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3953 break;
3954 case D3DTSS_ADDRESSV:
3955 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3956 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3957 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3958 break;
3959 case D3DTSS_ADDRESSW:
3960 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3961 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3962 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3963 break;
3964 default: /* nop */
3965 break; /** stupic compilator */
3968 break;
3970 case D3DTSS_BORDERCOLOR :
3972 float col[4];
3973 D3DCOLORTOGLFLOAT4(Value, col);
3974 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3975 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3976 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3978 break;
3980 case D3DTSS_TEXCOORDINDEX :
3982 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3984 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3985 one flag, you can still specify an index value, which the system uses to
3986 determine the texture wrapping mode.
3987 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3988 means use the vertex position (camera-space) as the input texture coordinates
3989 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3990 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3991 to the TEXCOORDINDEX value */
3993 /**
3994 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3996 switch (Value & 0xFFFF0000) {
3997 case D3DTSS_TCI_PASSTHRU:
3998 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3999 glDisable(GL_TEXTURE_GEN_S);
4000 glDisable(GL_TEXTURE_GEN_T);
4001 glDisable(GL_TEXTURE_GEN_R);
4002 break;
4004 case D3DTSS_TCI_CAMERASPACEPOSITION:
4005 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4006 as the input texture coordinates for this stage's texture transformation. This
4007 equates roughly to EYE_LINEAR */
4009 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4010 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4011 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4012 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4013 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4015 glMatrixMode(GL_MODELVIEW);
4016 glPushMatrix();
4017 glLoadIdentity();
4018 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4019 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4020 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4021 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4022 glPopMatrix();
4024 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4025 glEnable(GL_TEXTURE_GEN_S);
4026 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4027 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4028 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4029 glEnable(GL_TEXTURE_GEN_T);
4030 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4031 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4032 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4033 glEnable(GL_TEXTURE_GEN_R);
4034 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4035 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4036 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4038 break;
4040 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
4041 case D3DTSS_TCI_CAMERASPACENORMAL:
4043 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4044 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4045 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4046 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4047 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4049 glMatrixMode(GL_MODELVIEW);
4050 glPushMatrix();
4051 glLoadIdentity();
4052 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4053 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4054 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4055 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4056 glPopMatrix();
4058 glEnable(GL_TEXTURE_GEN_S);
4059 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4060 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
4061 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
4062 glEnable(GL_TEXTURE_GEN_T);
4063 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4064 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
4065 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
4066 glEnable(GL_TEXTURE_GEN_R);
4067 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4068 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
4069 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
4071 break;
4072 #endif
4074 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
4075 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4078 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4079 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4080 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4081 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4082 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4084 glMatrixMode(GL_MODELVIEW);
4085 glPushMatrix();
4086 glLoadIdentity();
4087 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4088 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4089 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4090 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4091 glPopMatrix();
4093 glEnable(GL_TEXTURE_GEN_S);
4094 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4095 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
4096 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
4097 glEnable(GL_TEXTURE_GEN_T);
4098 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4099 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
4100 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
4101 glEnable(GL_TEXTURE_GEN_R);
4102 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4103 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
4104 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
4106 break;
4107 #endif
4109 /* Unhandled types: */
4110 default:
4111 /* Todo: */
4112 /* ? disable GL_TEXTURE_GEN_n ? */
4113 glDisable(GL_TEXTURE_GEN_S);
4114 glDisable(GL_TEXTURE_GEN_T);
4115 glDisable(GL_TEXTURE_GEN_R);
4116 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
4117 break;
4120 break;
4122 /* Unhandled */
4123 case D3DTSS_BUMPENVMAT00 :
4124 case D3DTSS_BUMPENVMAT01 :
4125 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
4126 break;
4127 case D3DTSS_BUMPENVMAT10 :
4128 case D3DTSS_BUMPENVMAT11 :
4129 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
4130 break;
4132 case D3DTSS_TEXTURETRANSFORMFLAGS :
4134 switch (Value & ~D3DTTFF_PROJECTED)
4136 case D3DTTFF_DISABLE: /* Disable transform matrix for this texture by setting up the identity matrix */
4137 glMatrixMode(GL_TEXTURE);
4138 glLoadIdentity();
4139 checkGLcall("Load identity matrix for texture");
4140 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
4141 break;
4143 default: /* Enable it */
4144 IDirect3DDevice8Impl_SetTransform(iface, D3DTS_TEXTURE0+Stage, &This->UpdateStateBlock->transforms[D3DTS_TEXTURE0+Stage]);
4145 break;
4148 /* From web: <quote source="opengl12.pdf" section="Apendix C, Version 1.1/Other changes"
4149 2. Texture coordinates s, t, and r are divided by q during the rasterization
4150 of points, pixel rectangles, and bitmaps. This division was documented
4151 only for lines and polygons in the 1.0 version. </quote>
4152 I interpret this as we can implement projected transforms in slow vertex mode
4153 by moving the last coord to the 'q' coord and using one less dimension. The only
4154 way to do it in TexCoordPtr would be to massage the data stream to insert extra
4155 coords */
4157 break;
4159 case D3DTSS_MIPMAPLODBIAS :
4160 case D3DTSS_MAXMIPLEVEL :
4161 case D3DTSS_BUMPENVLSCALE :
4162 case D3DTSS_BUMPENVLOFFSET :
4163 case D3DTSS_RESULTARG :
4164 default:
4165 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4166 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4168 return D3D_OK;
4170 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
4171 ICOM_THIS(IDirect3DDevice8Impl,iface);
4172 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
4173 return D3D_OK;
4175 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
4176 ICOM_THIS(IDirect3DDevice8Impl,iface);
4177 FIXME("(%p) : stub\n", This);
4178 return D3D_OK;
4180 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4181 ICOM_THIS(IDirect3DDevice8Impl,iface);
4182 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
4183 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
4184 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
4185 return D3D_OK;
4187 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4188 ICOM_THIS(IDirect3DDevice8Impl,iface);
4189 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
4190 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
4191 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
4192 return D3D_OK;
4194 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
4195 ICOM_THIS(IDirect3DDevice8Impl,iface);
4196 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
4197 This->currentPalette = PaletteNumber;
4198 #if defined(GL_EXT_paletted_texture)
4199 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
4200 glColorTableEXT(GL_TEXTURE_2D, /* target */
4201 GL_RGBA, /* internal format */
4202 256, /* table size */
4203 GL_RGBA, /* table format */
4204 GL_UNSIGNED_BYTE, /* table type */
4205 This->palettes[PaletteNumber]);
4206 checkGLcall("glColorTableEXT");
4207 } else {
4208 /* Delayed palette handling ... waiting for software emulation into preload code */
4210 #endif
4211 return D3D_OK;
4213 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
4214 ICOM_THIS(IDirect3DDevice8Impl,iface);
4215 *PaletteNumber = This->currentPalette;
4216 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
4217 return D3D_OK;
4219 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
4221 IDirect3DVertexBuffer8 *pVB;
4223 ICOM_THIS(IDirect3DDevice8Impl,iface);
4224 pVB = This->StateBlock->stream_source[0];
4226 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
4228 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
4229 This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
4231 return D3D_OK;
4233 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
4234 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
4235 UINT idxStride = 2;
4236 IDirect3DIndexBuffer8 *pIB;
4237 IDirect3DVertexBuffer8 *pVB;
4238 D3DINDEXBUFFER_DESC IdxBufDsc;
4240 ICOM_THIS(IDirect3DDevice8Impl,iface);
4241 pIB = This->StateBlock->pIndexData;
4242 pVB = This->StateBlock->stream_source[0];
4244 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
4245 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4246 minIndex, NumVertices, startIndex, primCount);
4248 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
4249 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
4250 idxStride = 2;
4251 } else {
4252 idxStride = 4;
4255 DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
4256 This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
4257 minIndex);
4259 return D3D_OK;
4261 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
4262 ICOM_THIS(IDirect3DDevice8Impl,iface);
4264 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4265 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4267 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4269 This->StateBlock->stream_source[0] = NULL;
4270 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4271 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4272 0, 0, 0, NULL, 0);
4273 This->StateBlock->stream_stride[0] = 0;
4275 /*stream zero settings set to null at end */
4276 return D3D_OK;
4278 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4279 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4280 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4281 UINT VertexStreamZeroStride) {
4282 int idxStride;
4283 ICOM_THIS(IDirect3DDevice8Impl,iface);
4284 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4285 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4287 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4288 if (IndexDataFormat == D3DFMT_INDEX16) {
4289 idxStride = 2;
4290 } else {
4291 idxStride = 4;
4294 This->StateBlock->stream_source[0] = NULL;
4295 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4296 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4297 This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4299 /*stream zero settings set to null at end */
4300 This->StateBlock->stream_stride[0] = 0;
4301 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4303 return D3D_OK;
4305 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4306 ICOM_THIS(IDirect3DDevice8Impl,iface);
4307 FIXME("(%p) : stub\n", This); return D3D_OK;
4309 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4310 ICOM_THIS(IDirect3DDevice8Impl,iface);
4311 IDirect3DVertexShaderImpl* object;
4312 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4313 HRESULT res;
4314 UINT i;
4316 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
4317 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4318 return D3DERR_INVALIDCALL;
4320 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4321 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4322 return D3DERR_OUTOFVIDEOMEMORY;
4325 /** Create the Vertex Shader */
4326 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4327 /** TODO: check FAILED(res) */
4329 /** Create and Bind the Vertex Shader Declaration */
4330 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4331 /** TODO: check FAILED(res) */
4333 VertexShaders[i] = object;
4334 VertexShaderDeclarations[i] = attached_decl;
4335 *pHandle = VS_HIGHESTFIXEDFXF + i;
4337 return D3D_OK;
4339 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4340 ICOM_THIS(IDirect3DDevice8Impl,iface);
4342 This->UpdateStateBlock->VertexShader = Handle;
4343 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4344 This->UpdateStateBlock->Set.vertexShader = TRUE;
4346 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4347 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4348 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4349 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4350 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4351 } else { /* use a fvf, so desactivate the vshader decl */
4352 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4353 This->UpdateStateBlock->vertexShaderDecl = NULL;
4354 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4355 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4357 /* Handle recording of state blocks */
4358 if (This->isRecordingState) {
4359 TRACE("Recording... not performing anything\n");
4360 return D3D_OK;
4363 * TODO: merge HAL shaders context switching from prototype
4365 return D3D_OK;
4367 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4368 ICOM_THIS(IDirect3DDevice8Impl,iface);
4369 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4370 *pHandle = This->StateBlock->VertexShader;
4371 return D3D_OK;
4374 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4375 ICOM_THIS(IDirect3DDevice8Impl,iface);
4376 IDirect3DVertexShaderImpl* object;
4377 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4379 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4380 return D3DERR_INVALIDCALL;
4384 * Delete Vertex Shader
4386 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4387 if (NULL == object) {
4388 return D3DERR_INVALIDCALL;
4390 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4391 /* TODO: check validity of object */
4392 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4393 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4394 HeapFree(GetProcessHeap(), 0, (void *)object);
4395 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4398 * Delete Vertex Shader Declaration
4400 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4401 if (NULL == attached_decl) {
4402 return D3DERR_INVALIDCALL;
4404 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4405 /* TODO: check validity of object */
4406 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4407 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4408 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4410 return D3D_OK;
4413 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4414 ICOM_THIS(IDirect3DDevice8Impl,iface);
4416 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4417 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4418 return D3DERR_INVALIDCALL;
4420 if (NULL == pConstantData) {
4421 return D3DERR_INVALIDCALL;
4423 if (ConstantCount > 1) {
4424 FLOAT* f = (FLOAT*)pConstantData;
4425 UINT i;
4426 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4427 for (i = 0; i < ConstantCount; ++i) {
4428 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4429 f += 4;
4431 } else {
4432 FLOAT* f = (FLOAT*) pConstantData;
4433 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4435 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4436 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4437 return D3D_OK;
4439 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4440 ICOM_THIS(IDirect3DDevice8Impl,iface);
4442 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4443 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4444 return D3DERR_INVALIDCALL;
4446 if (NULL == pConstantData) {
4447 return D3DERR_INVALIDCALL;
4449 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4450 return D3D_OK;
4452 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4453 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4454 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4456 attached_decl = VERTEX_SHADER_DECL(Handle);
4457 if (NULL == attached_decl) {
4458 return D3DERR_INVALIDCALL;
4460 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4462 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4463 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4464 IDirect3DVertexShaderImpl* object;
4466 object = VERTEX_SHADER(Handle);
4467 if (NULL == object) {
4468 return D3DERR_INVALIDCALL;
4470 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4473 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4474 ICOM_THIS(IDirect3DDevice8Impl,iface);
4475 IDirect3DIndexBuffer8 *oldIdxs;
4477 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4478 oldIdxs = This->StateBlock->pIndexData;
4480 This->UpdateStateBlock->Changed.Indices = TRUE;
4481 This->UpdateStateBlock->Set.Indices = TRUE;
4482 This->UpdateStateBlock->pIndexData = pIndexData;
4483 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4485 /* Handle recording of state blocks */
4486 if (This->isRecordingState) {
4487 TRACE("Recording... not performing anything\n");
4488 return D3D_OK;
4491 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4492 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4493 return D3D_OK;
4495 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4496 ICOM_THIS(IDirect3DDevice8Impl,iface);
4497 FIXME("(%p) : stub\n", This);
4499 *ppIndexData = This->StateBlock->pIndexData;
4500 /* up ref count on ppindexdata */
4501 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4502 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4504 return D3D_OK;
4506 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4507 ICOM_THIS(IDirect3DDevice8Impl,iface);
4508 IDirect3DPixelShaderImpl* object;
4509 HRESULT res;
4510 UINT i;
4512 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4513 if (NULL == pFunction || NULL == pHandle) {
4514 return D3DERR_INVALIDCALL;
4516 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4517 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4518 return D3DERR_OUTOFVIDEOMEMORY;
4521 /** Create the Pixel Shader */
4522 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4523 if (SUCCEEDED(res)) {
4524 PixelShaders[i] = object;
4525 *pHandle = VS_HIGHESTFIXEDFXF + i;
4526 return D3D_OK;
4528 *pHandle = 0xFFFFFFFF;
4529 return res;
4531 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4532 ICOM_THIS(IDirect3DDevice8Impl,iface);
4534 This->UpdateStateBlock->PixelShader = Handle;
4535 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4536 This->UpdateStateBlock->Set.pixelShader = TRUE;
4538 /* Handle recording of state blocks */
4539 if (This->isRecordingState) {
4540 TRACE_(d3d_shader)("Recording... not performing anything\n");
4541 return D3D_OK;
4544 /* FIXME: Quieten when not being used */
4545 if (Handle != 0) {
4546 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4547 } else {
4548 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4551 return D3D_OK;
4553 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4554 ICOM_THIS(IDirect3DDevice8Impl,iface);
4555 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4556 *pHandle = This->StateBlock->PixelShader;
4557 return D3D_OK;
4560 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4561 ICOM_THIS(IDirect3DDevice8Impl,iface);
4562 IDirect3DPixelShaderImpl* object;
4564 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4565 return D3DERR_INVALIDCALL;
4567 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4568 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4569 /* TODO: check validity of object before free */
4570 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4571 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4572 HeapFree(GetProcessHeap(), 0, (void *)object);
4573 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4575 return D3D_OK;
4578 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4579 ICOM_THIS(IDirect3DDevice8Impl,iface);
4581 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4582 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4583 return D3DERR_INVALIDCALL;
4585 if (NULL == pConstantData) {
4586 return D3DERR_INVALIDCALL;
4588 if (ConstantCount > 1) {
4589 FLOAT* f = (FLOAT*)pConstantData;
4590 UINT i;
4591 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4592 for (i = 0; i < ConstantCount; ++i) {
4593 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4594 f += 4;
4596 } else {
4597 FLOAT* f = (FLOAT*) pConstantData;
4598 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4600 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4601 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4602 return D3D_OK;
4604 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4605 ICOM_THIS(IDirect3DDevice8Impl,iface);
4607 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4608 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4609 return D3DERR_INVALIDCALL;
4611 if (NULL == pConstantData) {
4612 return D3DERR_INVALIDCALL;
4614 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4615 return D3D_OK;
4617 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4618 IDirect3DPixelShaderImpl* object;
4620 object = PIXEL_SHADER(Handle);
4621 if (NULL == object) {
4622 return D3DERR_INVALIDCALL;
4624 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4626 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4627 ICOM_THIS(IDirect3DDevice8Impl,iface);
4628 FIXME("(%p) : stub\n", This); return D3D_OK;
4630 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4631 ICOM_THIS(IDirect3DDevice8Impl,iface);
4632 FIXME("(%p) : stub\n", This); return D3D_OK;
4634 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4635 ICOM_THIS(IDirect3DDevice8Impl,iface);
4636 FIXME("(%p) : stub\n", This); return D3D_OK;
4639 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4640 IDirect3DVertexBuffer8 *oldSrc;
4641 ICOM_THIS(IDirect3DDevice8Impl,iface);
4643 oldSrc = This->StateBlock->stream_source[StreamNumber];
4644 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4646 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4647 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4648 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4649 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4651 /* Handle recording of state blocks */
4652 if (This->isRecordingState) {
4653 TRACE("Recording... not performing anything\n");
4654 return D3D_OK;
4657 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4658 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4659 return D3D_OK;
4661 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4662 ICOM_THIS(IDirect3DDevice8Impl,iface);
4663 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4664 *pStream = This->StateBlock->stream_source[StreamNumber];
4665 *pStride = This->StateBlock->stream_stride[StreamNumber];
4666 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4667 return D3D_OK;
4671 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4673 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4674 IDirect3DDevice8Impl_QueryInterface,
4675 IDirect3DDevice8Impl_AddRef,
4676 IDirect3DDevice8Impl_Release,
4677 IDirect3DDevice8Impl_TestCooperativeLevel,
4678 IDirect3DDevice8Impl_GetAvailableTextureMem,
4679 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4680 IDirect3DDevice8Impl_GetDirect3D,
4681 IDirect3DDevice8Impl_GetDeviceCaps,
4682 IDirect3DDevice8Impl_GetDisplayMode,
4683 IDirect3DDevice8Impl_GetCreationParameters,
4684 IDirect3DDevice8Impl_SetCursorProperties,
4685 IDirect3DDevice8Impl_SetCursorPosition,
4686 IDirect3DDevice8Impl_ShowCursor,
4687 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4688 IDirect3DDevice8Impl_Reset,
4689 IDirect3DDevice8Impl_Present,
4690 IDirect3DDevice8Impl_GetBackBuffer,
4691 IDirect3DDevice8Impl_GetRasterStatus,
4692 IDirect3DDevice8Impl_SetGammaRamp,
4693 IDirect3DDevice8Impl_GetGammaRamp,
4694 IDirect3DDevice8Impl_CreateTexture,
4695 IDirect3DDevice8Impl_CreateVolumeTexture,
4696 IDirect3DDevice8Impl_CreateCubeTexture,
4697 IDirect3DDevice8Impl_CreateVertexBuffer,
4698 IDirect3DDevice8Impl_CreateIndexBuffer,
4699 IDirect3DDevice8Impl_CreateRenderTarget,
4700 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4701 IDirect3DDevice8Impl_CreateImageSurface,
4702 IDirect3DDevice8Impl_CopyRects,
4703 IDirect3DDevice8Impl_UpdateTexture,
4704 IDirect3DDevice8Impl_GetFrontBuffer,
4705 IDirect3DDevice8Impl_SetRenderTarget,
4706 IDirect3DDevice8Impl_GetRenderTarget,
4707 IDirect3DDevice8Impl_GetDepthStencilSurface,
4708 IDirect3DDevice8Impl_BeginScene,
4709 IDirect3DDevice8Impl_EndScene,
4710 IDirect3DDevice8Impl_Clear,
4711 IDirect3DDevice8Impl_SetTransform,
4712 IDirect3DDevice8Impl_GetTransform,
4713 IDirect3DDevice8Impl_MultiplyTransform,
4714 IDirect3DDevice8Impl_SetViewport,
4715 IDirect3DDevice8Impl_GetViewport,
4716 IDirect3DDevice8Impl_SetMaterial,
4717 IDirect3DDevice8Impl_GetMaterial,
4718 IDirect3DDevice8Impl_SetLight,
4719 IDirect3DDevice8Impl_GetLight,
4720 IDirect3DDevice8Impl_LightEnable,
4721 IDirect3DDevice8Impl_GetLightEnable,
4722 IDirect3DDevice8Impl_SetClipPlane,
4723 IDirect3DDevice8Impl_GetClipPlane,
4724 IDirect3DDevice8Impl_SetRenderState,
4725 IDirect3DDevice8Impl_GetRenderState,
4726 IDirect3DDevice8Impl_BeginStateBlock,
4727 IDirect3DDevice8Impl_EndStateBlock,
4728 IDirect3DDevice8Impl_ApplyStateBlock,
4729 IDirect3DDevice8Impl_CaptureStateBlock,
4730 IDirect3DDevice8Impl_DeleteStateBlock,
4731 IDirect3DDevice8Impl_CreateStateBlock,
4732 IDirect3DDevice8Impl_SetClipStatus,
4733 IDirect3DDevice8Impl_GetClipStatus,
4734 IDirect3DDevice8Impl_GetTexture,
4735 IDirect3DDevice8Impl_SetTexture,
4736 IDirect3DDevice8Impl_GetTextureStageState,
4737 IDirect3DDevice8Impl_SetTextureStageState,
4738 IDirect3DDevice8Impl_ValidateDevice,
4739 IDirect3DDevice8Impl_GetInfo,
4740 IDirect3DDevice8Impl_SetPaletteEntries,
4741 IDirect3DDevice8Impl_GetPaletteEntries,
4742 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4743 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4744 IDirect3DDevice8Impl_DrawPrimitive,
4745 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4746 IDirect3DDevice8Impl_DrawPrimitiveUP,
4747 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4748 IDirect3DDevice8Impl_ProcessVertices,
4749 IDirect3DDevice8Impl_CreateVertexShader,
4750 IDirect3DDevice8Impl_SetVertexShader,
4751 IDirect3DDevice8Impl_GetVertexShader,
4752 IDirect3DDevice8Impl_DeleteVertexShader,
4753 IDirect3DDevice8Impl_SetVertexShaderConstant,
4754 IDirect3DDevice8Impl_GetVertexShaderConstant,
4755 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4756 IDirect3DDevice8Impl_GetVertexShaderFunction,
4757 IDirect3DDevice8Impl_SetStreamSource,
4758 IDirect3DDevice8Impl_GetStreamSource,
4759 IDirect3DDevice8Impl_SetIndices,
4760 IDirect3DDevice8Impl_GetIndices,
4761 IDirect3DDevice8Impl_CreatePixelShader,
4762 IDirect3DDevice8Impl_SetPixelShader,
4763 IDirect3DDevice8Impl_GetPixelShader,
4764 IDirect3DDevice8Impl_DeletePixelShader,
4765 IDirect3DDevice8Impl_SetPixelShaderConstant,
4766 IDirect3DDevice8Impl_GetPixelShaderConstant,
4767 IDirect3DDevice8Impl_GetPixelShaderFunction,
4768 IDirect3DDevice8Impl_DrawRectPatch,
4769 IDirect3DDevice8Impl_DrawTriPatch,
4770 IDirect3DDevice8Impl_DeletePatch
4773 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface) {
4774 ICOM_THIS(IDirect3DDevice8Impl,iface);
4775 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4776 #if 0
4777 if (This->glCtx != This->render_ctx) {
4778 glXDestroyContext(This->display, This->render_ctx);
4779 This->render_ctx = This->glCtx;
4781 #endif
4782 if (This->win != This->drawable) {
4783 glXDestroyPbuffer(This->display, This->drawable);
4784 This->drawable = This->win;
4786 #endif
4787 return D3D_OK;
4790 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4791 IDirect3DSurface8* RenderSurface,
4792 IDirect3DSurface8* StencilSurface) {
4795 * Currently only active for GLX >= 1.3
4796 * for others versions we'll have to use GLXPixmaps
4798 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4799 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4800 * so only check OpenGL version
4802 #if defined(GL_VERSION_1_3)
4804 GLXFBConfig* cfgs = NULL;
4805 int nCfgs = 0;
4806 int attribs[256];
4807 int nAttribs = 0;
4808 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4809 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4810 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4811 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4812 IDirect3DSurface8Impl* tmp;
4814 ICOM_THIS(IDirect3DDevice8Impl,iface);
4816 #define PUSH1(att) attribs[nAttribs++] = (att);
4817 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4819 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4820 PUSH2(GLX_X_RENDERABLE, TRUE);
4821 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4823 switch (BackBufferFormat) {
4824 /* color buffer */
4825 case D3DFMT_P8:
4826 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4827 PUSH2(GLX_BUFFER_SIZE, 8);
4828 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4829 break;
4831 case D3DFMT_R3G3B2:
4832 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4833 PUSH2(GLX_RED_SIZE, 3);
4834 PUSH2(GLX_GREEN_SIZE, 3);
4835 PUSH2(GLX_BLUE_SIZE, 2);
4836 break;
4838 case D3DFMT_A1R5G5B5:
4839 PUSH2(GLX_ALPHA_SIZE, 1);
4840 case D3DFMT_X1R5G5B5:
4841 PUSH2(GLX_RED_SIZE, 5);
4842 PUSH2(GLX_GREEN_SIZE, 5);
4843 PUSH2(GLX_BLUE_SIZE, 5);
4844 break;
4846 case D3DFMT_R5G6B5:
4847 PUSH2(GLX_RED_SIZE, 5);
4848 PUSH2(GLX_GREEN_SIZE, 6);
4849 PUSH2(GLX_BLUE_SIZE, 5);
4850 break;
4852 case D3DFMT_A4R4G4B4:
4853 PUSH2(GLX_ALPHA_SIZE, 4);
4854 case D3DFMT_X4R4G4B4:
4855 PUSH2(GLX_RED_SIZE, 4);
4856 PUSH2(GLX_GREEN_SIZE, 4);
4857 PUSH2(GLX_BLUE_SIZE, 4);
4858 break;
4860 case D3DFMT_A8R8G8B8:
4861 PUSH2(GLX_ALPHA_SIZE, 8);
4862 case D3DFMT_R8G8B8:
4863 case D3DFMT_X8R8G8B8:
4864 PUSH2(GLX_RED_SIZE, 8);
4865 PUSH2(GLX_GREEN_SIZE, 8);
4866 PUSH2(GLX_BLUE_SIZE, 8);
4867 break;
4869 default:
4870 break;
4873 switch (StencilBufferFormat) {
4874 case D3DFMT_D16_LOCKABLE:
4875 case D3DFMT_D16:
4876 PUSH2(GLX_DEPTH_SIZE, 16);
4877 break;
4879 case D3DFMT_D15S1:
4880 PUSH2(GLX_DEPTH_SIZE, 15);
4881 break;
4883 case D3DFMT_D24X8:
4884 PUSH2(GLX_DEPTH_SIZE, 24);
4885 break;
4887 case D3DFMT_D24X4S4:
4888 PUSH2(GLX_DEPTH_SIZE, 24);
4889 PUSH2(GLX_STENCIL_SIZE, 4);
4890 break;
4892 case D3DFMT_D24S8:
4893 PUSH2(GLX_DEPTH_SIZE, 24);
4894 PUSH2(GLX_STENCIL_SIZE, 8);
4895 break;
4897 case D3DFMT_D32:
4898 PUSH2(GLX_DEPTH_SIZE, 32);
4899 break;
4901 default:
4902 break;
4905 PUSH1(None);
4907 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4908 if (NULL != cfgs) {
4909 #if 0
4910 int i;
4911 for (i = 0; i < nCfgs; ++i) {
4912 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4914 #endif
4916 if (NULL != This->renderTarget) {
4917 GLenum prev_read;
4918 glFlush();
4919 vcheckGLcall("glFlush");
4921 #if 0
4922 /** very very usefull debug code */
4923 glXSwapBuffers(This->display, This->drawable);
4924 printf("Hit Enter to get next frame ...\n");
4925 getchar();
4926 #endif
4928 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4929 vcheckGLcall("glIntegerv");
4930 glReadBuffer(GL_BACK);
4931 vcheckGLcall("glReadBuffer");
4933 long j;
4934 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4935 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4936 glReadPixels(0,
4937 This->renderTarget->myDesc.Height - j - 1,
4938 This->renderTarget->myDesc.Width,
4940 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4941 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4942 This->renderTarget->allocatedMemory + j * pitch);
4943 vcheckGLcall("glReadPixels");
4946 glReadBuffer(prev_read);
4947 vcheckGLcall("glReadBuffer");
4950 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4951 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4952 nAttribs = 0;
4953 PUSH2(GLX_PBUFFER_WIDTH, Width);
4954 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4955 PUSH1(None);
4956 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4958 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4959 if (NULL == This->render_ctx) {
4960 ERR("cannot create glxContext\n");
4963 glFlush();
4964 glXSwapBuffers(This->display, This->drawable);
4965 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4966 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4968 checkGLcall("glXMakeContextCurrent");
4971 tmp = This->renderTarget;
4972 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4973 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4974 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4976 tmp = This->stencilBufferTarget;
4977 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4978 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4979 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4981 return D3D_OK;
4983 } else {
4984 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4987 #undef PUSH1
4988 #undef PUSH2
4990 #endif
4992 return D3DERR_INVALIDCALL;