- add a new private header d3dcore_gl.h that declares needed opengl
[wine/dcerpc.git] / dlls / d3d8 / device.c
blob224b7e8d4cdd5b782d738812562a995c44ec0062
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 /*#undef GLX_GLXEXT_LEGACY*/
36 #include "d3d8_private.h"
37 #include <GL/glext.h>
38 #include <GL/glxext.h>
40 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
41 #undef GL_VERSION_1_4
43 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
44 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
46 /* Some #defines for additional diagnostics */
48 /* Per-vertex trace: */
49 #if 0
50 # define VTRACE(A) TRACE A
51 #else
52 # define VTRACE(A)
53 #endif
56 static IDirect3DVertexShaderImpl* VertexShaders[64];
57 static IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
58 static IDirect3DPixelShaderImpl* PixelShaders[64];
60 /* CreateVertexShader can return > 0xFFFF */
61 #define VS_HIGHESTFIXEDFXF 0xF0000000
64 * Utility functions or macros
66 #define conv_mat(mat,gl_mat) \
67 do { \
68 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
69 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
70 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
71 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
72 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
73 } while (0)
75 #define VERTEX_SHADER(Handle) \
76 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
77 #define VERTEX_SHADER_DECL(Handle) \
78 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
79 #define PIXEL_SHADER(Handle) \
80 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
82 #define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
84 /* Routine common to the draw primitive and draw indexed primitive routines */
85 void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
86 int PrimitiveType,
87 long NumPrimitives,
88 BOOL isIndexed,
90 /* For Both:*/
91 D3DFORMAT fvf,
92 const void *vertexBufData,
94 /* for Indexed: */
95 long StartVertexIndex,
96 long StartIdx,
97 short idxBytes,
98 const void *idxData,
99 int minIndex) {
101 int NumVertexes = NumPrimitives;
102 IDirect3DVertexShaderImpl* vertex_shader = NULL;
103 BOOL useVertexShaderFunction = FALSE;
105 ICOM_THIS(IDirect3DDevice8Impl,iface);
107 /* Dont understand how to handle multiple streams, but if a fixed
108 FVF is passed in rather than a handle, it must use stream 0 */
110 if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
111 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
112 if (NULL == vertex_shader) {
113 ERR_(d3d_shader)("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
114 return ;
116 if (NULL == vertex_shader->function) {
117 TRACE_(d3d_shader)("vertex shader declared without program, using FVF pure mode\n");
118 } else {
119 useVertexShaderFunction = TRUE;
121 fvf = (D3DFORMAT) This->UpdateStateBlock->vertexShaderDecl->fvf;
122 TRACE_(d3d_shader)("vertex shader declared FVF: %08lx\n", This->UpdateStateBlock->vertexShaderDecl->fvf);
123 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
125 /** init Constants */
126 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
127 TRACE_(d3d_shader)("vertex shader init Constant\n");
128 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
134 int skip = This->StateBlock->stream_stride[0];
135 GLenum primType = GL_POINTS;
136 BOOL normal;
137 BOOL isRHW;
138 BOOL isPtSize;
139 BOOL isDiffuse;
140 BOOL isSpecular;
141 int numBlends;
142 BOOL isLastUByte4;
143 int numTextures;
144 int textureNo;
145 const char *curVtx = NULL;
146 const short *pIdxBufS = NULL;
147 const long *pIdxBufL = NULL;
148 const char *curPos;
149 BOOL isLightingOn = FALSE;
150 int vx_index;
151 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
152 float s[8], t[8], r[8], q[8]; /* Holding place for tex coords */
153 const char *coordPtr[8]; /* Holding place for the ptr to tex coords */
154 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
157 float x = 0.0f,
158 y = 0.0f,
159 z = 0.0f; /* x,y,z coordinates */
160 float nx = 0.0f,
161 ny =0.0,
162 nz = 0.0f; /* normal x,y,z coordinates */
163 float rhw = 0.0f; /* rhw */
164 float ptSize = 0.0f; /* Point size */
165 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
166 DWORD specularColor = 0; /* Specular Color */
168 ENTER_GL();
170 if (isIndexed) {
171 if (idxBytes == 2) pIdxBufS = (short *) idxData;
172 else pIdxBufL = (long *) idxData;
175 /* Check vertex formats expected ? */
176 /**
177 * FVF parser as seen it
178 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp
180 normal = fvf & D3DFVF_NORMAL;
181 isRHW = fvf & D3DFVF_XYZRHW;
182 isLastUByte4 = fvf & D3DFVF_LASTBETA_UBYTE4;
183 numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */
184 isPtSize = fvf & D3DFVF_PSIZE;
185 isDiffuse = fvf & D3DFVF_DIFFUSE;
186 isSpecular = fvf & D3DFVF_SPECULAR;
187 numTextures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
188 coordIdxInfo = (fvf & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
190 TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d, coordIdxInfo=%x)\n",
191 fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends, coordIdxInfo);
193 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
194 set by the appropriate render state */
195 if (!normal) {
196 isLightingOn = glIsEnabled(GL_LIGHTING);
197 glDisable(GL_LIGHTING);
198 TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
201 if (isRHW) {
202 double X, Y, height, width, minZ, maxZ;
204 * Already transformed vertex do not need transform
205 * matrices. Reset all matrices to identity.
206 * Leave the default matrix in world mode.
208 glMatrixMode(GL_MODELVIEW);
209 checkGLcall("glMatrixMode");
210 glLoadIdentity();
211 checkGLcall("glLoadIdentity");
213 * As seen in d3d7 code:
214 * See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
215 * Correctness Tips section).
217 glTranslatef(0.375f, 0.375f, 0.0f);
221 glMatrixMode(GL_PROJECTION);
222 checkGLcall("glMatrixMode");
223 glLoadIdentity();
224 checkGLcall("glLoadIdentity");
225 X = This->StateBlock->viewport.X;
226 Y = This->StateBlock->viewport.Y;
227 height = This->StateBlock->viewport.Height;
228 width = This->StateBlock->viewport.Width;
229 minZ = This->StateBlock->viewport.MinZ;
230 maxZ = This->StateBlock->viewport.MaxZ;
231 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
232 /*glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);*/
233 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
234 checkGLcall("glOrtho");
235 } else {
236 double X, Y, height, width;
237 X = This->StateBlock->viewport.X;
238 Y = This->StateBlock->viewport.Y;
239 height = This->StateBlock->viewport.Height;
240 width = This->StateBlock->viewport.Width;
242 glMatrixMode(GL_MODELVIEW);
243 checkGLcall("glMatrixMode");
244 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
245 checkGLcall("glLoadMatrixf");
246 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
247 checkGLcall("glMultMatrixf");
249 #if 0
251 * OpenGL seems to map font between pixels
252 * well with this it seems better but not perfect
253 * anyone have a better idea ?
255 glTranslatef(0.8f / width, -0.8f / height, 0.0f);
259 #endif
261 glMatrixMode(GL_PROJECTION);
262 checkGLcall("glMatrixMode");
263 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
264 checkGLcall("glLoadMatrixf");
267 /* Set OpenGL to the appropriate Primitive Type */
268 switch (PrimitiveType) {
269 case D3DPT_POINTLIST:
270 TRACE("POINTS\n");
271 primType = GL_POINTS;
272 NumVertexes = NumPrimitives;
273 break;
275 case D3DPT_LINELIST:
276 TRACE("LINES\n");
277 primType = GL_LINES;
278 NumVertexes = NumPrimitives * 2;
279 break;
281 case D3DPT_LINESTRIP:
282 TRACE("LINE_STRIP\n");
283 primType = GL_LINE_STRIP;
284 NumVertexes = NumPrimitives + 1;
285 break;
287 case D3DPT_TRIANGLELIST:
288 TRACE("TRIANGLES\n");
289 primType = GL_TRIANGLES;
290 NumVertexes = NumPrimitives * 3;
291 break;
293 case D3DPT_TRIANGLESTRIP:
294 TRACE("TRIANGLE_STRIP\n");
295 primType = GL_TRIANGLE_STRIP;
296 NumVertexes = NumPrimitives + 2;
297 break;
299 case D3DPT_TRIANGLEFAN:
300 TRACE("TRIANGLE_FAN\n");
301 primType = GL_TRIANGLE_FAN;
302 NumVertexes = NumPrimitives + 2;
303 break;
305 default:
306 FIXME("Unhandled primitive\n");
307 break;
310 /* Fixme, Ideally, only use this per-vertex code for software HAL
311 but until opengl supports all the functions returned to setup
312 vertex arrays, we need to drop down to the slow mechanism for
313 certain functions */
315 if (isPtSize || isDiffuse || useVertexShaderFunction == TRUE || (numBlends > 0)) {
316 TRACE("Using slow per-vertex code\n");
318 /* Enable this one to be able to debug what is going on, but it is slower
319 than the pointer/array version */
320 VTRACE(("glBegin(%x)\n", primType));
321 glBegin(primType);
323 /* Draw the primitives */
324 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
326 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
328 if (!isIndexed) {
329 curPos = curVtx;
330 } else {
331 if (idxBytes == 2) {
332 VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
333 curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
334 } else {
335 VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
336 curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
340 /* Work through the vertex buffer */
341 x = *(float *)curPos;
342 curPos = curPos + sizeof(float);
343 y = *(float *)curPos;
344 curPos = curPos + sizeof(float);
345 z = *(float *)curPos;
346 curPos = curPos + sizeof(float);
347 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
349 /* RHW follows, only if transformed */
350 if (isRHW) {
351 rhw = *(float *)curPos;
352 curPos = curPos + sizeof(float);
353 VTRACE(("rhw=%f\n", rhw));
356 /* Blending data */
357 if (numBlends > 0) {
358 UINT i;
359 D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
360 DWORD skippedBlendLastUByte4 = 0;
362 for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
363 ((float*)&skippedBlend)[i] = *(float *)curPos;
364 curPos = curPos + sizeof(float);
367 if (isLastUByte4) {
368 skippedBlendLastUByte4 = *(DWORD*)curPos;
369 curPos = curPos + sizeof(DWORD);
373 /* Vertex Normal Data (untransformed only) */
374 if (normal) {
375 nx = *(float *)curPos;
376 curPos = curPos + sizeof(float);
377 ny = *(float *)curPos;
378 curPos = curPos + sizeof(float);
379 nz = *(float *)curPos;
380 curPos = curPos + sizeof(float);
381 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
384 if (isPtSize) {
385 ptSize = *(float *)curPos;
386 VTRACE(("ptSize=%f\n", ptSize));
387 curPos = curPos + sizeof(float);
390 if (isDiffuse) {
391 diffuseColor = *(DWORD *)curPos;
392 VTRACE(("diffuseColor=%lx\n", diffuseColor));
393 curPos = curPos + sizeof(DWORD);
396 if (isSpecular) {
397 specularColor = *(DWORD *)curPos;
398 VTRACE(("specularColor=%lx\n", specularColor));
399 curPos = curPos + sizeof(DWORD);
402 /* Texture coords */
403 /* numTextures indicates the number of texture coordinates supplied */
404 /* However, the first set may not be for stage 0 texture - it all */
405 /* depends on D3DTSS_TEXCOORDINDEX. */
406 /* The number of bytes for each coordinate set is based off */
407 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
409 /* Initialize unused coords to unsupplied so we can check later */
410 for (textureNo = numTextures; textureNo < 7; textureNo++) numCoords[textureNo] = -1;
412 /* So, for each supplied texture extract the coords */
413 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
415 numCoords[textureNo] = coordIdxInfo & 0x03;
417 /* Always one set */
418 s[textureNo] = *(float *)curPos;
419 curPos = curPos + sizeof(float);
420 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
421 t[textureNo] = *(float *)curPos;
422 curPos = curPos + sizeof(float);
423 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
424 r[textureNo] = *(float *)curPos;
425 curPos = curPos + sizeof(float);
426 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
427 q[textureNo] = *(float *)curPos;
428 curPos = curPos + sizeof(float);
433 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
436 /* Now use the appropriate set of texture indexes */
437 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
439 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
440 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
441 continue ;
444 /* Query tex coords */
445 if ((This->StateBlock->textures[textureNo] != NULL) &&
446 (useVertexShaderFunction == FALSE)) {
448 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
450 if (coordIdx > 7) {
451 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
452 } else if (coordIdx >= numTextures) {
453 VTRACE(("tex: %d - Skip tex coords, as requested higher than supplied\n", textureNo));
454 } else {
456 int coordsToUse = numCoords[coordIdx];
458 /* If texture transform flags in effect, values passed through to vertex
459 depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
460 if (coordsToUse > 0 &&
461 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
463 /* This indicates how many coords to use regardless of the
464 texture type. However, d3d/opengl fill in the rest appropriately */
465 coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
467 /* BUT - Projected is more 'fun' - Move the last coord to the 'q'
468 parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
469 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
470 switch (coordsToUse) {
471 case 0: /* Drop Through */
472 case 1:
473 FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
474 break;
475 case 2:
476 q[textureNo] = t[textureNo];
477 t[textureNo] = 0.0;
478 coordsToUse = 4;
479 break;
480 case 3:
481 q[textureNo] = r[textureNo];
482 r[textureNo] = 0.0;
483 coordsToUse = 4;
484 break;
485 case 4: /* Nop here */
486 break;
487 default:
488 FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n",
489 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
494 switch (coordsToUse) { /* Supply the provided texture coords */
495 case D3DFVF_TEXTUREFORMAT1:
496 VTRACE(("tex:%d, s=%f\n", textureNo, s[coordIdx]));
497 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
498 #if defined(GL_VERSION_1_3)
499 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s[coordIdx]);
500 #else
501 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx]);
502 #endif
503 } else {
504 glTexCoord1f(s[coordIdx]);
506 break;
507 case D3DFVF_TEXTUREFORMAT2:
508 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s[coordIdx], t[coordIdx]));
509 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
510 #if defined(GL_VERSION_1_3)
511 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx]);
512 #else
513 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx]);
514 #endif
515 } else {
516 glTexCoord2f(s[coordIdx], t[coordIdx]);
518 break;
519 case D3DFVF_TEXTUREFORMAT3:
520 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx]));
521 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
522 #if defined(GL_VERSION_1_3)
523 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
524 #else
525 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
526 #endif
527 } else {
528 glTexCoord3f(s[coordIdx], t[coordIdx], r[coordIdx]);
530 break;
531 case D3DFVF_TEXTUREFORMAT4:
532 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]));
533 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
534 #if defined(GL_VERSION_1_3)
535 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
536 #else
537 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
538 #endif
539 } else {
540 glTexCoord4f(s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
542 break;
543 default:
544 FIXME("Should not get here as numCoords is two bits only (%x)!\n", numCoords[coordIdx]);
551 /** if vertex shader program specified ... using it */
552 if (TRUE == useVertexShaderFunction) {
555 * this code must become the really
556 * vs input params init
558 * because its possible to use input registers for anything
559 * and some samples use registers for other things than they are
560 * declared
563 /**
564 * no really valid declaration, user defined input register use
565 * so fill input registers as described in vertex shader declaration
567 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
568 (!isIndexed) ? (vx_index * skip) :
569 (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) :
570 ((pIdxBufL[StartIdx + vx_index]) * skip));
572 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
573 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
575 TRACE_VECTOR(vertex_shader->output.oPos);
576 TRACE_VECTOR(vertex_shader->output.oD[0]);
577 TRACE_VECTOR(vertex_shader->output.oD[1]);
578 TRACE_VECTOR(vertex_shader->output.oT[0]);
579 TRACE_VECTOR(vertex_shader->output.oT[1]);
580 TRACE_VECTOR(vertex_shader->input.V[0]);
581 TRACE_VECTOR(vertex_shader->data->C[0]);
582 TRACE_VECTOR(vertex_shader->data->C[1]);
583 TRACE_VECTOR(vertex_shader->data->C[2]);
584 TRACE_VECTOR(vertex_shader->data->C[3]);
585 TRACE_VECTOR(vertex_shader->data->C[4]);
586 TRACE_VECTOR(vertex_shader->data->C[5]);
587 TRACE_VECTOR(vertex_shader->data->C[6]);
588 TRACE_VECTOR(vertex_shader->data->C[7]);
590 x = vertex_shader->output.oPos.x;
591 y = vertex_shader->output.oPos.y;
592 z = vertex_shader->output.oPos.z;
594 if (1.0f != vertex_shader->output.oPos.w || isRHW) {
595 rhw = vertex_shader->output.oPos.w;
597 /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
598 glColor4fv((float*) &vertex_shader->output.oD[0]);
600 /* Requires secondary color extensions to compile... */
601 #if defined(GL_EXT_secondary_color)
602 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
603 /*specularColor = D3DCOLORTOCOLORVALUE(vertex_shader->output.oD[1]);*/
604 GL_EXTCALL(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_EXT_secondary_color)
819 /* FIXME: check for GL_EXT_secondary_color */
820 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
821 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, skip, curPos);
822 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
823 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
824 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
826 #endif
827 curPos += sizeof(DWORD);
828 } else {
829 #if defined(GL_EXT_secondary_color)
830 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
831 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
832 vcheckGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
833 #if 0
834 GL_EXTCALL(glSecondaryColor3fEXT)(0.0f, 0.0f, 0.0f);
835 vcheckGLcall("glSecondaryColor3fEXT(0, 0, 0)");
836 #endif
838 #endif
841 /* Texture coords */
842 /* numTextures indicates the number of texture coordinates supplied */
843 /* However, the first set may not be for stage 0 texture - it all */
844 /* depends on D3DTSS_TEXCOORDINDEX. */
845 /* The number of bytes for each coordinate set is based off */
846 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
848 /* Initialize unused coords to unsupplied so we can check later */
849 for (textureNo = numTextures; textureNo < 7; textureNo++) coordPtr[textureNo] = NULL;
851 /* So, for each supplied texture extract the coords */
852 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
854 numCoords[textureNo] = coordIdxInfo & 0x03;
855 coordPtr[textureNo] = curPos;
857 /* Always one set */
858 curPos = curPos + sizeof(float);
859 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
860 curPos = curPos + sizeof(float);
861 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
862 curPos = curPos + sizeof(float);
863 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
864 curPos = curPos + sizeof(float);
868 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
871 /* Now use the appropriate set of texture indexes */
872 for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
874 if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
875 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
876 continue ;
879 /* Query tex coords */
880 if ((This->StateBlock->textures[textureNo] != NULL) && (useVertexShaderFunction == FALSE)) {
881 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
883 if (coordIdx > 7) {
884 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
885 } else {
886 int numFloats = 0;
887 int coordsToUse = numCoords[coordIdx];
888 #if defined(GL_VERSION_1_3)
889 glClientActiveTexture(GL_TEXTURE0 + textureNo);
890 #else
891 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
892 #endif
894 /* If texture transform flags in effect, values passed through to vertex
895 depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
896 if (coordsToUse > 0 &&
897 This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
899 /* This indicates how many coords to use regardless of the
900 texture type. However, d3d/opengl fill in the rest appropriately */
901 coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
903 /* BUT - Projected is more 'fun' - Cant be done for ptr mode.
904 Probably should scan enabled texture units and drop back to
905 slow mode if found? */
906 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
907 FIXME("Cannot handle projected transform state in fast mode\n");
911 switch (coordsToUse) { /* Supply the provided texture coords */
912 case D3DFVF_TEXTUREFORMAT1: numFloats = 1; break;
913 case D3DFVF_TEXTUREFORMAT2: numFloats = 2; break;
914 case D3DFVF_TEXTUREFORMAT3: numFloats = 3; break;
915 case D3DFVF_TEXTUREFORMAT4: numFloats = 4; break;
916 default: numFloats = 0; break;
919 if (numFloats == 0 || coordIdx >= numTextures) {
920 VTRACE(("Skipping as invalid request - numfloats=%d, coordIdx=%d, numTextures=%d\n", numFloats, coordIdx, numTextures));
921 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
922 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
923 } else {
924 VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, coordPtr[coordIdx], numFloats));
925 glTexCoordPointer(numFloats, GL_FLOAT, skip, coordPtr[coordIdx]);
926 checkGLcall("glTexCoordPointer(x, ...)");
927 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
928 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
934 /* Finally do the drawing */
935 if (isIndexed) {
937 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
938 if (idxBytes==2) {
939 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
940 glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
941 (char *)idxData+(2 * StartIdx));
942 #else
943 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
944 GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
945 #endif
946 } else {
947 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
948 glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
949 (char *)idxData+(4 * StartIdx));
950 #else
951 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
952 GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
953 #endif
955 checkGLcall("glDrawRangeElements");
957 } else {
959 /* Note first is now zero as we shuffled along earlier */
960 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
961 glDrawArrays(primType, 0, NumVertexes);
962 checkGLcall("glDrawArrays");
967 /* If no normals, restore previous lighting state */
968 if (!normal) {
969 if (isLightingOn) glEnable(GL_LIGHTING);
970 else glDisable(GL_LIGHTING);
971 TRACE("Restored lighting to original state\n");
975 LEAVE_GL();
977 TRACE("glEnd\n");
980 /* Apply the current values to the specified texture stage */
981 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
982 ICOM_THIS(IDirect3DDevice8Impl,iface);
983 int i = 0;
984 float col[4];
986 /* Make appropriate texture active */
987 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
988 #if defined(GL_VERSION_1_3)
989 glActiveTexture(GL_TEXTURE0 + Stage);
990 #else
991 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
992 #endif
993 checkGLcall("glActiveTextureARB");
994 } else if (Stage > 0) {
995 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
998 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
999 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
1000 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1003 /* Note the D3DRS value applies to all textures, but GL has one
1004 * per texture, so apply it now ready to be used!
1006 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
1007 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1008 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1010 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1013 /* IDirect3D IUnknown parts follow: */
1014 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1016 ICOM_THIS(IDirect3DDevice8Impl,iface);
1018 if (IsEqualGUID(riid, &IID_IUnknown)
1019 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1020 IDirect3DDevice8Impl_AddRef(iface);
1021 *ppobj = This;
1022 return D3D_OK;
1025 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1026 return E_NOINTERFACE;
1029 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1030 ICOM_THIS(IDirect3DDevice8Impl,iface);
1031 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1032 return ++(This->ref);
1035 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1036 ICOM_THIS(IDirect3DDevice8Impl,iface);
1037 ULONG ref = --This->ref;
1038 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1039 if (ref == 0) {
1040 IDirect3DDevice8Impl_CleanRender(iface);
1041 HeapFree(GetProcessHeap(), 0, This);
1043 return ref;
1046 /* IDirect3DDevice Interface follow: */
1047 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1048 ICOM_THIS(IDirect3DDevice8Impl,iface);
1049 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
1050 return D3D_OK;
1053 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1054 ICOM_THIS(IDirect3DDevice8Impl,iface);
1055 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1057 * pretend we have 32MB of any type of memory queried.
1059 return (1024*1024*32);
1062 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1063 ICOM_THIS(IDirect3DDevice8Impl,iface);
1064 FIXME("(%p) : stub\n", This); return D3D_OK;
1066 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1067 ICOM_THIS(IDirect3DDevice8Impl,iface);
1068 TRACE("(%p) : returning %p\n", This, This->direct3d8);
1070 /* Inc ref count */
1071 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1073 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1074 return D3D_OK;
1076 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1077 ICOM_THIS(IDirect3DDevice8Impl,iface);
1078 FIXME("(%p) : stub, calling idirect3d for now\n", This);
1079 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1080 return D3D_OK;
1082 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1084 HDC hdc;
1085 int bpp = 0;
1087 ICOM_THIS(IDirect3DDevice8Impl,iface);
1088 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
1089 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
1090 pMode->RefreshRate = 85; /*FIXME: How to identify? */
1092 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1093 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1094 DeleteDC(hdc);
1096 switch (bpp) {
1097 case 8: pMode->Format = D3DFMT_R8G8B8; break;
1098 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1099 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
1100 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1101 default:
1102 FIXME("Unrecognized display mode format\n");
1103 pMode->Format = D3DFMT_UNKNOWN;
1106 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
1107 pMode->Format, debug_d3dformat(pMode->Format));
1108 return D3D_OK;
1110 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1111 ICOM_THIS(IDirect3DDevice8Impl,iface);
1112 TRACE("(%p) copying to %p\n", This, pParameters);
1113 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1114 return D3D_OK;
1116 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1117 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
1118 ICOM_THIS(IDirect3DDevice8Impl,iface);
1119 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
1121 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
1122 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
1123 return D3DERR_INVALIDCALL;
1125 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
1126 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
1127 return D3DERR_INVALIDCALL;
1130 This->xHotSpot = XHotSpot;
1131 This->yHotSpot = YHotSpot;
1132 return D3D_OK;
1134 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
1135 ICOM_THIS(IDirect3DDevice8Impl,iface);
1136 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
1137 This->xScreenSpace = XScreenSpace;
1138 This->yScreenSpace = YScreenSpace;
1139 return;
1141 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1142 ICOM_THIS(IDirect3DDevice8Impl,iface);
1143 TRACE("(%p) : visible(%d)\n", This, bShow);
1144 This->bCursorVisible = bShow;
1145 return D3D_OK;
1147 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1148 IDirect3DSwapChain8Impl* object;
1149 ICOM_THIS(IDirect3DDevice8Impl,iface);
1150 FIXME("(%p) : stub\n", This);
1152 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
1153 if (NULL == object) {
1154 return D3DERR_OUTOFVIDEOMEMORY;
1156 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
1157 object->ref = 1;
1159 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
1160 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
1161 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
1163 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
1164 (pPresentationParameters->BackBufferHeight == 0))) {
1165 RECT Rect;
1167 GetClientRect(This->win_handle, &Rect);
1169 if (pPresentationParameters->BackBufferWidth == 0) {
1170 pPresentationParameters->BackBufferWidth = Rect.right;
1171 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1173 if (pPresentationParameters->BackBufferHeight == 0) {
1174 pPresentationParameters->BackBufferHeight = Rect.bottom;
1175 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1179 /* Save the presentation parms now filled in correctly */
1180 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
1182 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1183 pPresentationParameters->BackBufferWidth,
1184 pPresentationParameters->BackBufferHeight,
1185 pPresentationParameters->BackBufferFormat,
1186 pPresentationParameters->MultiSampleType,
1187 TRUE,
1188 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
1190 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1191 pPresentationParameters->BackBufferWidth,
1192 pPresentationParameters->BackBufferHeight,
1193 pPresentationParameters->BackBufferFormat,
1194 pPresentationParameters->MultiSampleType,
1195 TRUE,
1196 (LPDIRECT3DSURFACE8*) &object->backBuffer);
1198 if (pPresentationParameters->EnableAutoDepthStencil) {
1199 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
1200 pPresentationParameters->BackBufferWidth,
1201 pPresentationParameters->BackBufferHeight,
1202 pPresentationParameters->AutoDepthStencilFormat,
1203 D3DMULTISAMPLE_NONE,
1204 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
1205 } else {
1206 object->depthStencilBuffer = NULL;
1209 *pSwapChain = (IDirect3DSwapChain8*) object;
1210 return D3D_OK;
1212 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1213 ICOM_THIS(IDirect3DDevice8Impl,iface);
1214 FIXME("(%p) : stub\n", This); return D3D_OK;
1216 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1217 ICOM_THIS(IDirect3DDevice8Impl,iface);
1218 TRACE("(%p) : complete stub!\n", This);
1220 ENTER_GL();
1222 glXSwapBuffers(This->display, This->drawable);
1223 /* Dont call checkGLcall, as glGetError is not applicable here */
1224 TRACE("glXSwapBuffers called, Starting new frame");
1226 LEAVE_GL();
1228 return D3D_OK;
1230 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
1231 ICOM_THIS(IDirect3DDevice8Impl,iface);
1232 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1233 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1235 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
1236 FIXME("Only one backBuffer currently supported\n");
1237 return D3DERR_INVALIDCALL;
1240 /* Note inc ref on returned surface */
1241 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1243 return D3D_OK;
1245 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1246 ICOM_THIS(IDirect3DDevice8Impl,iface);
1247 FIXME("(%p) : stub\n", This);
1248 return D3D_OK;
1250 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
1251 HDC hDC;
1252 ICOM_THIS(IDirect3DDevice8Impl,iface);
1254 FIXME("(%p) : pRamp@%p\n", This, pRamp);
1255 hDC = GetDC(This->win_handle);
1256 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
1257 ReleaseDC(This->win_handle, hDC);
1258 return;
1260 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1261 HDC hDC;
1262 ICOM_THIS(IDirect3DDevice8Impl,iface);
1264 FIXME("(%p) : pRamp@%p\n", This, pRamp);
1265 hDC = GetDC(This->win_handle);
1266 GetDeviceGammaRamp(hDC, pRamp);
1267 ReleaseDC(This->win_handle, hDC);
1268 return;
1270 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1271 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
1272 IDirect3DTexture8Impl *object;
1273 int i;
1274 UINT tmpW;
1275 UINT tmpH;
1277 ICOM_THIS(IDirect3DDevice8Impl,iface);
1279 /* Allocate the storage for the device */
1280 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);
1281 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1282 object->lpVtbl = &Direct3DTexture8_Vtbl;
1283 object->Device = This;
1284 object->ResourceType = D3DRTYPE_TEXTURE;
1285 object->ref = 1;
1286 object->width = Width;
1287 object->height = Height;
1288 object->levels = Levels;
1289 object->usage = Usage;
1290 object->format = Format;
1292 /* Calculate levels for mip mapping */
1293 if (Levels == 0) {
1294 object->levels++;
1295 tmpW = Width;
1296 tmpH = Height;
1297 while (tmpW > 1 && tmpH > 1) {
1298 tmpW = max(1, tmpW / 2);
1299 tmpH = max(1, tmpH / 2);
1300 object->levels++;
1302 TRACE("Calculated levels = %d\n", object->levels);
1305 /* Generate all the surfaces */
1306 tmpW = Width;
1307 tmpH = Height;
1308 for (i = 0; i < object->levels; i++)
1310 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1311 object->surfaces[i]->Container = (IUnknown*) object;
1312 object->surfaces[i]->myDesc.Usage = Usage;
1313 object->surfaces[i]->myDesc.Pool = Pool;
1314 /**
1315 * As writen in msdn in IDirect3DTexture8::LockRect
1316 * Textures created in D3DPOOL_DEFAULT are not lockable.
1318 if (D3DPOOL_DEFAULT == Pool) {
1319 object->surfaces[i]->lockable = FALSE;
1322 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1323 tmpW = max(1, tmpW / 2);
1324 tmpH = max(1, tmpH / 2);
1327 *ppTexture = (LPDIRECT3DTEXTURE8) object;
1328 return D3D_OK;
1330 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
1331 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
1332 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
1334 IDirect3DVolumeTexture8Impl *object;
1335 int i;
1336 UINT tmpW;
1337 UINT tmpH;
1338 UINT tmpD;
1340 ICOM_THIS(IDirect3DDevice8Impl,iface);
1342 /* Allocate the storage for it */
1343 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);
1344 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1345 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1346 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1347 object->Device = This;
1348 object->ref = 1;
1350 object->width = Width;
1351 object->height = Height;
1352 object->depth = Depth;
1353 object->levels = Levels;
1354 object->usage = Usage;
1355 object->format = Format;
1357 /* Calculate levels for mip mapping */
1358 if (Levels == 0) {
1359 object->levels++;
1360 tmpW = Width;
1361 tmpH = Height;
1362 tmpD = Depth;
1363 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1364 tmpW = max(1, tmpW / 2);
1365 tmpH = max(1, tmpH / 2);
1366 tmpD = max(1, tmpD / 2);
1367 object->levels++;
1369 TRACE("Calculated levels = %d\n", object->levels);
1372 /* Generate all the surfaces */
1373 tmpW = Width;
1374 tmpH = Height;
1375 tmpD = Depth;
1377 for (i = 0; i < object->levels; i++)
1379 IDirect3DVolume8Impl* volume;
1381 /* Create the volume - No entry point for this seperately?? */
1382 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1383 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1385 volume->lpVtbl = &Direct3DVolume8_Vtbl;
1386 volume->Device = This;
1387 volume->ResourceType = D3DRTYPE_VOLUME;
1388 volume->Container = (IUnknown*) object;
1389 volume->ref = 1;
1391 volume->myDesc.Width = Width;
1392 volume->myDesc.Height = Height;
1393 volume->myDesc.Depth = Depth;
1394 volume->myDesc.Format = Format;
1395 volume->myDesc.Type = D3DRTYPE_VOLUME;
1396 volume->myDesc.Pool = Pool;
1397 volume->myDesc.Usage = Usage;
1398 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
1399 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
1400 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1402 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
1403 This, Width, Height, Depth, Format, debug_d3dformat(Format),
1404 volume, volume->allocatedMemory, volume->myDesc.Size);
1406 tmpW = max(1, tmpW / 2);
1407 tmpH = max(1, tmpH / 2);
1408 tmpD = max(1, tmpD / 2);
1411 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
1412 return D3D_OK;
1414 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
1415 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
1417 IDirect3DCubeTexture8Impl *object;
1418 ICOM_THIS(IDirect3DDevice8Impl,iface);
1419 int i,j;
1420 UINT tmpW;
1422 /* Allocate the storage for it */
1423 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), Pool);
1424 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1425 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1426 object->ref = 1;
1427 object->Device = This;
1428 object->ResourceType = D3DRTYPE_CUBETEXTURE;
1430 object->edgeLength = EdgeLength;
1431 object->levels = Levels;
1432 object->usage = Usage;
1433 object->format = Format;
1435 /* Calculate levels for mip mapping */
1436 if (Levels == 0) {
1437 object->levels++;
1438 tmpW = EdgeLength;
1439 while (tmpW > 1) {
1440 tmpW = max(1, tmpW / 2);
1441 object->levels++;
1443 TRACE("Calculated levels = %d\n", object->levels);
1446 /* Generate all the surfaces */
1447 tmpW = EdgeLength;
1448 for (i = 0; i < object->levels; i++) {
1449 /* Create the 6 faces */
1450 for (j = 0; j < 6; j++) {
1451 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1452 object->surfaces[j][i]->Container = (IUnknown*) object;
1453 object->surfaces[j][i]->myDesc.Usage = Usage;
1454 object->surfaces[j][i]->myDesc.Pool = Pool;
1455 /**
1456 * As writen in msdn in IDirect3DCubeTexture8::LockRect
1457 * Textures created in D3DPOOL_DEFAULT are not lockable.
1459 if (D3DPOOL_DEFAULT == Pool) {
1460 object->surfaces[j][i]->lockable = FALSE;
1463 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1465 tmpW = max(1, tmpW / 2);
1468 TRACE("(%p) : Iface@%p\n", This, object);
1469 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1470 return D3D_OK;
1472 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1473 IDirect3DVertexBuffer8Impl *object;
1475 ICOM_THIS(IDirect3DDevice8Impl,iface);
1477 /* Allocate the storage for the device */
1478 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1479 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1480 object->Device = This;
1481 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1482 object->ref = 1;
1483 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1484 object->currentDesc.Usage = Usage;
1485 object->currentDesc.Pool = Pool;
1486 object->currentDesc.FVF = FVF;
1487 object->currentDesc.Size = Size;
1489 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1491 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1493 return D3D_OK;
1495 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
1496 IDirect3DIndexBuffer8Impl *object;
1498 ICOM_THIS(IDirect3DDevice8Impl,iface);
1499 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
1501 /* Allocate the storage for the device */
1502 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1503 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1504 object->Device = This;
1505 object->ref = 1;
1506 object->ResourceType = D3DRTYPE_INDEXBUFFER;
1508 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1509 object->currentDesc.Usage = Usage;
1510 object->currentDesc.Pool = Pool;
1511 object->currentDesc.Format = Format;
1512 object->currentDesc.Size = Length;
1514 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1516 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1518 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1520 return D3D_OK;
1522 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
1523 IDirect3DSurface8Impl *object;
1524 ICOM_THIS(IDirect3DDevice8Impl,iface);
1526 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1527 if (NULL == object) {
1528 *ppSurface = NULL;
1529 return D3DERR_OUTOFVIDEOMEMORY;
1531 *ppSurface = (LPDIRECT3DSURFACE8) object;
1532 object->lpVtbl = &Direct3DSurface8_Vtbl;
1533 object->Device = This;
1534 object->ResourceType = D3DRTYPE_SURFACE;
1535 object->Container = (IUnknown*) This;
1537 object->ref = 1;
1538 object->myDesc.Width = Width;
1539 object->myDesc.Height = Height;
1540 object->myDesc.Format = Format;
1541 object->myDesc.Type = D3DRTYPE_SURFACE;
1542 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
1543 object->myDesc.Pool = D3DPOOL_DEFAULT;
1544 object->myDesc.MultiSampleType = MultiSample;
1545 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1546 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1547 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1548 object->lockable = Lockable;
1549 object->locked = FALSE;
1551 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);
1552 return D3D_OK;
1554 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
1555 IDirect3DSurface8Impl *object;
1557 ICOM_THIS(IDirect3DDevice8Impl,iface);
1559 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1560 if (NULL == object) {
1561 *ppSurface = NULL;
1562 return D3DERR_OUTOFVIDEOMEMORY;
1564 *ppSurface = (LPDIRECT3DSURFACE8) object;
1565 object->lpVtbl = &Direct3DSurface8_Vtbl;
1566 object->Device = This;
1567 object->ResourceType = D3DRTYPE_SURFACE;
1568 object->Container = (IUnknown*) This;
1570 object->ref = 1;
1571 object->myDesc.Width = Width;
1572 object->myDesc.Height = Height;
1573 object->myDesc.Format = Format;
1574 object->myDesc.Type = D3DRTYPE_SURFACE;
1575 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
1576 object->myDesc.Pool = D3DPOOL_DEFAULT;
1577 object->myDesc.MultiSampleType = MultiSample;
1578 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1579 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1580 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1581 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
1582 object->locked = FALSE;
1584 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);
1585 return D3D_OK;
1587 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
1588 IDirect3DSurface8Impl *object;
1590 ICOM_THIS(IDirect3DDevice8Impl,iface);
1592 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1593 *ppSurface = (LPDIRECT3DSURFACE8) object;
1594 object->lpVtbl = &Direct3DSurface8_Vtbl;
1595 object->Device = This;
1596 object->ResourceType = D3DRTYPE_SURFACE;
1597 object->Container = (IUnknown*) This;
1599 object->ref = 1;
1600 object->myDesc.Width = Width;
1601 object->myDesc.Height = Height;
1602 object->myDesc.Format = Format;
1603 object->myDesc.Type = D3DRTYPE_SURFACE;
1604 object->myDesc.Usage = 0;
1605 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
1606 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
1607 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1608 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1609 object->lockable = TRUE;
1610 object->locked = FALSE;
1612 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);
1613 return D3D_OK;
1615 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
1616 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
1617 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
1619 HRESULT rc = D3D_OK;
1620 IDirect3DBaseTexture8* texture = NULL;
1623 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
1624 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1626 ICOM_THIS(IDirect3DDevice8Impl,iface);
1627 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1628 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1630 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1631 a sample and doesnt seem to break anything as far as I can tell */
1632 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1633 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1634 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1635 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1636 rc = D3DERR_INVALIDCALL;
1638 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1639 TRACE("Converting dest to same format as source, since dest was unknown\n");
1640 dst->myDesc.Format = src->myDesc.Format;
1642 /* Convert container as well */
1643 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1644 if (texture != NULL) {
1645 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1646 /** Releasing texture after GetContainer */
1647 IDirect3DBaseTexture8_Release(texture);
1648 texture = NULL;
1652 /* Quick if complete copy ... */
1653 if (rc == D3D_OK && cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1655 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1657 D3DLOCKED_RECT lrSrc;
1658 D3DLOCKED_RECT lrDst;
1659 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1660 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1661 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1663 /*memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);*/
1664 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1666 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1667 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1668 TRACE("Unlocked src and dst\n");
1670 } else {
1672 FIXME("Wanted to copy all surfaces but size not compatible\n");
1673 rc = D3DERR_INVALIDCALL;
1677 } else {
1679 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1681 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1682 int i;
1683 /* Copy rect by rect */
1684 for (i = 0; i < cRects; i++) {
1685 CONST RECT* r = &pSourceRectsArray[i];
1686 CONST POINT* p = &pDestPointsArray[i];
1687 int copyperline = (r->right - r->left) * bytesPerPixel;
1688 int j;
1689 D3DLOCKED_RECT lrSrc;
1690 D3DLOCKED_RECT lrDst;
1691 RECT dest_rect;
1694 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1696 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1697 dest_rect.left = p->x;
1698 dest_rect.top = p->y;
1699 dest_rect.right = p->x + (r->right - r->left);
1700 dest_rect.left = p->y + (r->bottom - r->top);
1701 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1702 TRACE("Locked src and dst\n");
1704 /* Find where to start */
1705 #if 0
1706 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1707 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
1708 /* Copy line by line */
1709 for (j = 0; j < (r->bottom - r->top); j++) {
1710 memcpy(to + (j * pitchTo), from + (j * pitchFrom), copyperline);
1712 #endif
1714 for (j = 0; j < (r->bottom - r->top); j++) {
1715 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1718 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1719 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1720 TRACE("Unlocked src and dst\n");
1723 } else {
1725 FIXME("Wanted to copy partial surfaces not implemented\n");
1726 rc = D3DERR_INVALIDCALL;
1731 return rc;
1733 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1734 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1735 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1736 D3DRESOURCETYPE srcType;
1737 D3DRESOURCETYPE dstType;
1739 ICOM_THIS(IDirect3DDevice8Impl,iface);
1740 TRACE("(%p) : first try\n", This);
1742 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1743 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1745 if (srcType != dstType) {
1746 return D3DERR_INVALIDCALL;
1748 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1749 return D3DERR_INVALIDCALL;
1751 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1752 return D3DERR_INVALIDCALL;
1754 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1755 /** Only copy Dirty textures */
1756 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1757 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1758 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1759 UINT i, j;
1761 for (i = skipLevels; i < srcLevelCnt; ++i) {
1762 HRESULT hr;
1764 switch (srcType) {
1765 case D3DRTYPE_TEXTURE:
1767 IDirect3DSurface8* srcSur = NULL;
1768 IDirect3DSurface8* dstSur = NULL;
1769 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1770 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1771 /*IDirect3DDevice8_CopyRects*/
1772 IDirect3DSurface8Impl_Release(srcSur);
1773 IDirect3DSurface8Impl_Release(dstSur);
1775 break;
1776 case D3DRTYPE_VOLUMETEXTURE:
1778 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1780 break;
1781 case D3DRTYPE_CUBETEXTURE:
1783 IDirect3DSurface8* srcSur = NULL;
1784 IDirect3DSurface8* dstSur = NULL;
1785 for (j = 0; j < 5; ++j) {
1786 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1787 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1788 /*IDirect3DDevice8_CopyRects*/
1789 IDirect3DSurface8Impl_Release(srcSur);
1790 IDirect3DSurface8Impl_Release(dstSur);
1793 break;
1794 default:
1795 break;
1798 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1801 return D3D_OK;
1803 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1804 HRESULT hr;
1805 D3DLOCKED_RECT lockedRect;
1806 RECT wantedRect;
1807 GLint prev_store;
1808 GLenum prev_read;
1810 ICOM_THIS(IDirect3DDevice8Impl,iface);
1812 FIXME("(%p) : see if behavior correct\n", This);
1814 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1815 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1816 return D3DERR_INVALIDCALL;
1819 wantedRect.left = 0;
1820 wantedRect.top = 0;
1821 wantedRect.right = This->PresentParms.BackBufferWidth;
1822 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1824 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1825 if (FAILED(hr)) {
1826 ERR("(%p) : cannot lock surface\n", This);
1827 return D3DERR_INVALIDCALL;
1830 ENTER_GL();
1834 IDirect3DSurface8Impl* tmp = ((IDirect3DSurface8Impl*) pDestSurface);
1835 FIXME("dest:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
1836 FIXME("dest2:pitch%u\n", lockedRect.Pitch);
1837 FIXME("src:%u,%u\n", This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight);
1838 tmp = This->frontBuffer;
1839 FIXME("src2:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
1843 glFlush();
1844 vcheckGLcall("glFlush");
1845 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1846 vcheckGLcall("glIntegerv");
1847 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1848 vcheckGLcall("glIntegerv");
1850 glReadBuffer(GL_FRONT);
1851 vcheckGLcall("glReadBuffer");
1852 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1853 vcheckGLcall("glPixelStorei");
1854 /* stupid copy */
1856 long j;
1857 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1858 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1859 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1860 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1861 vcheckGLcall("glReadPixels");
1864 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1865 vcheckGLcall("glPixelStorei");
1866 glReadBuffer(prev_read);
1867 vcheckGLcall("glReadBuffer");
1869 LEAVE_GL();
1871 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1872 return hr;
1874 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1875 HRESULT hr;
1877 ICOM_THIS(IDirect3DDevice8Impl,iface);
1879 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1880 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1881 return D3D_OK;
1884 IDirect3DDevice8Impl_CleanRender(iface);
1886 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1887 IDirect3DSurface8Impl* tmp;
1889 TRACE("retoring SetRenderTarget defaults\n");
1891 tmp = This->renderTarget;
1892 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1893 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1894 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1896 tmp = This->stencilBufferTarget;
1897 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1898 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1899 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1901 return D3D_OK;
1904 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1906 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1908 return hr;
1911 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1912 ICOM_THIS(IDirect3DDevice8Impl,iface);
1914 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1916 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1917 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1919 return D3D_OK;
1922 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1923 ICOM_THIS(IDirect3DDevice8Impl,iface);
1925 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1927 /* Note inc ref on returned surface */
1928 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1929 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1931 return D3D_OK;
1934 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1935 ICOM_THIS(IDirect3DDevice8Impl,iface);
1936 TRACE("(%p) : stub\n", This);
1937 return D3D_OK;
1939 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1940 ICOM_THIS(IDirect3DDevice8Impl,iface);
1941 TRACE("(%p)\n", This);
1943 ENTER_GL();
1945 glFlush();
1946 checkGLcall("glFlush");
1948 /* Useful for debugging sometimes!
1949 printf("Hit Enter ...\n");
1950 getchar(); */
1952 if (This->frontBuffer != This->renderTarget) {
1954 GLenum prev_read;
1955 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1956 vcheckGLcall("glIntegerv");
1957 glReadBuffer(GL_BACK);
1958 vcheckGLcall("glReadBuffer");
1960 long j;
1961 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1962 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1963 glReadPixels(0,
1964 This->renderTarget->myDesc.Height - j - 1,
1965 This->renderTarget->myDesc.Width,
1967 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1968 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1969 This->renderTarget->allocatedMemory + j * pitch);
1970 vcheckGLcall("glReadPixels");
1973 glReadBuffer(prev_read);
1974 vcheckGLcall("glReadBuffer");
1977 IDirect3DBaseTexture8* cont = NULL;
1978 HRESULT hr;
1979 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1980 if (SUCCEEDED(hr) && NULL != cont) {
1981 /** always dirtify for now. we must find a better way to see that surface have been modified */
1982 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1983 IDirect3DBaseTexture8_PreLoad(cont);
1984 IDirect3DBaseTexture8Impl_Release(cont);
1985 cont = NULL;
1989 LEAVE_GL();
1990 return D3D_OK;
1992 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1993 ICOM_THIS(IDirect3DDevice8Impl,iface);
1995 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1996 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1997 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1998 GLbitfield glMask = 0;
1999 GLboolean old_ztest;
2000 GLfloat old_z_clear_value;
2001 GLint old_stencil_clear_value;
2002 GLfloat old_color_clear_value[4];
2003 int i;
2004 CONST D3DRECT* curRect;
2006 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
2007 Count, pRects, Flags, Z, Stencil);
2009 ENTER_GL();
2010 if (Count > 0 && pRects) {
2011 glEnable(GL_SCISSOR_TEST);
2012 checkGLcall("glEnable GL_SCISSOR_TEST");
2013 curRect = pRects;
2014 } else {
2015 curRect = NULL;
2018 /* Only set the values up once, as they are not changing */
2019 if (Flags & D3DCLEAR_STENCIL) {
2020 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2021 glClearStencil(Stencil);
2022 checkGLcall("glClearStencil");
2023 glMask = glMask | GL_STENCIL_BUFFER_BIT;
2026 if (Flags & D3DCLEAR_ZBUFFER) {
2027 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
2028 glDepthMask(GL_TRUE);
2029 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2030 glClearDepth(Z);
2031 checkGLcall("glClearDepth");
2032 glMask = glMask | GL_DEPTH_BUFFER_BIT;
2035 if (Flags & D3DCLEAR_TARGET) {
2036 TRACE("Clearing screen with glClear to color %lx\n", Color);
2037 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2038 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
2039 ((Color >> 8) & 0xFF) / 255.0f,
2040 ((Color >> 0) & 0xFF) / 255.0f,
2041 ((Color >> 24) & 0xFF) / 255.0f);
2042 checkGLcall("glClearColor");
2043 glMask = glMask | GL_COLOR_BUFFER_BIT;
2046 /* Now process each rect in turn */
2047 for (i = 0; i < Count || i == 0; i++) {
2049 if (curRect) {
2050 /* Note gl uses lower left, width/height */
2051 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
2052 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
2053 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
2054 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
2055 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
2056 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
2057 checkGLcall("glScissor");
2060 /* Clear the selected rectangle (or full screen) */
2061 glClear(glMask);
2062 checkGLcall("glClear");
2064 /* Step to the next rectangle */
2065 if (curRect) curRect = curRect + sizeof(D3DRECT);
2068 /* Restore the old values (why..?) */
2069 if (Flags & D3DCLEAR_STENCIL) {
2070 glClearStencil(old_stencil_clear_value);
2072 if (Flags & D3DCLEAR_ZBUFFER) {
2073 glDepthMask(old_ztest);
2074 glClearDepth(old_z_clear_value);
2076 if (Flags & D3DCLEAR_TARGET) {
2077 glClearColor(old_color_clear_value[0],
2078 old_color_clear_value[1],
2079 old_color_clear_value[2],
2080 old_color_clear_value[3]);
2083 if (Count > 0 && pRects) {
2084 glDisable(GL_SCISSOR_TEST);
2085 checkGLcall("glDisable");
2087 LEAVE_GL();
2089 return D3D_OK;
2091 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
2092 ICOM_THIS(IDirect3DDevice8Impl,iface);
2093 D3DMATRIX m;
2094 int k;
2095 float f;
2096 BOOL viewChanged = TRUE;
2097 int Stage;
2099 /* Most of this routine, comments included copied from ddraw tree initially: */
2100 TRACE("(%p) : State=%d\n", This, d3dts);
2102 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
2103 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
2104 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2106 /* Handle recording of state blocks */
2107 if (This->isRecordingState) {
2108 TRACE("Recording... not performing anything\n");
2109 return D3D_OK;
2113 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2115 where ViewMat = Camera space, WorldMat = world space.
2117 In OpenGL, camera and world space is combined into GL_MODELVIEW
2118 matrix. The Projection matrix stay projection matrix. */
2120 /* After reading through both OpenGL and Direct3D documentations, I
2121 thought that D3D matrices were written in 'line major mode' transposed
2122 from OpenGL's 'column major mode'. But I found out that a simple memcpy
2123 works fine to transfer one matrix format to the other (it did not work
2124 when transposing)....
2126 So :
2127 1) are the documentations wrong
2128 2) does the matrix work even if they are not read correctly
2129 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
2130 loading using glLoadMatrix ?
2132 Anyway, I always use 'conv_mat' to transfer the matrices from one format
2133 to the other so that if I ever find out that I need to transpose them, I
2134 will able to do it quickly, only by changing the macro conv_mat. */
2136 if (d3dts < 256) {
2137 switch (d3dts) {
2138 case D3DTS_VIEW:
2139 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
2140 break;
2142 case D3DTS_PROJECTION:
2143 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
2144 break;
2146 case D3DTS_TEXTURE0:
2147 case D3DTS_TEXTURE1:
2148 case D3DTS_TEXTURE2:
2149 case D3DTS_TEXTURE3:
2150 case D3DTS_TEXTURE4:
2151 case D3DTS_TEXTURE5:
2152 case D3DTS_TEXTURE6:
2153 case D3DTS_TEXTURE7:
2154 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2155 break;
2157 default:
2158 FIXME("Unhandled transform state!!\n");
2159 break;
2161 } else {
2162 /**
2163 * Indexed Vertex Blending Matrices 256 -> 511
2164 * where WORLDMATRIX(0) == 256!
2166 /** store it */
2167 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2168 #if 0
2169 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2170 FIXME("TODO\n");
2171 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2172 FIXME("TODO\n");
2174 #endif
2178 * Move the GL operation to outside of switch to make it work
2179 * regardless of transform set order.
2181 ENTER_GL();
2182 if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
2183 glMatrixMode(GL_PROJECTION);
2184 checkGLcall("glMatrixMode");
2185 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
2186 checkGLcall("glLoadMatrixf");
2187 memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
2188 } else {
2189 TRACE("Skipping as projection already correct\n");
2192 glMatrixMode(GL_MODELVIEW);
2193 checkGLcall("glMatrixMode");
2194 viewChanged = FALSE;
2195 if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
2196 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2197 checkGLcall("glLoadMatrixf");
2198 memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
2199 viewChanged = TRUE;
2201 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
2202 if (d3dts == D3DTS_VIEW) {
2204 /* NOTE: We have to reset the positions even if the light/plane is not currently
2205 enabled, since the call to enable it will not reset the position. */
2207 /* Reset lights */
2208 for (k = 0; k < GL_LIMITS(lights); k++) {
2209 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
2210 checkGLcall("glLightfv posn");
2211 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
2212 checkGLcall("glLightfv dirn");
2215 /* Reset Clipping Planes if clipping is enabled */
2216 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2217 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
2218 checkGLcall("glClipPlane");
2221 /* Reapply texture transforms as based off modelview when applied */
2222 for (Stage = 0; Stage < GL_LIMITS(textures); Stage++) {
2224 /* Only applicable if the transforms are not disabled */
2225 if (This->UpdateStateBlock->texture_state[Stage][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
2227 /* Now apply texture transforms if not applying to the dummy textures */
2228 #if defined(GL_VERSION_1_3)
2229 glActiveTexture(GL_TEXTURE0 + Stage);
2230 #else
2231 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2232 #endif
2233 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
2235 glMatrixMode(GL_TEXTURE);
2236 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2237 glLoadIdentity();
2238 } else {
2239 D3DMATRIX fred;
2240 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2241 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2244 checkGLcall("Load matrix for texture");
2246 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2248 } else if ((d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) &&
2249 (This->UpdateStateBlock->texture_state[d3dts - D3DTS_TEXTURE0][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)) {
2250 /* Now apply texture transforms if not applying to the dummy textures */
2251 Stage = d3dts - D3DTS_TEXTURE0;
2253 if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX))) {
2254 memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX));
2256 #if defined(GL_VERSION_1_3)
2257 glActiveTexture(GL_TEXTURE0 + Stage);
2258 #else
2259 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2260 #endif
2261 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
2263 glMatrixMode(GL_TEXTURE);
2264 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2265 glLoadIdentity();
2266 } else {
2267 D3DMATRIX fred;
2268 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2269 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2271 checkGLcall("Load matrix for texture");
2272 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2273 } else {
2274 TRACE("Skipping texture transform as already correct\n");
2277 } else {
2278 TRACE("Skipping view setup as view already correct\n");
2282 * Vertex Blending as described
2283 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
2285 switch (This->UpdateStateBlock->vertex_blend) {
2286 case D3DVBF_DISABLE:
2288 if (viewChanged == TRUE ||
2289 (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
2290 memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
2291 if (viewChanged == FALSE) {
2292 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2293 checkGLcall("glLoadMatrixf");
2295 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
2296 checkGLcall("glMultMatrixf");
2297 } else {
2298 TRACE("Skipping as world already correct\n");
2301 break;
2302 case D3DVBF_1WEIGHTS:
2303 case D3DVBF_2WEIGHTS:
2304 case D3DVBF_3WEIGHTS:
2306 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
2308 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
2309 * so waiting for the values before matrix work
2310 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
2311 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
2312 checkGLcall("glMultMatrixf");
2316 break;
2317 case D3DVBF_TWEENING:
2319 FIXME("valid/correct D3DVBF_TWEENING\n");
2320 f = This->UpdateStateBlock->tween_factor;
2321 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
2322 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
2323 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
2324 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
2325 if (viewChanged == FALSE) {
2326 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2327 checkGLcall("glLoadMatrixf");
2329 glMultMatrixf((float *) &m.u.m[0][0]);
2330 checkGLcall("glMultMatrixf");
2332 break;
2333 case D3DVBF_0WEIGHTS:
2335 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
2336 /* single matrix of weight 1.0f */
2337 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
2338 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
2339 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
2340 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
2341 if (viewChanged == FALSE) {
2342 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2343 checkGLcall("glLoadMatrixf");
2345 glMultMatrixf((float *) &m.u.m[0][0]);
2346 checkGLcall("glMultMatrixf");
2348 break;
2349 default:
2350 break; /* stupid compilator */
2353 LEAVE_GL();
2355 return D3D_OK;
2358 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
2359 ICOM_THIS(IDirect3DDevice8Impl,iface);
2360 TRACE("(%p) : for State %d\n", This, State);
2361 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
2362 return D3D_OK;
2365 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2366 D3DMATRIX *mat = NULL;
2367 D3DMATRIX temp;
2369 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
2370 but works regardless of recording being on.
2371 If this is found to be wrong, change to StateBlock. */
2372 ICOM_THIS(IDirect3DDevice8Impl,iface);
2373 TRACE("(%p) : For state %u\n", This, State);
2375 if (State < HIGHEST_TRANSFORMSTATE)
2377 mat = &This->UpdateStateBlock->transforms[State];
2378 } else {
2379 FIXME("Unhandled transform state!!\n");
2382 /* Copied from ddraw code: */
2383 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);
2384 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);
2385 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);
2386 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);
2388 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);
2389 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);
2390 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);
2391 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);
2393 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);
2394 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);
2395 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);
2396 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);
2398 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);
2399 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);
2400 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);
2401 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);
2403 /* Apply change via set transform - will reapply to eg. lights this way */
2404 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
2405 return D3D_OK;
2407 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
2408 ICOM_THIS(IDirect3DDevice8Impl,iface);
2410 TRACE("(%p)\n", This);
2411 This->UpdateStateBlock->Changed.viewport = TRUE;
2412 This->UpdateStateBlock->Set.viewport = TRUE;
2413 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
2415 /* Handle recording of state blocks */
2416 if (This->isRecordingState) {
2417 TRACE("Recording... not performing anything\n");
2418 return D3D_OK;
2421 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2422 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2424 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2425 checkGLcall("glDepthRange");
2426 /* Note: GL requires lower left, DirectX supplies upper left */
2427 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
2428 pViewport->Width, pViewport->Height);
2429 checkGLcall("glViewport");
2432 return D3D_OK;
2435 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
2436 ICOM_THIS(IDirect3DDevice8Impl,iface);
2437 TRACE("(%p)\n", This);
2438 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
2439 return D3D_OK;
2442 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
2443 ICOM_THIS(IDirect3DDevice8Impl,iface);
2445 This->UpdateStateBlock->Changed.material = TRUE;
2446 This->UpdateStateBlock->Set.material = TRUE;
2447 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
2449 /* Handle recording of state blocks */
2450 if (This->isRecordingState) {
2451 TRACE("Recording... not performing anything\n");
2452 return D3D_OK;
2455 ENTER_GL();
2456 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2457 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2458 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2459 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2460 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2462 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
2463 checkGLcall("glMaterialfv");
2464 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
2465 checkGLcall("glMaterialfv");
2467 /* Only change material color if specular is enabled, otherwise it is set to black */
2468 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
2469 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2470 checkGLcall("glMaterialfv");
2472 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
2473 checkGLcall("glMaterialfv");
2474 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
2475 checkGLcall("glMaterialf");
2477 LEAVE_GL();
2478 return D3D_OK;
2480 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
2481 ICOM_THIS(IDirect3DDevice8Impl,iface);
2482 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
2483 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2484 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2485 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2486 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2487 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2488 return D3D_OK;
2491 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
2492 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
2493 float rho;
2494 float quad_att;
2496 ICOM_THIS(IDirect3DDevice8Impl,iface);
2497 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2499 if (Index >= GL_LIMITS(lights)) {
2500 TRACE("Cannot handle more lights than device supports\n");
2501 return D3DERR_INVALIDCALL;
2504 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,
2505 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2506 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2507 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2508 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2509 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2510 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2512 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
2513 This->UpdateStateBlock->Set.lights[Index] = TRUE;
2514 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
2516 /* Handle recording of state blocks */
2517 if (This->isRecordingState) {
2518 TRACE("Recording... not performing anything\n");
2519 return D3D_OK;
2522 /* Diffuse: */
2523 colRGBA[0] = pLight->Diffuse.r;
2524 colRGBA[1] = pLight->Diffuse.g;
2525 colRGBA[2] = pLight->Diffuse.b;
2526 colRGBA[3] = pLight->Diffuse.a;
2527 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2528 checkGLcall("glLightfv");
2530 /* Specular */
2531 colRGBA[0] = pLight->Specular.r;
2532 colRGBA[1] = pLight->Specular.g;
2533 colRGBA[2] = pLight->Specular.b;
2534 colRGBA[3] = pLight->Specular.a;
2535 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2536 checkGLcall("glLightfv");
2538 /* Ambient */
2539 colRGBA[0] = pLight->Ambient.r;
2540 colRGBA[1] = pLight->Ambient.g;
2541 colRGBA[2] = pLight->Ambient.b;
2542 colRGBA[3] = pLight->Ambient.a;
2543 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2544 checkGLcall("glLightfv");
2546 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2547 glMatrixMode(GL_MODELVIEW);
2548 glPushMatrix();
2549 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2551 /* Attenuation - Are these right? guessing... */
2552 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
2553 checkGLcall("glLightf");
2554 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
2555 checkGLcall("glLightf");
2557 quad_att = 1.4/(pLight->Range*pLight->Range);
2558 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2559 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2560 checkGLcall("glLightf");
2562 switch (pLight->Type) {
2563 case D3DLIGHT_POINT:
2564 /* Position */
2565 This->lightPosn[Index][0] = pLight->Position.x;
2566 This->lightPosn[Index][1] = pLight->Position.y;
2567 This->lightPosn[Index][2] = pLight->Position.z;
2568 This->lightPosn[Index][3] = 1.0;
2569 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2570 checkGLcall("glLightfv");
2572 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2573 checkGLcall("glLightf");
2575 /* FIXME: Range */
2576 break;
2578 case D3DLIGHT_SPOT:
2579 /* Position */
2580 This->lightPosn[Index][0] = pLight->Position.x;
2581 This->lightPosn[Index][1] = pLight->Position.y;
2582 This->lightPosn[Index][2] = pLight->Position.z;
2583 This->lightPosn[Index][3] = 1.0;
2584 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2585 checkGLcall("glLightfv");
2587 /* Direction */
2588 This->lightDirn[Index][0] = pLight->Direction.x;
2589 This->lightDirn[Index][1] = pLight->Direction.y;
2590 This->lightDirn[Index][2] = pLight->Direction.z;
2591 This->lightDirn[Index][3] = 1.0;
2592 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2593 checkGLcall("glLightfv");
2596 * opengl-ish and d3d-ish spot lights use too different models for the
2597 * light "intensity" as a function of the angle towards the main light direction,
2598 * so we only can approximate very roughly.
2599 * however spot lights are rather rarely used in games (if ever used at all).
2600 * furthermore if still used, probably nobody pays attention to such details.
2602 if (pLight->Falloff == 0) {
2603 rho = 6.28f;
2604 } else {
2605 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2607 if (rho < 0.0001) rho = 0.0001f;
2608 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2609 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2611 /* FIXME: Range */
2612 break;
2613 case D3DLIGHT_DIRECTIONAL:
2614 /* Direction */
2615 This->lightPosn[Index][0] = -pLight->Direction.x;
2616 This->lightPosn[Index][1] = -pLight->Direction.y;
2617 This->lightPosn[Index][2] = -pLight->Direction.z;
2618 This->lightPosn[Index][3] = 0.0;
2619 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2620 checkGLcall("glLightfv");
2622 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2623 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2626 break;
2627 default:
2628 FIXME("Unrecognized light type %d\n", pLight->Type);
2631 /* Restore the modelview matrix */
2632 glPopMatrix();
2634 return D3D_OK;
2636 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2637 ICOM_THIS(IDirect3DDevice8Impl,iface);
2638 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2640 if (Index >= GL_LIMITS(lights)) {
2641 TRACE("Cannot handle more lights than device supports\n");
2642 return D3DERR_INVALIDCALL;
2645 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2646 return D3D_OK;
2648 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2649 ICOM_THIS(IDirect3DDevice8Impl,iface);
2650 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2652 if (Index >= GL_LIMITS(lights)) {
2653 TRACE("Cannot handle more lights than device supports\n");
2654 return D3DERR_INVALIDCALL;
2657 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2658 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2659 This->UpdateStateBlock->lightEnable[Index] = Enable;
2661 /* Handle recording of state blocks */
2662 if (This->isRecordingState) {
2663 TRACE("Recording... not performing anything\n");
2664 return D3D_OK;
2667 if (Enable) {
2668 glEnable(GL_LIGHT0 + Index);
2669 checkGLcall("glEnable GL_LIGHT0+Index");
2670 } else {
2671 glDisable(GL_LIGHT0 + Index);
2672 checkGLcall("glDisable GL_LIGHT0+Index");
2674 return D3D_OK;
2676 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2677 ICOM_THIS(IDirect3DDevice8Impl,iface);
2678 TRACE("(%p) : for idx(%ld)\n", This, Index);
2680 if (Index >= GL_LIMITS(lights)) {
2681 TRACE("Cannot handle more lights than device supports\n");
2682 return D3DERR_INVALIDCALL;
2685 *pEnable = This->StateBlock->lightEnable[Index];
2686 return D3D_OK;
2688 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2689 ICOM_THIS(IDirect3DDevice8Impl,iface);
2690 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2692 /* Validate Index */
2693 if (Index >= GL_LIMITS(clipplanes)) {
2694 TRACE("Application has requested clipplane this device doesnt support\n");
2695 return D3DERR_INVALIDCALL;
2698 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2699 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2700 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2701 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2702 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2703 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2705 /* Handle recording of state blocks */
2706 if (This->isRecordingState) {
2707 TRACE("Recording... not performing anything\n");
2708 return D3D_OK;
2711 /* Apply it */
2713 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2714 glMatrixMode(GL_MODELVIEW);
2715 glPushMatrix();
2716 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2718 TRACE("Clipplane [%f,%f,%f,%f]\n",
2719 This->UpdateStateBlock->clipplane[Index][0],
2720 This->UpdateStateBlock->clipplane[Index][1],
2721 This->UpdateStateBlock->clipplane[Index][2],
2722 This->UpdateStateBlock->clipplane[Index][3]);
2723 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2725 glPopMatrix();
2726 checkGLcall("glClipPlane");
2728 return D3D_OK;
2730 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2731 ICOM_THIS(IDirect3DDevice8Impl,iface);
2732 TRACE("(%p) : for idx %ld\n", This, Index);
2734 /* Validate Index */
2735 if (Index >= GL_LIMITS(clipplanes)) {
2736 TRACE("Application has requested clipplane this device doesnt support\n");
2737 return D3DERR_INVALIDCALL;
2740 pPlane[0] = This->StateBlock->clipplane[Index][0];
2741 pPlane[1] = This->StateBlock->clipplane[Index][1];
2742 pPlane[2] = This->StateBlock->clipplane[Index][2];
2743 pPlane[3] = This->StateBlock->clipplane[Index][3];
2744 return D3D_OK;
2746 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2747 ICOM_THIS(IDirect3DDevice8Impl,iface);
2748 DWORD OldValue = This->StateBlock->renderstate[State];
2750 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2751 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2752 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2753 This->UpdateStateBlock->renderstate[State] = Value;
2755 /* Handle recording of state blocks */
2756 if (This->isRecordingState) {
2757 TRACE("Recording... not performing anything\n");
2758 return D3D_OK;
2761 switch (State) {
2762 case D3DRS_FILLMODE :
2763 switch ((D3DFILLMODE) Value) {
2764 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2765 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2766 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2767 default:
2768 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2770 checkGLcall("glPolygonMode (fillmode)");
2771 break;
2773 case D3DRS_LIGHTING :
2774 if (Value) {
2775 glEnable(GL_LIGHTING);
2776 checkGLcall("glEnable GL_LIGHTING");
2777 } else {
2778 glDisable(GL_LIGHTING);
2779 checkGLcall("glDisable GL_LIGHTING");
2781 break;
2783 case D3DRS_ZENABLE :
2784 switch ((D3DZBUFFERTYPE) Value) {
2785 case D3DZB_FALSE:
2786 glDisable(GL_DEPTH_TEST);
2787 checkGLcall("glDisable GL_DEPTH_TEST");
2788 break;
2789 case D3DZB_TRUE:
2790 glEnable(GL_DEPTH_TEST);
2791 checkGLcall("glEnable GL_DEPTH_TEST");
2792 break;
2794 case D3DZB_USEW:
2795 default:
2796 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2798 break;
2800 case D3DRS_CULLMODE :
2802 /* If we are culling "back faces with clockwise vertices" then
2803 set front faces to be counter clockwise and enable culling
2804 of back faces */
2805 switch ((D3DCULL) Value) {
2806 case D3DCULL_NONE:
2807 glDisable(GL_CULL_FACE);
2808 checkGLcall("glDisable GL_CULL_FACE");
2809 break;
2810 case D3DCULL_CW:
2811 glEnable(GL_CULL_FACE);
2812 checkGLcall("glEnable GL_CULL_FACE");
2813 glFrontFace(GL_CCW);
2814 checkGLcall("glFrontFace GL_CCW");
2815 glCullFace(GL_BACK);
2816 break;
2817 case D3DCULL_CCW:
2818 glEnable(GL_CULL_FACE);
2819 checkGLcall("glEnable GL_CULL_FACE");
2820 glFrontFace(GL_CW);
2821 checkGLcall("glFrontFace GL_CW");
2822 glCullFace(GL_BACK);
2823 break;
2824 default:
2825 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2827 break;
2829 case D3DRS_SHADEMODE :
2830 switch ((D3DSHADEMODE) Value) {
2831 case D3DSHADE_FLAT:
2832 glShadeModel(GL_FLAT);
2833 checkGLcall("glShadeModel");
2834 break;
2835 case D3DSHADE_GOURAUD:
2836 glShadeModel(GL_SMOOTH);
2837 checkGLcall("glShadeModel");
2838 break;
2839 case D3DSHADE_PHONG:
2840 FIXME("D3DSHADE_PHONG isnt supported?\n");
2841 return D3DERR_INVALIDCALL;
2842 default:
2843 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2845 break;
2847 case D3DRS_DITHERENABLE :
2848 if (Value) {
2849 glEnable(GL_DITHER);
2850 checkGLcall("glEnable GL_DITHER");
2851 } else {
2852 glDisable(GL_DITHER);
2853 checkGLcall("glDisable GL_DITHER");
2855 break;
2857 case D3DRS_ZWRITEENABLE :
2858 if (Value) {
2859 glDepthMask(1);
2860 checkGLcall("glDepthMask");
2861 } else {
2862 glDepthMask(0);
2863 checkGLcall("glDepthMask");
2865 break;
2867 case D3DRS_ZFUNC :
2869 int glParm = GL_LESS;
2871 switch ((D3DCMPFUNC) Value) {
2872 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2873 case D3DCMP_LESS: glParm=GL_LESS; break;
2874 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2875 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2876 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2877 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2878 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2879 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2880 default:
2881 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2883 glDepthFunc(glParm);
2884 checkGLcall("glDepthFunc");
2886 break;
2888 case D3DRS_AMBIENT :
2890 float col[4];
2891 D3DCOLORTOGLFLOAT4(Value, col);
2892 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2893 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2894 checkGLcall("glLightModel for MODEL_AMBIENT");
2897 break;
2899 case D3DRS_ALPHABLENDENABLE :
2900 if (Value) {
2901 glEnable(GL_BLEND);
2902 checkGLcall("glEnable GL_BLEND");
2903 } else {
2904 glDisable(GL_BLEND);
2905 checkGLcall("glDisable GL_BLEND");
2907 break;
2909 case D3DRS_SRCBLEND :
2910 case D3DRS_DESTBLEND :
2912 int newVal = GL_ZERO;
2913 switch (Value) {
2914 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2915 case D3DBLEND_ONE : newVal = GL_ONE; break;
2916 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2917 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2918 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2919 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2920 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2921 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2922 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2923 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2924 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2926 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2927 This->srcBlend = newVal;
2928 This->dstBlend = newVal;
2929 break;
2931 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2932 This->srcBlend = newVal;
2933 This->dstBlend = newVal;
2934 break;
2935 default:
2936 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2939 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2940 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2941 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2942 glBlendFunc(This->srcBlend, This->dstBlend);
2944 checkGLcall("glBlendFunc");
2946 break;
2948 case D3DRS_ALPHATESTENABLE :
2949 if (Value) {
2950 glEnable(GL_ALPHA_TEST);
2951 checkGLcall("glEnable GL_ALPHA_TEST");
2952 } else {
2953 glDisable(GL_ALPHA_TEST);
2954 checkGLcall("glDisable GL_ALPHA_TEST");
2956 break;
2958 case D3DRS_ALPHAFUNC :
2960 int glParm = GL_LESS;
2961 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2963 switch ((D3DCMPFUNC) Value) {
2964 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2965 case D3DCMP_LESS: glParm = GL_LESS; break;
2966 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2967 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2968 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2969 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2970 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2971 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2972 default:
2973 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2975 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2976 glAlphaFunc(glParm, ref);
2977 This->alphafunc = glParm;
2978 checkGLcall("glAlphaFunc");
2980 break;
2982 case D3DRS_ALPHAREF :
2984 int glParm = This->alphafunc;
2985 float ref = 1.0f;
2987 ref = ((float) Value) / 255.0f;
2988 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2989 glAlphaFunc(glParm, ref);
2990 checkGLcall("glAlphaFunc");
2992 break;
2994 case D3DRS_CLIPPLANEENABLE :
2995 case D3DRS_CLIPPING :
2997 /* Ensure we only do the changed clip planes */
2998 DWORD enable = 0xFFFFFFFF;
2999 DWORD disable = 0x00000000;
3001 /* If enabling / disabling all */
3002 if (State == D3DRS_CLIPPING) {
3003 if (Value) {
3004 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
3005 disable = 0x00;
3006 } else {
3007 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
3008 enable = 0x00;
3010 } else {
3011 enable = Value & ~OldValue;
3012 disable = ~Value & OldValue;
3015 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
3016 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
3017 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
3018 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
3019 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
3020 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
3022 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
3023 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
3024 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
3025 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
3026 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
3027 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
3029 break;
3031 case D3DRS_BLENDOP :
3033 int glParm = GL_FUNC_ADD;
3035 switch ((D3DBLENDOP) Value) {
3036 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
3037 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
3038 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
3039 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
3040 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
3041 default:
3042 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
3044 TRACE("glBlendEquation(%x)\n", glParm);
3045 glBlendEquation(glParm);
3046 checkGLcall("glBlendEquation");
3048 break;
3050 case D3DRS_TEXTUREFACTOR :
3052 int i;
3054 /* Note the texture color applies to all textures whereas
3055 GL_TEXTURE_ENV_COLOR applies to active only */
3056 float col[4];
3057 D3DCOLORTOGLFLOAT4(Value, col);
3058 /* Set the default alpha blend color */
3059 glBlendColor(col[0], col[1], col[2], col[3]);
3060 checkGLcall("glBlendColor");
3062 /* And now the default texture color as well */
3063 for (i = 0; i < GL_LIMITS(textures); i++) {
3065 /* Note the D3DRS value applies to all textures, but GL has one
3066 per texture, so apply it now ready to be used! */
3067 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3068 #if defined(GL_VERSION_1_3)
3069 glActiveTexture(GL_TEXTURE0 + i);
3070 #else
3071 glActiveTextureARB(GL_TEXTURE0_ARB + i);
3072 #endif
3073 checkGLcall("Activate texture.. to update const color");
3074 } else if (i>0) {
3075 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3078 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
3079 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3082 break;
3084 case D3DRS_SPECULARENABLE :
3086 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3087 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3088 specular color. This is wrong:
3089 Seperate specular color means the specular colour is maintained seperately, whereas
3090 single color means it is merged in. However in both cases they are being used to
3091 some extent.
3092 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3093 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
3094 yet running 1.4!
3096 if (Value) {
3097 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
3098 checkGLcall("glMaterialfv");
3099 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3100 glEnable(GL_COLOR_SUM_EXT);
3101 } else {
3102 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3104 checkGLcall("glEnable(GL_COLOR_SUM)\n");
3105 } else {
3106 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3108 /* for the case of enabled lighting: */
3109 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
3110 checkGLcall("glMaterialfv");
3112 /* for the case of disabled lighting: */
3113 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3114 glDisable(GL_COLOR_SUM_EXT);
3115 } else {
3116 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3118 checkGLcall("glDisable(GL_COLOR_SUM)\n");
3121 break;
3123 case D3DRS_STENCILENABLE :
3124 if (Value) {
3125 glEnable(GL_STENCIL_TEST);
3126 checkGLcall("glEnable GL_STENCIL_TEST");
3127 } else {
3128 glDisable(GL_STENCIL_TEST);
3129 checkGLcall("glDisable GL_STENCIL_TEST");
3131 break;
3133 case D3DRS_STENCILFUNC :
3135 int glParm = GL_ALWAYS;
3136 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
3137 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
3139 switch ((D3DCMPFUNC) Value) {
3140 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3141 case D3DCMP_LESS: glParm=GL_LESS; break;
3142 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3143 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3144 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3145 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3146 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3147 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3148 default:
3149 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3151 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3152 This->stencilfunc = glParm;
3153 glStencilFunc(glParm, ref, mask);
3154 checkGLcall("glStencilFunc");
3156 break;
3158 case D3DRS_STENCILREF :
3160 int glParm = This->stencilfunc;
3161 int ref = 0;
3162 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
3164 ref = Value;
3165 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3166 glStencilFunc(glParm, ref, mask);
3167 checkGLcall("glStencilFunc");
3169 break;
3171 case D3DRS_STENCILMASK :
3173 int glParm = This->stencilfunc;
3174 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
3175 GLuint mask = Value;
3177 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3178 glStencilFunc(glParm, ref, mask);
3179 checkGLcall("glStencilFunc");
3181 break;
3183 case D3DRS_STENCILFAIL :
3185 GLenum fail ;
3186 GLenum zpass ;
3187 GLenum zfail ;
3189 fail = StencilOp(Value);
3190 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3191 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3192 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3193 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3195 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3196 glStencilOp(fail, zfail, zpass);
3197 checkGLcall("glStencilOp(fail, zfail, zpass);");
3199 break;
3200 case D3DRS_STENCILZFAIL :
3202 GLenum fail ;
3203 GLenum zpass ;
3204 GLenum zfail ;
3206 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3207 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3208 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3209 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3210 zfail = StencilOp(Value);
3212 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3213 glStencilOp(fail, zfail, zpass);
3214 checkGLcall("glStencilOp(fail, zfail, zpass);");
3216 break;
3217 case D3DRS_STENCILPASS :
3219 GLenum fail ;
3220 GLenum zpass ;
3221 GLenum zfail ;
3223 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3224 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3225 zpass = StencilOp(Value);
3226 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3227 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3229 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3230 glStencilOp(fail, zfail, zpass);
3231 checkGLcall("glStencilOp(fail, zfail, zpass);");
3233 break;
3235 case D3DRS_STENCILWRITEMASK :
3237 glStencilMask(Value);
3238 TRACE("glStencilMask(%lu)\n", Value);
3239 checkGLcall("glStencilMask");
3241 break;
3243 case D3DRS_FOGENABLE :
3245 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
3246 glEnable(GL_FOG);
3247 checkGLcall("glEnable GL_FOG\n");
3248 } else {
3249 glDisable(GL_FOG);
3250 checkGLcall("glDisable GL_FOG\n");
3253 break;
3255 case D3DRS_FOGCOLOR :
3257 float col[4];
3258 D3DCOLORTOGLFLOAT4(Value, col);
3259 /* Set the default alpha blend color */
3260 glFogfv(GL_FOG_COLOR, &col[0]);
3261 checkGLcall("glFog GL_FOG_COLOR");
3263 break;
3265 case D3DRS_FOGTABLEMODE :
3267 switch (Value) {
3268 case D3DFOG_NONE: /* I don't know what to do here */ break;
3269 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3270 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3271 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3272 default:
3273 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
3276 break;
3278 case D3DRS_FOGSTART :
3280 float *f = (float*) &Value;
3281 glFogfv(GL_FOG_START, f);
3282 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3283 TRACE("Fog Start == %f\n", *f);
3285 break;
3287 case D3DRS_FOGEND :
3289 float *f = (float*) &Value;
3290 glFogfv(GL_FOG_END, f);
3291 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3292 TRACE("Fog End == %f\n", *f);
3294 break;
3296 case D3DRS_FOGDENSITY :
3298 float *f = (float*) &Value;
3299 glFogfv(GL_FOG_DENSITY, f);
3300 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3302 break;
3304 case D3DRS_VERTEXBLEND :
3306 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3307 TRACE("Vertex Blending state to %ld\n", Value);
3309 break;
3311 case D3DRS_TWEENFACTOR :
3313 This->UpdateStateBlock->tween_factor = *((float*) &Value);
3314 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
3316 break;
3318 case D3DRS_INDEXEDVERTEXBLENDENABLE :
3320 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3322 break;
3324 case D3DRS_COLORVERTEX :
3325 case D3DRS_DIFFUSEMATERIALSOURCE :
3326 case D3DRS_SPECULARMATERIALSOURCE :
3327 case D3DRS_AMBIENTMATERIALSOURCE :
3328 case D3DRS_EMISSIVEMATERIALSOURCE :
3330 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3332 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
3333 glEnable(GL_COLOR_MATERIAL);
3334 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
3336 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3337 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
3338 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
3339 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
3340 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
3342 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3343 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3344 Parm = GL_AMBIENT_AND_DIFFUSE;
3345 } else {
3346 Parm = GL_DIFFUSE;
3348 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3349 Parm = GL_AMBIENT;
3350 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3351 Parm = GL_EMISSION;
3352 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3353 Parm = GL_SPECULAR;
3354 } else {
3355 Parm = -1;
3358 if (Parm == -1) {
3359 glDisable(GL_COLOR_MATERIAL);
3360 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3361 } else {
3362 TRACE("glColorMaterial Parm=%d\n", Parm);
3363 glColorMaterial(GL_FRONT_AND_BACK, Parm);
3364 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
3367 } else {
3368 glDisable(GL_COLOR_MATERIAL);
3369 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3372 break;
3374 case D3DRS_LINEPATTERN :
3376 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
3377 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
3379 if (pattern->wRepeatFactor) {
3380 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
3381 checkGLcall("glLineStipple(repeat, linepattern)\n");
3382 glEnable(GL_LINE_STIPPLE);
3383 checkGLcall("glEnable(GL_LINE_STIPPLE);\n");
3384 } else {
3385 glDisable(GL_LINE_STIPPLE);
3386 checkGLcall("glDisable(GL_LINE_STIPPLE);\n");
3389 break;
3391 case D3DRS_ZBIAS :
3393 if (Value) {
3394 TRACE("ZBias value %f\n", *((float*)&Value));
3395 glPolygonOffset(0, -*((float*)&Value));
3396 checkGLcall("glPolygonOffset(0, -Value)");
3397 glEnable(GL_POLYGON_OFFSET_FILL);
3398 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3399 glEnable(GL_POLYGON_OFFSET_LINE);
3400 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3401 glEnable(GL_POLYGON_OFFSET_POINT);
3402 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3403 } else {
3404 glDisable(GL_POLYGON_OFFSET_FILL);
3405 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3406 glDisable(GL_POLYGON_OFFSET_LINE);
3407 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3408 glDisable(GL_POLYGON_OFFSET_POINT);
3409 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3412 break;
3414 case D3DRS_NORMALIZENORMALS :
3415 if (Value) {
3416 glEnable(GL_NORMALIZE);
3417 checkGLcall("glEnable(GL_NORMALIZE);");
3418 } else {
3419 glDisable(GL_NORMALIZE);
3420 checkGLcall("glDisable(GL_NORMALIZE);");
3422 break;
3424 case D3DRS_POINTSIZE :
3425 TRACE("Set point size to %f\n", *((float*)&Value));
3426 glPointSize(*((float*)&Value));
3427 checkGLcall("glPointSize(...);\n");
3428 break;
3430 case D3DRS_POINTSIZE_MIN :
3431 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3432 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
3433 checkGLcall("glPointParameterfEXT(...);\n");
3434 } else {
3435 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
3437 break;
3439 case D3DRS_POINTSIZE_MAX :
3440 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3441 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
3442 checkGLcall("glPointParameterfEXT(...);\n");
3443 } else {
3444 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
3446 break;
3448 case D3DRS_POINTSCALE_A :
3449 case D3DRS_POINTSCALE_B :
3450 case D3DRS_POINTSCALE_C :
3451 case D3DRS_POINTSCALEENABLE :
3453 /* If enabled, supply the parameters, otherwise fall back to defaults */
3454 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
3455 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3456 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
3457 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
3458 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
3460 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3461 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3462 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
3463 } else {
3464 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
3466 } else {
3467 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3468 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3469 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3470 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
3471 } else {
3472 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
3475 break;
3478 case D3DRS_COLORWRITEENABLE :
3479 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3480 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3481 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3482 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3483 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3484 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
3485 Value & D3DCOLORWRITEENABLE_GREEN,
3486 Value & D3DCOLORWRITEENABLE_BLUE,
3487 Value & D3DCOLORWRITEENABLE_ALPHA);
3488 checkGLcall("glColorMask(...)\n");
3489 break;
3491 /* Unhandled yet...! */
3492 case D3DRS_LASTPIXEL :
3493 case D3DRS_ZVISIBLE :
3494 case D3DRS_EDGEANTIALIAS :
3495 case D3DRS_RANGEFOGENABLE :
3496 case D3DRS_WRAP0 :
3497 case D3DRS_WRAP1 :
3498 case D3DRS_WRAP2 :
3499 case D3DRS_WRAP3 :
3500 case D3DRS_WRAP4 :
3501 case D3DRS_WRAP5 :
3502 case D3DRS_WRAP6 :
3503 case D3DRS_WRAP7 :
3504 case D3DRS_FOGVERTEXMODE :
3505 case D3DRS_LOCALVIEWER :
3506 case D3DRS_SOFTWAREVERTEXPROCESSING :
3507 case D3DRS_POINTSPRITEENABLE :
3508 case D3DRS_MULTISAMPLEANTIALIAS :
3509 case D3DRS_MULTISAMPLEMASK :
3510 case D3DRS_PATCHEDGESTYLE :
3511 case D3DRS_PATCHSEGMENTS :
3512 case D3DRS_DEBUGMONITORTOKEN :
3513 case D3DRS_POSITIONORDER :
3514 case D3DRS_NORMALORDER :
3515 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3516 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3517 break;
3518 default:
3519 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3522 return D3D_OK;
3524 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3525 ICOM_THIS(IDirect3DDevice8Impl,iface);
3526 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3527 *pValue = This->StateBlock->renderstate[State];
3528 return D3D_OK;
3530 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3531 ICOM_THIS(IDirect3DDevice8Impl,iface);
3533 TRACE("(%p)\n", This);
3535 return IDirect3DDeviceImpl_BeginStateBlock(This);
3537 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3538 IDirect3DStateBlockImpl* pSB;
3539 ICOM_THIS(IDirect3DDevice8Impl,iface);
3540 HRESULT res;
3542 TRACE("(%p)\n", This);
3544 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3545 *pToken = (DWORD) pSB;
3546 return res;
3549 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3550 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3551 ICOM_THIS(IDirect3DDevice8Impl,iface);
3553 TRACE("(%p)\n", This);
3555 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3558 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3559 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3560 ICOM_THIS(IDirect3DDevice8Impl,iface);
3562 TRACE("(%p)\n", This);
3564 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3566 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3567 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3568 ICOM_THIS(IDirect3DDevice8Impl,iface);
3570 TRACE("(%p)\n", This);
3572 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3575 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3576 IDirect3DStateBlockImpl* pSB;
3577 ICOM_THIS(IDirect3DDevice8Impl,iface);
3578 HRESULT res;
3580 TRACE("(%p) : for type %d\n", This, Type);
3582 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3583 *pToken = (DWORD) pSB;
3584 return res;
3587 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3588 ICOM_THIS(IDirect3DDevice8Impl,iface);
3589 FIXME("(%p) : stub\n", This); return D3D_OK;
3591 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3592 ICOM_THIS(IDirect3DDevice8Impl,iface);
3593 FIXME("(%p) : stub\n", This); return D3D_OK;
3595 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3596 ICOM_THIS(IDirect3DDevice8Impl,iface);
3597 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3598 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3599 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3600 return D3D_OK;
3602 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3604 IDirect3DBaseTexture8 *oldTxt;
3605 BOOL reapplyStates = TRUE;
3607 ICOM_THIS(IDirect3DDevice8Impl,iface);
3608 D3DRESOURCETYPE textureType;
3610 oldTxt = This->UpdateStateBlock->textures[Stage];
3611 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3613 /* Reject invalid texture units */
3614 if (Stage >= GL_LIMITS(textures)) {
3615 TRACE("Attempt to access invalid texture rejected\n");
3616 return D3DERR_INVALIDCALL;
3619 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3620 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3621 This->UpdateStateBlock->textures[Stage] = pTexture;
3623 /* Handle recording of state blocks */
3624 if (This->isRecordingState) {
3625 TRACE("Recording... not performing anything\n");
3626 return D3D_OK;
3629 /* Make appropriate texture active */
3630 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3631 #if defined(GL_VERSION_1_3)
3632 glActiveTexture(GL_TEXTURE0 + Stage);
3633 #else
3634 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3635 #endif
3636 checkGLcall("glActiveTextureARB");
3637 } else if (Stage>0) {
3638 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3641 /* Decrement the count of the previous texture */
3642 if (NULL != oldTxt) {
3643 IDirect3DBaseTexture8Impl_Release(oldTxt);
3646 if (NULL != pTexture) {
3647 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3649 /* Now setup the texture appropraitly */
3650 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3652 if (textureType == D3DRTYPE_TEXTURE) {
3653 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3654 TRACE("Skipping setting texture as old == new\n");
3655 reapplyStates = FALSE;
3656 } else {
3657 /* Standard 2D texture */
3658 TRACE("Standard 2d texture\n");
3659 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3661 /* Load up the texture now */
3662 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3664 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3665 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3666 TRACE("Skipping setting texture as old == new\n");
3667 reapplyStates = FALSE;
3668 } else {
3669 /* Standard 3D (volume) texture */
3670 TRACE("Standard 3d texture\n");
3671 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3673 /* Load up the texture now */
3674 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3676 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3677 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3678 TRACE("Skipping setting texture as old == new\n");
3679 reapplyStates = FALSE;
3680 } else {
3681 /* Standard Cube texture */
3682 TRACE("Standard Cube texture\n");
3683 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3685 /* Load up the texture now */
3686 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3688 } else {
3689 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3691 } else {
3692 TRACE("Setting to no texture (ie default texture)\n");
3693 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3694 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3695 checkGLcall("glBindTexture");
3696 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3699 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3700 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3701 if (reapplyStates) {
3702 setupTextureStates(iface, Stage);
3705 return D3D_OK;
3708 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3709 ICOM_THIS(IDirect3DDevice8Impl,iface);
3710 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3711 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3712 return D3D_OK;
3715 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3716 ICOM_THIS(IDirect3DDevice8Impl,iface);
3718 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3720 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value=%ld\n", This, Stage, Type, Value);
3722 /* Reject invalid texture units */
3723 if (Stage >= GL_LIMITS(textures)) {
3724 TRACE("Attempt to access invalid texture rejected\n");
3725 return D3DERR_INVALIDCALL;
3728 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3729 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3730 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3732 /* Handle recording of state blocks */
3733 if (This->isRecordingState) {
3734 TRACE("Recording... not performing anything\n");
3735 return D3D_OK;
3738 /* Make appropriate texture active */
3739 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3740 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3741 #if defined(GL_VERSION_1_3)
3742 glActiveTexture(GL_TEXTURE0 + Stage);
3743 vcheckGLcall("glActiveTexture");
3744 #else
3745 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3746 vcheckGLcall("glActiveTextureARB");
3747 #endif
3748 } else if (Stage > 0) {
3749 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3752 switch (Type) {
3754 case D3DTSS_MINFILTER :
3755 case D3DTSS_MIPFILTER :
3757 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3758 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3759 GLint realVal = GL_LINEAR;
3761 if (ValueMIN == D3DTEXF_POINT) {
3762 /* GL_NEAREST_* */
3763 if (ValueMIP == D3DTEXF_POINT) {
3764 realVal = GL_NEAREST_MIPMAP_NEAREST;
3765 } else if (ValueMIP == D3DTEXF_LINEAR) {
3766 realVal = GL_NEAREST_MIPMAP_LINEAR;
3767 } else if (ValueMIP == D3DTEXF_NONE) {
3768 realVal = GL_NEAREST;
3769 } else {
3770 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3771 realVal = GL_NEAREST_MIPMAP_LINEAR;
3773 } else if (ValueMIN == D3DTEXF_LINEAR) {
3774 /* GL_LINEAR_* */
3775 if (ValueMIP == D3DTEXF_POINT) {
3776 realVal = GL_LINEAR_MIPMAP_NEAREST;
3777 } else if (ValueMIP == D3DTEXF_LINEAR) {
3778 realVal = GL_LINEAR_MIPMAP_LINEAR;
3779 } else if (ValueMIP == D3DTEXF_NONE) {
3780 realVal = GL_LINEAR;
3781 } else {
3782 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3783 realVal = GL_LINEAR_MIPMAP_LINEAR;
3785 } else if (ValueMIN == D3DTEXF_NONE) {
3786 /* Doesnt really make sense - Windows just seems to disable
3787 mipmapping when this occurs */
3788 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3789 realVal = GL_LINEAR;
3791 } else {
3792 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3793 realVal = GL_LINEAR_MIPMAP_LINEAR;
3796 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3797 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3798 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3800 break;
3802 case D3DTSS_MAXANISOTROPY :
3804 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3805 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3806 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3809 break;
3811 case D3DTSS_MAGFILTER :
3812 if (Value == D3DTEXF_POINT) {
3813 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3814 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3815 } else if (Value == D3DTEXF_LINEAR) {
3816 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3817 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3818 } else {
3819 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3821 break;
3823 case D3DTSS_ALPHAOP :
3824 case D3DTSS_COLOROP :
3827 if (Value == D3DTOP_DISABLE) {
3828 /* TODO: Disable by making this and all later levels disabled */
3829 if (Type == D3DTSS_COLOROP) {
3830 glDisable(GL_TEXTURE_1D);
3831 checkGLcall("Disable GL_TEXTURE_1D");
3832 glDisable(GL_TEXTURE_2D);
3833 checkGLcall("Disable GL_TEXTURE_2D");
3834 glDisable(GL_TEXTURE_3D);
3835 checkGLcall("Disable GL_TEXTURE_3D");
3837 break; /* Dont bother setting the texture operations */
3838 } else {
3839 /* Enable only the appropriate texture dimension */
3840 if (Type == D3DTSS_COLOROP) {
3841 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3842 glEnable(GL_TEXTURE_1D);
3843 checkGLcall("Enable GL_TEXTURE_1D");
3844 } else {
3845 glDisable(GL_TEXTURE_1D);
3846 checkGLcall("Disable GL_TEXTURE_1D");
3848 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3849 glEnable(GL_TEXTURE_2D);
3850 checkGLcall("Enable GL_TEXTURE_2D");
3851 } else {
3852 glDisable(GL_TEXTURE_2D);
3853 checkGLcall("Disable GL_TEXTURE_2D");
3855 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3856 glEnable(GL_TEXTURE_3D);
3857 checkGLcall("Enable GL_TEXTURE_3D");
3858 } else {
3859 glDisable(GL_TEXTURE_3D);
3860 checkGLcall("Disable GL_TEXTURE_3D");
3862 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3863 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3864 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3865 } else {
3866 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3867 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3871 /* Drop through... (Except disable case) */
3872 case D3DTSS_COLORARG0 :
3873 case D3DTSS_COLORARG1 :
3874 case D3DTSS_COLORARG2 :
3875 case D3DTSS_ALPHAARG0 :
3876 case D3DTSS_ALPHAARG1 :
3877 case D3DTSS_ALPHAARG2 :
3879 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3880 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3881 if (isAlphaArg) {
3882 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3883 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3884 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3885 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3886 } else {
3887 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3888 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3889 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3890 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3893 break;
3896 case D3DTSS_ADDRESSU :
3897 case D3DTSS_ADDRESSV :
3898 case D3DTSS_ADDRESSW :
3900 GLint wrapParm = GL_REPEAT;
3901 switch (Value) {
3902 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3903 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3904 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3905 #if defined(GL_VERSION_1_4)
3906 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3907 #elif defined(GL_ARB_texture_mirrored_repeat)
3908 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3909 #else
3910 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3911 #endif
3912 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3913 default:
3914 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3915 wrapParm = GL_REPEAT;
3918 switch (Type) {
3919 case D3DTSS_ADDRESSU:
3920 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3921 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3922 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3923 break;
3924 case D3DTSS_ADDRESSV:
3925 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3926 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3927 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3928 break;
3929 case D3DTSS_ADDRESSW:
3930 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3931 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3932 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3933 break;
3934 default: /* nop */
3935 break; /** stupic compilator */
3938 break;
3940 case D3DTSS_BORDERCOLOR :
3942 float col[4];
3943 D3DCOLORTOGLFLOAT4(Value, col);
3944 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3945 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3946 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3948 break;
3950 case D3DTSS_TEXCOORDINDEX :
3952 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3954 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3955 one flag, you can still specify an index value, which the system uses to
3956 determine the texture wrapping mode.
3957 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3958 means use the vertex position (camera-space) as the input texture coordinates
3959 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3960 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3961 to the TEXCOORDINDEX value */
3963 /**
3964 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3966 switch (Value & 0xFFFF0000) {
3967 case D3DTSS_TCI_PASSTHRU:
3968 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3969 glDisable(GL_TEXTURE_GEN_S);
3970 glDisable(GL_TEXTURE_GEN_T);
3971 glDisable(GL_TEXTURE_GEN_R);
3972 break;
3974 case D3DTSS_TCI_CAMERASPACEPOSITION:
3975 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3976 as the input texture coordinates for this stage's texture transformation. This
3977 equates roughly to EYE_LINEAR */
3979 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3980 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3981 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3982 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3983 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3985 glMatrixMode(GL_MODELVIEW);
3986 glPushMatrix();
3987 glLoadIdentity();
3988 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3989 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3990 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3991 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3992 glPopMatrix();
3994 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3995 glEnable(GL_TEXTURE_GEN_S);
3996 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3997 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3998 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3999 glEnable(GL_TEXTURE_GEN_T);
4000 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4001 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4002 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4003 glEnable(GL_TEXTURE_GEN_R);
4004 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4005 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4006 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4008 break;
4010 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
4011 case D3DTSS_TCI_CAMERASPACENORMAL:
4013 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4014 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4015 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4016 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4017 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4019 glMatrixMode(GL_MODELVIEW);
4020 glPushMatrix();
4021 glLoadIdentity();
4022 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4023 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4024 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4025 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4026 glPopMatrix();
4028 glEnable(GL_TEXTURE_GEN_S);
4029 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4030 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
4031 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
4032 glEnable(GL_TEXTURE_GEN_T);
4033 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4034 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
4035 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
4036 glEnable(GL_TEXTURE_GEN_R);
4037 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4038 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
4039 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
4041 break;
4042 #endif
4044 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
4045 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4048 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4049 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4050 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4051 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4052 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4054 glMatrixMode(GL_MODELVIEW);
4055 glPushMatrix();
4056 glLoadIdentity();
4057 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4058 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4059 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4060 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4061 glPopMatrix();
4063 glEnable(GL_TEXTURE_GEN_S);
4064 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4065 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
4066 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
4067 glEnable(GL_TEXTURE_GEN_T);
4068 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4069 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
4070 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
4071 glEnable(GL_TEXTURE_GEN_R);
4072 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4073 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
4074 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
4076 break;
4077 #endif
4079 /* Unhandled types: */
4080 default:
4081 /* Todo: */
4082 /* ? disable GL_TEXTURE_GEN_n ? */
4083 glDisable(GL_TEXTURE_GEN_S);
4084 glDisable(GL_TEXTURE_GEN_T);
4085 glDisable(GL_TEXTURE_GEN_R);
4086 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
4087 break;
4090 break;
4092 /* Unhandled */
4093 case D3DTSS_BUMPENVMAT00 :
4094 case D3DTSS_BUMPENVMAT01 :
4095 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
4096 break;
4097 case D3DTSS_BUMPENVMAT10 :
4098 case D3DTSS_BUMPENVMAT11 :
4099 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
4100 break;
4102 case D3DTSS_TEXTURETRANSFORMFLAGS :
4104 switch (Value & ~D3DTTFF_PROJECTED)
4106 case D3DTTFF_DISABLE: /* Disable transform matrix for this texture by setting up the identity matrix */
4107 glMatrixMode(GL_TEXTURE);
4108 glLoadIdentity();
4109 checkGLcall("Load identity matrix for texture");
4110 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
4111 break;
4113 default: /* Enable it */
4114 IDirect3DDevice8Impl_SetTransform(iface, D3DTS_TEXTURE0+Stage, &This->UpdateStateBlock->transforms[D3DTS_TEXTURE0+Stage]);
4115 break;
4118 /* From web: <quote source="opengl12.pdf" section="Apendix C, Version 1.1/Other changes"
4119 2. Texture coordinates s, t, and r are divided by q during the rasterization
4120 of points, pixel rectangles, and bitmaps. This division was documented
4121 only for lines and polygons in the 1.0 version. </quote>
4122 I interpret this as we can implement projected transforms in slow vertex mode
4123 by moving the last coord to the 'q' coord and using one less dimension. The only
4124 way to do it in TexCoordPtr would be to massage the data stream to insert extra
4125 coords */
4127 break;
4129 case D3DTSS_MIPMAPLODBIAS :
4130 case D3DTSS_MAXMIPLEVEL :
4131 case D3DTSS_BUMPENVLSCALE :
4132 case D3DTSS_BUMPENVLOFFSET :
4133 case D3DTSS_RESULTARG :
4134 default:
4135 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4136 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4138 return D3D_OK;
4140 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
4141 ICOM_THIS(IDirect3DDevice8Impl,iface);
4142 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
4143 return D3D_OK;
4145 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
4146 ICOM_THIS(IDirect3DDevice8Impl,iface);
4147 FIXME("(%p) : stub\n", This);
4148 return D3D_OK;
4150 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4151 ICOM_THIS(IDirect3DDevice8Impl,iface);
4152 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
4153 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
4154 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
4155 return D3D_OK;
4157 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4158 ICOM_THIS(IDirect3DDevice8Impl,iface);
4159 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
4160 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
4161 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
4162 return D3D_OK;
4164 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
4165 ICOM_THIS(IDirect3DDevice8Impl,iface);
4166 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
4167 This->currentPalette = PaletteNumber;
4168 #if defined(GL_EXT_paletted_texture)
4169 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
4170 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
4171 GL_RGBA, /* internal format */
4172 256, /* table size */
4173 GL_RGBA, /* table format */
4174 GL_UNSIGNED_BYTE, /* table type */
4175 This->palettes[PaletteNumber]);
4176 checkGLcall("glColorTableEXT");
4177 } else {
4178 /* Delayed palette handling ... waiting for software emulation into preload code */
4180 #endif
4181 return D3D_OK;
4183 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
4184 ICOM_THIS(IDirect3DDevice8Impl,iface);
4185 *PaletteNumber = This->currentPalette;
4186 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
4187 return D3D_OK;
4189 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
4191 IDirect3DVertexBuffer8 *pVB;
4193 ICOM_THIS(IDirect3DDevice8Impl,iface);
4194 pVB = This->StateBlock->stream_source[0];
4196 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
4198 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
4199 This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
4201 return D3D_OK;
4203 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
4204 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
4205 UINT idxStride = 2;
4206 IDirect3DIndexBuffer8 *pIB;
4207 IDirect3DVertexBuffer8 *pVB;
4208 D3DINDEXBUFFER_DESC IdxBufDsc;
4210 ICOM_THIS(IDirect3DDevice8Impl,iface);
4211 pIB = This->StateBlock->pIndexData;
4212 pVB = This->StateBlock->stream_source[0];
4214 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
4215 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4216 minIndex, NumVertices, startIndex, primCount);
4218 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
4219 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
4220 idxStride = 2;
4221 } else {
4222 idxStride = 4;
4225 DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
4226 This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
4227 minIndex);
4229 return D3D_OK;
4231 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
4232 ICOM_THIS(IDirect3DDevice8Impl,iface);
4234 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4235 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4237 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4239 This->StateBlock->stream_source[0] = NULL;
4240 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4241 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4242 0, 0, 0, NULL, 0);
4243 This->StateBlock->stream_stride[0] = 0;
4245 /*stream zero settings set to null at end */
4246 return D3D_OK;
4248 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4249 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4250 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4251 UINT VertexStreamZeroStride) {
4252 int idxStride;
4253 ICOM_THIS(IDirect3DDevice8Impl,iface);
4254 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),
4255 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4257 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4258 if (IndexDataFormat == D3DFMT_INDEX16) {
4259 idxStride = 2;
4260 } else {
4261 idxStride = 4;
4264 This->StateBlock->stream_source[0] = NULL;
4265 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4266 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4267 This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4269 /*stream zero settings set to null at end */
4270 This->StateBlock->stream_stride[0] = 0;
4271 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4273 return D3D_OK;
4275 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4276 ICOM_THIS(IDirect3DDevice8Impl,iface);
4277 FIXME("(%p) : stub\n", This); return D3D_OK;
4279 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4280 ICOM_THIS(IDirect3DDevice8Impl,iface);
4281 IDirect3DVertexShaderImpl* object;
4282 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4283 HRESULT res;
4284 UINT i;
4286 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
4287 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4288 return D3DERR_INVALIDCALL;
4290 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4291 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4292 return D3DERR_OUTOFVIDEOMEMORY;
4295 /** Create the Vertex Shader */
4296 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4297 /** TODO: check FAILED(res) */
4299 /** Create and Bind the Vertex Shader Declaration */
4300 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4301 /** TODO: check FAILED(res) */
4303 VertexShaders[i] = object;
4304 VertexShaderDeclarations[i] = attached_decl;
4305 *pHandle = VS_HIGHESTFIXEDFXF + i;
4307 return D3D_OK;
4309 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4310 ICOM_THIS(IDirect3DDevice8Impl,iface);
4312 This->UpdateStateBlock->VertexShader = Handle;
4313 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4314 This->UpdateStateBlock->Set.vertexShader = TRUE;
4316 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4317 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4318 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4319 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4320 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4321 } else { /* use a fvf, so desactivate the vshader decl */
4322 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4323 This->UpdateStateBlock->vertexShaderDecl = NULL;
4324 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4325 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4327 /* Handle recording of state blocks */
4328 if (This->isRecordingState) {
4329 TRACE("Recording... not performing anything\n");
4330 return D3D_OK;
4333 * TODO: merge HAL shaders context switching from prototype
4335 return D3D_OK;
4337 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4338 ICOM_THIS(IDirect3DDevice8Impl,iface);
4339 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4340 *pHandle = This->StateBlock->VertexShader;
4341 return D3D_OK;
4344 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4345 ICOM_THIS(IDirect3DDevice8Impl,iface);
4346 IDirect3DVertexShaderImpl* object;
4347 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4349 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4350 return D3DERR_INVALIDCALL;
4354 * Delete Vertex Shader
4356 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4357 if (NULL == object) {
4358 return D3DERR_INVALIDCALL;
4360 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4361 /* TODO: check validity of object */
4362 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4363 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4364 HeapFree(GetProcessHeap(), 0, (void *)object);
4365 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4368 * Delete Vertex Shader Declaration
4370 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4371 if (NULL == attached_decl) {
4372 return D3DERR_INVALIDCALL;
4374 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4375 /* TODO: check validity of object */
4376 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4377 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4378 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4380 return D3D_OK;
4383 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4384 ICOM_THIS(IDirect3DDevice8Impl,iface);
4386 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4387 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4388 return D3DERR_INVALIDCALL;
4390 if (NULL == pConstantData) {
4391 return D3DERR_INVALIDCALL;
4393 if (ConstantCount > 1) {
4394 FLOAT* f = (FLOAT*)pConstantData;
4395 UINT i;
4396 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4397 for (i = 0; i < ConstantCount; ++i) {
4398 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4399 f += 4;
4401 } else {
4402 FLOAT* f = (FLOAT*) pConstantData;
4403 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4405 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4406 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4407 return D3D_OK;
4409 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4410 ICOM_THIS(IDirect3DDevice8Impl,iface);
4412 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4413 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4414 return D3DERR_INVALIDCALL;
4416 if (NULL == pConstantData) {
4417 return D3DERR_INVALIDCALL;
4419 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4420 return D3D_OK;
4422 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4423 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4424 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4426 attached_decl = VERTEX_SHADER_DECL(Handle);
4427 if (NULL == attached_decl) {
4428 return D3DERR_INVALIDCALL;
4430 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4432 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4433 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4434 IDirect3DVertexShaderImpl* object;
4436 object = VERTEX_SHADER(Handle);
4437 if (NULL == object) {
4438 return D3DERR_INVALIDCALL;
4440 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4443 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4444 ICOM_THIS(IDirect3DDevice8Impl,iface);
4445 IDirect3DIndexBuffer8 *oldIdxs;
4447 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4448 oldIdxs = This->StateBlock->pIndexData;
4450 This->UpdateStateBlock->Changed.Indices = TRUE;
4451 This->UpdateStateBlock->Set.Indices = TRUE;
4452 This->UpdateStateBlock->pIndexData = pIndexData;
4453 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4455 /* Handle recording of state blocks */
4456 if (This->isRecordingState) {
4457 TRACE("Recording... not performing anything\n");
4458 return D3D_OK;
4461 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4462 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4463 return D3D_OK;
4465 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4466 ICOM_THIS(IDirect3DDevice8Impl,iface);
4467 FIXME("(%p) : stub\n", This);
4469 *ppIndexData = This->StateBlock->pIndexData;
4470 /* up ref count on ppindexdata */
4471 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4472 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4474 return D3D_OK;
4476 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4477 ICOM_THIS(IDirect3DDevice8Impl,iface);
4478 IDirect3DPixelShaderImpl* object;
4479 HRESULT res;
4480 UINT i;
4482 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4483 if (NULL == pFunction || NULL == pHandle) {
4484 return D3DERR_INVALIDCALL;
4486 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4487 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4488 return D3DERR_OUTOFVIDEOMEMORY;
4491 /** Create the Pixel Shader */
4492 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4493 if (SUCCEEDED(res)) {
4494 PixelShaders[i] = object;
4495 *pHandle = VS_HIGHESTFIXEDFXF + i;
4496 return D3D_OK;
4498 *pHandle = 0xFFFFFFFF;
4499 return res;
4501 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4502 ICOM_THIS(IDirect3DDevice8Impl,iface);
4504 This->UpdateStateBlock->PixelShader = Handle;
4505 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4506 This->UpdateStateBlock->Set.pixelShader = TRUE;
4508 /* Handle recording of state blocks */
4509 if (This->isRecordingState) {
4510 TRACE_(d3d_shader)("Recording... not performing anything\n");
4511 return D3D_OK;
4514 /* FIXME: Quieten when not being used */
4515 if (Handle != 0) {
4516 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4517 } else {
4518 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4521 return D3D_OK;
4523 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4524 ICOM_THIS(IDirect3DDevice8Impl,iface);
4525 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4526 *pHandle = This->StateBlock->PixelShader;
4527 return D3D_OK;
4530 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4531 ICOM_THIS(IDirect3DDevice8Impl,iface);
4532 IDirect3DPixelShaderImpl* object;
4534 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4535 return D3DERR_INVALIDCALL;
4537 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4538 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4539 /* TODO: check validity of object before free */
4540 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4541 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4542 HeapFree(GetProcessHeap(), 0, (void *)object);
4543 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4545 return D3D_OK;
4548 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4549 ICOM_THIS(IDirect3DDevice8Impl,iface);
4551 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4552 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4553 return D3DERR_INVALIDCALL;
4555 if (NULL == pConstantData) {
4556 return D3DERR_INVALIDCALL;
4558 if (ConstantCount > 1) {
4559 FLOAT* f = (FLOAT*)pConstantData;
4560 UINT i;
4561 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4562 for (i = 0; i < ConstantCount; ++i) {
4563 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4564 f += 4;
4566 } else {
4567 FLOAT* f = (FLOAT*) pConstantData;
4568 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4570 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4571 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4572 return D3D_OK;
4574 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4575 ICOM_THIS(IDirect3DDevice8Impl,iface);
4577 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4578 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4579 return D3DERR_INVALIDCALL;
4581 if (NULL == pConstantData) {
4582 return D3DERR_INVALIDCALL;
4584 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4585 return D3D_OK;
4587 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4588 IDirect3DPixelShaderImpl* object;
4590 object = PIXEL_SHADER(Handle);
4591 if (NULL == object) {
4592 return D3DERR_INVALIDCALL;
4594 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4596 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4597 ICOM_THIS(IDirect3DDevice8Impl,iface);
4598 FIXME("(%p) : stub\n", This); return D3D_OK;
4600 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4601 ICOM_THIS(IDirect3DDevice8Impl,iface);
4602 FIXME("(%p) : stub\n", This); return D3D_OK;
4604 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4605 ICOM_THIS(IDirect3DDevice8Impl,iface);
4606 FIXME("(%p) : stub\n", This); return D3D_OK;
4609 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4610 IDirect3DVertexBuffer8 *oldSrc;
4611 ICOM_THIS(IDirect3DDevice8Impl,iface);
4613 oldSrc = This->StateBlock->stream_source[StreamNumber];
4614 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4616 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4617 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4618 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4619 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4621 /* Handle recording of state blocks */
4622 if (This->isRecordingState) {
4623 TRACE("Recording... not performing anything\n");
4624 return D3D_OK;
4627 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4628 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4629 return D3D_OK;
4631 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4632 ICOM_THIS(IDirect3DDevice8Impl,iface);
4633 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4634 *pStream = This->StateBlock->stream_source[StreamNumber];
4635 *pStride = This->StateBlock->stream_stride[StreamNumber];
4636 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4637 return D3D_OK;
4641 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4643 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4644 IDirect3DDevice8Impl_QueryInterface,
4645 IDirect3DDevice8Impl_AddRef,
4646 IDirect3DDevice8Impl_Release,
4647 IDirect3DDevice8Impl_TestCooperativeLevel,
4648 IDirect3DDevice8Impl_GetAvailableTextureMem,
4649 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4650 IDirect3DDevice8Impl_GetDirect3D,
4651 IDirect3DDevice8Impl_GetDeviceCaps,
4652 IDirect3DDevice8Impl_GetDisplayMode,
4653 IDirect3DDevice8Impl_GetCreationParameters,
4654 IDirect3DDevice8Impl_SetCursorProperties,
4655 IDirect3DDevice8Impl_SetCursorPosition,
4656 IDirect3DDevice8Impl_ShowCursor,
4657 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4658 IDirect3DDevice8Impl_Reset,
4659 IDirect3DDevice8Impl_Present,
4660 IDirect3DDevice8Impl_GetBackBuffer,
4661 IDirect3DDevice8Impl_GetRasterStatus,
4662 IDirect3DDevice8Impl_SetGammaRamp,
4663 IDirect3DDevice8Impl_GetGammaRamp,
4664 IDirect3DDevice8Impl_CreateTexture,
4665 IDirect3DDevice8Impl_CreateVolumeTexture,
4666 IDirect3DDevice8Impl_CreateCubeTexture,
4667 IDirect3DDevice8Impl_CreateVertexBuffer,
4668 IDirect3DDevice8Impl_CreateIndexBuffer,
4669 IDirect3DDevice8Impl_CreateRenderTarget,
4670 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4671 IDirect3DDevice8Impl_CreateImageSurface,
4672 IDirect3DDevice8Impl_CopyRects,
4673 IDirect3DDevice8Impl_UpdateTexture,
4674 IDirect3DDevice8Impl_GetFrontBuffer,
4675 IDirect3DDevice8Impl_SetRenderTarget,
4676 IDirect3DDevice8Impl_GetRenderTarget,
4677 IDirect3DDevice8Impl_GetDepthStencilSurface,
4678 IDirect3DDevice8Impl_BeginScene,
4679 IDirect3DDevice8Impl_EndScene,
4680 IDirect3DDevice8Impl_Clear,
4681 IDirect3DDevice8Impl_SetTransform,
4682 IDirect3DDevice8Impl_GetTransform,
4683 IDirect3DDevice8Impl_MultiplyTransform,
4684 IDirect3DDevice8Impl_SetViewport,
4685 IDirect3DDevice8Impl_GetViewport,
4686 IDirect3DDevice8Impl_SetMaterial,
4687 IDirect3DDevice8Impl_GetMaterial,
4688 IDirect3DDevice8Impl_SetLight,
4689 IDirect3DDevice8Impl_GetLight,
4690 IDirect3DDevice8Impl_LightEnable,
4691 IDirect3DDevice8Impl_GetLightEnable,
4692 IDirect3DDevice8Impl_SetClipPlane,
4693 IDirect3DDevice8Impl_GetClipPlane,
4694 IDirect3DDevice8Impl_SetRenderState,
4695 IDirect3DDevice8Impl_GetRenderState,
4696 IDirect3DDevice8Impl_BeginStateBlock,
4697 IDirect3DDevice8Impl_EndStateBlock,
4698 IDirect3DDevice8Impl_ApplyStateBlock,
4699 IDirect3DDevice8Impl_CaptureStateBlock,
4700 IDirect3DDevice8Impl_DeleteStateBlock,
4701 IDirect3DDevice8Impl_CreateStateBlock,
4702 IDirect3DDevice8Impl_SetClipStatus,
4703 IDirect3DDevice8Impl_GetClipStatus,
4704 IDirect3DDevice8Impl_GetTexture,
4705 IDirect3DDevice8Impl_SetTexture,
4706 IDirect3DDevice8Impl_GetTextureStageState,
4707 IDirect3DDevice8Impl_SetTextureStageState,
4708 IDirect3DDevice8Impl_ValidateDevice,
4709 IDirect3DDevice8Impl_GetInfo,
4710 IDirect3DDevice8Impl_SetPaletteEntries,
4711 IDirect3DDevice8Impl_GetPaletteEntries,
4712 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4713 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4714 IDirect3DDevice8Impl_DrawPrimitive,
4715 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4716 IDirect3DDevice8Impl_DrawPrimitiveUP,
4717 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4718 IDirect3DDevice8Impl_ProcessVertices,
4719 IDirect3DDevice8Impl_CreateVertexShader,
4720 IDirect3DDevice8Impl_SetVertexShader,
4721 IDirect3DDevice8Impl_GetVertexShader,
4722 IDirect3DDevice8Impl_DeleteVertexShader,
4723 IDirect3DDevice8Impl_SetVertexShaderConstant,
4724 IDirect3DDevice8Impl_GetVertexShaderConstant,
4725 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4726 IDirect3DDevice8Impl_GetVertexShaderFunction,
4727 IDirect3DDevice8Impl_SetStreamSource,
4728 IDirect3DDevice8Impl_GetStreamSource,
4729 IDirect3DDevice8Impl_SetIndices,
4730 IDirect3DDevice8Impl_GetIndices,
4731 IDirect3DDevice8Impl_CreatePixelShader,
4732 IDirect3DDevice8Impl_SetPixelShader,
4733 IDirect3DDevice8Impl_GetPixelShader,
4734 IDirect3DDevice8Impl_DeletePixelShader,
4735 IDirect3DDevice8Impl_SetPixelShaderConstant,
4736 IDirect3DDevice8Impl_GetPixelShaderConstant,
4737 IDirect3DDevice8Impl_GetPixelShaderFunction,
4738 IDirect3DDevice8Impl_DrawRectPatch,
4739 IDirect3DDevice8Impl_DrawTriPatch,
4740 IDirect3DDevice8Impl_DeletePatch
4743 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface) {
4744 ICOM_THIS(IDirect3DDevice8Impl,iface);
4745 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4746 #if 0
4747 if (This->glCtx != This->render_ctx) {
4748 glXDestroyContext(This->display, This->render_ctx);
4749 This->render_ctx = This->glCtx;
4751 #endif
4752 if (This->win != This->drawable) {
4753 glXDestroyPbuffer(This->display, This->drawable);
4754 This->drawable = This->win;
4756 #endif
4757 return D3D_OK;
4760 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4761 IDirect3DSurface8* RenderSurface,
4762 IDirect3DSurface8* StencilSurface) {
4765 * Currently only active for GLX >= 1.3
4766 * for others versions we'll have to use GLXPixmaps
4768 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4769 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4770 * so only check OpenGL version
4772 #if defined(GL_VERSION_1_3)
4774 GLXFBConfig* cfgs = NULL;
4775 int nCfgs = 0;
4776 int attribs[256];
4777 int nAttribs = 0;
4778 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4779 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4780 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4781 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4782 IDirect3DSurface8Impl* tmp;
4784 ICOM_THIS(IDirect3DDevice8Impl,iface);
4786 #define PUSH1(att) attribs[nAttribs++] = (att);
4787 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4789 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4790 PUSH2(GLX_X_RENDERABLE, TRUE);
4791 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4793 switch (BackBufferFormat) {
4794 /* color buffer */
4795 case D3DFMT_P8:
4796 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4797 PUSH2(GLX_BUFFER_SIZE, 8);
4798 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4799 break;
4801 case D3DFMT_R3G3B2:
4802 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4803 PUSH2(GLX_RED_SIZE, 3);
4804 PUSH2(GLX_GREEN_SIZE, 3);
4805 PUSH2(GLX_BLUE_SIZE, 2);
4806 break;
4808 case D3DFMT_A1R5G5B5:
4809 PUSH2(GLX_ALPHA_SIZE, 1);
4810 case D3DFMT_X1R5G5B5:
4811 PUSH2(GLX_RED_SIZE, 5);
4812 PUSH2(GLX_GREEN_SIZE, 5);
4813 PUSH2(GLX_BLUE_SIZE, 5);
4814 break;
4816 case D3DFMT_R5G6B5:
4817 PUSH2(GLX_RED_SIZE, 5);
4818 PUSH2(GLX_GREEN_SIZE, 6);
4819 PUSH2(GLX_BLUE_SIZE, 5);
4820 break;
4822 case D3DFMT_A4R4G4B4:
4823 PUSH2(GLX_ALPHA_SIZE, 4);
4824 case D3DFMT_X4R4G4B4:
4825 PUSH2(GLX_RED_SIZE, 4);
4826 PUSH2(GLX_GREEN_SIZE, 4);
4827 PUSH2(GLX_BLUE_SIZE, 4);
4828 break;
4830 case D3DFMT_A8R8G8B8:
4831 PUSH2(GLX_ALPHA_SIZE, 8);
4832 case D3DFMT_R8G8B8:
4833 case D3DFMT_X8R8G8B8:
4834 PUSH2(GLX_RED_SIZE, 8);
4835 PUSH2(GLX_GREEN_SIZE, 8);
4836 PUSH2(GLX_BLUE_SIZE, 8);
4837 break;
4839 default:
4840 break;
4843 switch (StencilBufferFormat) {
4844 case D3DFMT_D16_LOCKABLE:
4845 case D3DFMT_D16:
4846 PUSH2(GLX_DEPTH_SIZE, 16);
4847 break;
4849 case D3DFMT_D15S1:
4850 PUSH2(GLX_DEPTH_SIZE, 15);
4851 break;
4853 case D3DFMT_D24X8:
4854 PUSH2(GLX_DEPTH_SIZE, 24);
4855 break;
4857 case D3DFMT_D24X4S4:
4858 PUSH2(GLX_DEPTH_SIZE, 24);
4859 PUSH2(GLX_STENCIL_SIZE, 4);
4860 break;
4862 case D3DFMT_D24S8:
4863 PUSH2(GLX_DEPTH_SIZE, 24);
4864 PUSH2(GLX_STENCIL_SIZE, 8);
4865 break;
4867 case D3DFMT_D32:
4868 PUSH2(GLX_DEPTH_SIZE, 32);
4869 break;
4871 default:
4872 break;
4875 PUSH1(None);
4877 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4878 if (NULL != cfgs) {
4879 #if 0
4880 int i;
4881 for (i = 0; i < nCfgs; ++i) {
4882 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4884 #endif
4886 if (NULL != This->renderTarget) {
4887 GLenum prev_read;
4888 glFlush();
4889 vcheckGLcall("glFlush");
4891 #if 0
4892 /** very very usefull debug code */
4893 glXSwapBuffers(This->display, This->drawable);
4894 printf("Hit Enter to get next frame ...\n");
4895 getchar();
4896 #endif
4898 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4899 vcheckGLcall("glIntegerv");
4900 glReadBuffer(GL_BACK);
4901 vcheckGLcall("glReadBuffer");
4903 long j;
4904 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4905 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4906 glReadPixels(0,
4907 This->renderTarget->myDesc.Height - j - 1,
4908 This->renderTarget->myDesc.Width,
4910 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4911 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4912 This->renderTarget->allocatedMemory + j * pitch);
4913 vcheckGLcall("glReadPixels");
4916 glReadBuffer(prev_read);
4917 vcheckGLcall("glReadBuffer");
4920 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4921 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4922 nAttribs = 0;
4923 PUSH2(GLX_PBUFFER_WIDTH, Width);
4924 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4925 PUSH1(None);
4926 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4928 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4929 if (NULL == This->render_ctx) {
4930 ERR("cannot create glxContext\n");
4933 glFlush();
4934 glXSwapBuffers(This->display, This->drawable);
4935 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4936 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4938 checkGLcall("glXMakeContextCurrent");
4941 tmp = This->renderTarget;
4942 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4943 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4944 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4946 tmp = This->stencilBufferTarget;
4947 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4948 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4949 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4951 return D3D_OK;
4953 } else {
4954 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4957 #undef PUSH1
4958 #undef PUSH2
4960 #endif
4962 return D3DERR_INVALIDCALL;