- minor COM fixes (fixes some crashes on stupid games)
[wine/testsucceed.git] / dlls / d3d8 / device.c
blob3baae17a3d87f53187779a73f85bc813c6111d54
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <math.h>
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "wine/debug.h"
33 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
34 /*#define GL_GLEXT_PROTOTYPES*/
35 #include "d3d8_private.h"
37 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
38 #undef GL_VERSION_1_4
40 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
42 /* Some #defines for additional diagnostics */
44 /* Per-vertex trace: */
45 #if 0
46 # define VTRACE(A) TRACE A
47 #else
48 # define VTRACE(A)
49 #endif
52 static IDirect3DVertexShaderImpl* VertexShaders[64];
53 static IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
54 static IDirect3DPixelShaderImpl* PixelShaders[64];
56 /* CreateVertexShader can return > 0xFFFF */
57 #define VS_HIGHESTFIXEDFXF 0xF0000000
60 * Utility functions or macros
62 #define conv_mat(mat,gl_mat) \
63 do { \
64 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
65 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
66 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
68 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
69 } while (0)
71 #define VERTEX_SHADER(Handle) \
72 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
73 #define VERTEX_SHADER_DECL(Handle) \
74 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
75 #define PIXEL_SHADER(Handle) \
76 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
78 #define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
82 /* Routine common to the draw primitive and draw indexed primitive routines */
83 void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
84 int PrimitiveType,
85 long NumPrimitives,
86 BOOL isIndexed,
88 /* For Both:*/
89 D3DFORMAT fvf,
90 const void *vertexBufData,
92 /* for Indexed: */
93 long StartVertexIndex,
94 long StartIdx,
95 short idxBytes,
96 const void *idxData,
97 int minIndex) {
99 int NumVertexes = NumPrimitives;
100 IDirect3DVertexShaderImpl* vertex_shader = NULL;
101 BOOL useVertexShaderFunction = FALSE;
103 ICOM_THIS(IDirect3DDevice8Impl,iface);
105 /* Dont understand how to handle multiple streams, but if a fixed
106 FVF is passed in rather than a handle, it must use stream 0 */
108 if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
109 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
110 if (NULL == vertex_shader) {
111 ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
112 return ;
114 if (NULL == vertex_shader->function) {
115 TRACE("vertex shader declared without program, using FVF pure mode\n");
116 } else {
117 useVertexShaderFunction = TRUE;
119 fvf = (D3DFORMAT) This->UpdateStateBlock->vertexShaderDecl->fvf;
120 TRACE("vertex shader declared FVF: %lx\n", This->UpdateStateBlock->vertexShaderDecl->fvf);
121 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
123 /** init Constants */
124 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
125 TRACE("vertex shader init Constant\n");
126 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
132 int skip = This->StateBlock->stream_stride[0];
133 GLenum primType = GL_POINTS;
134 BOOL normal;
135 BOOL isRHW;
136 BOOL isPtSize;
137 BOOL isDiffuse;
138 BOOL isSpecular;
139 int numBlends;
140 BOOL isLastUByte4;
141 int numTextures;
142 int textureNo;
143 const char *curVtx = NULL;
144 const short *pIdxBufS = NULL;
145 const long *pIdxBufL = NULL;
146 const char *curPos;
147 BOOL isLightingOn = FALSE;
148 BOOL enableTexture = FALSE;
149 int vx_index;
151 float x = 0.0f,
152 y = 0.0f,
153 z = 0.0f; /* x,y,z coordinates */
154 float nx = 0.0f,
155 ny =0.0,
156 nz = 0.0f; /* normal x,y,z coordinates */
157 float rhw = 0.0f; /* rhw */
158 float ptSize = 0.0f; /* Point size */
159 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
160 DWORD specularColor = 0; /* Specular Color */
162 ENTER_GL();
164 if (isIndexed) {
165 if (idxBytes == 2) pIdxBufS = (short *) idxData;
166 else pIdxBufL = (long *) idxData;
169 /* Check vertex formats expected ? */
170 /**
171 * FVF parser as seen it
172 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp
174 normal = fvf & D3DFVF_NORMAL;
175 isRHW = fvf & D3DFVF_XYZRHW;
176 isLastUByte4 = fvf & D3DFVF_LASTBETA_UBYTE4;
177 numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */
178 isPtSize = fvf & D3DFVF_PSIZE;
179 isDiffuse = fvf & D3DFVF_DIFFUSE;
180 isSpecular = fvf & D3DFVF_SPECULAR;
181 numTextures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
183 TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d)\n",
184 fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends);
186 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
187 set by the appropriate render state */
188 if (!normal) {
189 isLightingOn = glIsEnabled(GL_LIGHTING);
190 glDisable(GL_LIGHTING);
191 TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
194 if (isRHW) {
195 double height, width, minZ, maxZ;
197 * Already transformed vertex do not need transform
198 * matrices. Reset all matrices to identity.
199 * Leave the default matrix in world mode.
201 glMatrixMode(GL_PROJECTION);
202 checkGLcall("glMatrixMode");
203 glLoadIdentity();
204 checkGLcall("glLoadIdentity");
205 glMatrixMode(GL_MODELVIEW);
206 checkGLcall("glMatrixMode");
207 glLoadIdentity();
208 checkGLcall("glLoadIdentity");
209 height = This->StateBlock->viewport.Height;
210 width = This->StateBlock->viewport.Width;
211 minZ = This->StateBlock->viewport.MinZ;
212 maxZ = This->StateBlock->viewport.MaxZ;
213 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
214 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
215 checkGLcall("glOrtho");
216 } else {
217 glMatrixMode(GL_PROJECTION);
218 checkGLcall("glMatrixMode");
219 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
220 checkGLcall("glLoadMatrixf");
221 glMatrixMode(GL_MODELVIEW);
222 checkGLcall("glMatrixMode");
223 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
224 checkGLcall("glLoadMatrixf");
225 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
226 checkGLcall("glMultMatrixf");
229 /* Set OpenGL to the appropriate Primitive Type */
230 switch (PrimitiveType) {
231 case D3DPT_POINTLIST:
232 TRACE("POINTS\n");
233 primType = GL_POINTS;
234 NumVertexes = NumPrimitives;
235 break;
237 case D3DPT_LINELIST:
238 TRACE("LINES\n");
239 primType = GL_LINES;
240 NumVertexes = NumPrimitives * 2;
241 break;
243 case D3DPT_LINESTRIP:
244 TRACE("LINE_STRIP\n");
245 primType = GL_LINE_STRIP;
246 NumVertexes = NumPrimitives + 1;
247 break;
249 case D3DPT_TRIANGLELIST:
250 TRACE("TRIANGLES\n");
251 primType = GL_TRIANGLES;
252 NumVertexes = NumPrimitives * 3;
253 break;
255 case D3DPT_TRIANGLESTRIP:
256 TRACE("TRIANGLE_STRIP\n");
257 primType = GL_TRIANGLE_STRIP;
258 NumVertexes = NumPrimitives + 2;
259 break;
261 case D3DPT_TRIANGLEFAN:
262 TRACE("TRIANGLE_FAN\n");
263 primType = GL_TRIANGLE_FAN;
264 NumVertexes = NumPrimitives + 2;
265 break;
267 default:
268 FIXME("Unhandled primitive\n");
269 break;
272 /* Fixme, Ideally, only use this per-vertex code for software HAL
273 but until opengl supports all the functions returned to setup
274 vertex arrays, we need to drop down to the slow mechanism for
275 certain functions */
277 if (isPtSize || isDiffuse || useVertexShaderFunction==TRUE || (numBlends > 0)) {
278 TRACE("Using slow per-vertex code\n");
280 /* Enable this one to be able to debug what is going on, but it is slower
281 than the pointer/array version */
282 VTRACE(("glBegin(%x)\n", primType));
283 glBegin(primType);
285 /* Draw the primitives */
286 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
288 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
290 if (!isIndexed) {
291 curPos = curVtx;
292 } else {
293 if (idxBytes == 2) {
294 VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
295 curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
296 } else {
297 VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
298 curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
302 /* Work through the vertex buffer */
303 x = *(float *)curPos;
304 curPos = curPos + sizeof(float);
305 y = *(float *)curPos;
306 curPos = curPos + sizeof(float);
307 z = *(float *)curPos;
308 curPos = curPos + sizeof(float);
309 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
311 /* RHW follows, only if transformed */
312 if (isRHW) {
313 rhw = *(float *)curPos;
314 curPos = curPos + sizeof(float);
315 VTRACE(("rhw=%f\n", rhw));
318 /* Blending data */
319 if (numBlends > 0) {
320 UINT i;
321 D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
322 DWORD skippedBlendLastUByte4 = 0;
324 for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
325 ((float*)&skippedBlend)[i] = *(float *)curPos;
326 curPos = curPos + sizeof(float);
329 if (isLastUByte4) {
330 skippedBlendLastUByte4 = *(DWORD*)curPos;
331 curPos = curPos + sizeof(DWORD);
335 /* Vertex Normal Data (untransformed only) */
336 if (normal) {
337 nx = *(float *)curPos;
338 curPos = curPos + sizeof(float);
339 ny = *(float *)curPos;
340 curPos = curPos + sizeof(float);
341 nz = *(float *)curPos;
342 curPos = curPos + sizeof(float);
343 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
346 if (isPtSize) {
347 ptSize = *(float *)curPos;
348 VTRACE(("ptSize=%f\n", ptSize));
349 curPos = curPos + sizeof(float);
352 if (isDiffuse) {
353 diffuseColor = *(DWORD *)curPos;
354 VTRACE(("diffuseColor=%lx\n", diffuseColor));
355 curPos = curPos + sizeof(DWORD);
358 if (isSpecular) {
359 specularColor = *(DWORD *)curPos;
360 VTRACE(("specularColor=%lx\n", specularColor));
361 curPos = curPos + sizeof(DWORD);
364 /* ToDo: Texture coords */
365 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
366 float s, t, r, q;
368 if (!(This->isMultiTexture) && textureNo > 0) {
369 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
370 continue ;
372 if (textureNo > This->TextureUnits) {
373 FIXME("Program using more concurrent textures than this opengl implementation support\n");
374 break ;
377 /* Query tex coords */
378 if (This->StateBlock->textures[textureNo] != NULL) {
379 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
380 case D3DRTYPE_TEXTURE:
381 s = *(float *)curPos;
382 curPos = curPos + sizeof(float);
383 t = *(float *)curPos;
384 curPos = curPos + sizeof(float);
385 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s,t));
387 if (TRUE == useVertexShaderFunction) {
388 /* Nothing to do */
389 } else {
390 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
391 VTRACE("Skip tex coords, as being system generated\n");
392 } else {
394 if (This->isMultiTexture) {
395 #if defined(GL_VERSION_1_3)
396 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
397 #else
398 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
399 #endif
400 } else {
401 glTexCoord2f(s, t);
406 break;
408 case D3DRTYPE_VOLUMETEXTURE:
409 s = *(float *)curPos;
410 curPos = curPos + sizeof(float);
411 t = *(float *)curPos;
412 curPos = curPos + sizeof(float);
413 r = *(float *)curPos;
414 curPos = curPos + sizeof(float);
415 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r));
417 if (TRUE == useVertexShaderFunction) {
418 /* Nothing to do */
419 } else {
420 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
421 VTRACE("Skip tex coords, as being system generated\n");
422 } else {
423 if (This->isMultiTexture) {
424 #if defined(GL_VERSION_1_3)
425 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
426 #else
427 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
428 #endif
429 } else {
430 glTexCoord3f(s, t, r);
434 break;
436 default:
437 r = 0.0f; q = 0.0f; /* Avoid compiler warnings, need these vars later for other textures */
438 FIXME("Unhandled texture type\n");
440 } else {
441 /* Note I have seen a program actually do this, so just hide it and continue */
442 VTRACE(("Very odd - texture requested in FVF but not bound!\n"));
447 /** if vertex shader program specified ... using it */
448 if (TRUE == useVertexShaderFunction) {
451 * this code must become the really
452 * vs input params init
454 * because its possible to use input registers for anything
455 * and some samples use registers for other things than they are
456 * declared
459 /**
460 * no really valid declaration, user defined input register use
461 * so fill input registers as described in vertex shader declaration
463 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
464 (!isIndexed) ? (vx_index * skip) :
465 (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) :
466 ((pIdxBufL[StartIdx + vx_index]) * skip));
468 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
469 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
471 TRACE_VECTOR(vertex_shader->output.oPos);
472 TRACE_VECTOR(vertex_shader->output.oD[0]);
473 TRACE_VECTOR(vertex_shader->output.oD[1]);
474 TRACE_VECTOR(vertex_shader->output.oT[0]);
475 TRACE_VECTOR(vertex_shader->output.oT[1]);
476 TRACE_VECTOR(vertex_shader->input.V[0]);
477 TRACE_VECTOR(vertex_shader->data->C[0]);
478 TRACE_VECTOR(vertex_shader->data->C[1]);
479 TRACE_VECTOR(vertex_shader->data->C[2]);
480 TRACE_VECTOR(vertex_shader->data->C[3]);
481 TRACE_VECTOR(vertex_shader->data->C[4]);
482 TRACE_VECTOR(vertex_shader->data->C[5]);
483 TRACE_VECTOR(vertex_shader->data->C[6]);
484 TRACE_VECTOR(vertex_shader->data->C[7]);
486 x = vertex_shader->output.oPos.x;
487 y = vertex_shader->output.oPos.y;
488 z = vertex_shader->output.oPos.z;
490 if (1.0f != vertex_shader->output.oPos.w || isRHW) {
491 rhw = vertex_shader->output.oPos.w;
493 /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
494 glColor4fv((float*) &vertex_shader->output.oD[0]);
496 /* Requires secondary color extensions to compile... */
497 #if defined(GL_VERSION_1_4)
498 glSecondaryColor3fv((float*) &vertex_shader->output.oD[1]);
499 checkGLcall("glSecondaryColor3fv");
500 #else
501 if (checkGLSupport(EXT_SECONDARY_COLOR)) {
502 /*specularColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[1]);*/
503 /*GLExtCall(glSecondaryColor3fvEXT)((float*) &vertex_shader->output.oD[1]);*/
504 /*checkGLcall("glSecondaryColor3fvEXT");*/
506 #endif
507 /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
508 for (textureNo = 0; textureNo < 4; ++textureNo) {
509 float s, t, r, q;
511 if (!(This->isMultiTexture) && textureNo > 0) {
512 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
513 continue ;
515 /* Query tex coords */
516 if (This->StateBlock->textures[textureNo] != NULL) {
517 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
518 case D3DRTYPE_TEXTURE:
519 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
520 s = vertex_shader->output.oT[textureNo].x;
521 t = vertex_shader->output.oT[textureNo].y;
522 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
523 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
524 VTRACE("Skip tex coords, as being system generated\n");
525 } else {
526 if (This->isMultiTexture) {
527 #if defined(GL_VERSION_1_3)
528 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
529 #else
530 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
531 #endif
532 /*checkGLcall("glMultiTexCoord2fARB");*/
533 } else {
534 glTexCoord2f(s, t);
535 /*checkGLcall("gTexCoord2f");*/
538 break;
540 case D3DRTYPE_VOLUMETEXTURE:
541 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
542 s = vertex_shader->output.oT[textureNo].x;
543 t = vertex_shader->output.oT[textureNo].y;
544 r = vertex_shader->output.oT[textureNo].z;
545 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
546 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
547 VTRACE("Skip tex coords, as being system generated\n");
548 } else {
549 if (This->isMultiTexture) {
550 #if defined(GL_VERSION_1_3)
551 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
552 #else
553 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
554 #endif
555 /*checkGLcall("glMultiTexCoord2fARB");*/
556 } else {
557 glTexCoord3f(s, t, r);
558 /*checkGLcall("gTexCoord3f");*/
561 break;
563 default:
564 /* Avoid compiler warnings, need these vars later for other textures */
565 r = 0.0f; q = 0.0f;
566 FIXME("Unhandled texture type\n");
571 if (1.0f == rhw || rhw < 0.01f) {
572 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
573 glVertex3f(x, y, z);
574 /*checkGLcall("glVertex3f");*/
575 } else {
576 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
577 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
578 /*checkGLcall("glVertex4f");*/
580 } else {
581 /**
582 * FALSE == useVertexShaderFunction
583 * using std FVF code
586 /* Handle these vertexes */
587 if (isDiffuse) {
588 glColor4ub((diffuseColor >> 16) & 0xFF,
589 (diffuseColor >> 8) & 0xFF,
590 (diffuseColor >> 0) & 0xFF,
591 (diffuseColor >> 24) & 0xFF);
592 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
593 ((diffuseColor >> 16) & 0xFF) / 255.0f,
594 ((diffuseColor >> 8) & 0xFF) / 255.0f,
595 ((diffuseColor >> 0) & 0xFF) / 255.0f,
596 ((diffuseColor >> 24) & 0xFF) / 255.0f));
599 if (normal) {
600 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
601 glNormal3f(nx, ny, nz);
602 glVertex3f(x, y, z);
603 } else {
604 if (1.0f == rhw || rhw < 0.01f) {
605 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
606 glVertex3f(x, y, z);
607 } else {
608 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
609 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
614 if (!isIndexed) {
615 curVtx = curVtx + skip;
619 glEnd();
620 checkGLcall("glEnd and previous calls");
622 } else {
623 TRACE("Using fast vertex array code\n");
625 /* Faster version, harder to debug */
626 /* Shuffle to the beginning of the vertexes to render and index from there */
627 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
628 curPos = curVtx;
630 /* Set up the vertex pointers */
631 if (isRHW) {
632 glVertexPointer(4, GL_FLOAT, skip, curPos);
633 checkGLcall("glVertexPointer(4, ...)");
634 curPos += 4 * sizeof(float);
635 } else {
636 glVertexPointer(3, GL_FLOAT, skip, curPos);
637 checkGLcall("glVertexPointer(3, ...)");
638 curPos += 3 * sizeof(float);
640 glEnableClientState(GL_VERTEX_ARRAY);
641 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
643 if (numBlends > 0) {
644 /* no such functionality in the fixed function GL pipeline */
645 /* FIXME: Wont get here as will drop to slow method */
646 /* FIXME("Cannot handle blending data here in openGl\n");*/
647 if (checkGLSupport(ARB_VERTEX_BLEND)) {
648 FIXME("TODO\n");
649 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
650 FIXME("TODO\n");
652 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
653 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
654 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
655 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
657 curPos += numBlends * sizeof(float);
658 } else {
659 FIXME("unsupported blending in openGl\n");
661 } else {
662 if (checkGLSupport(ARB_VERTEX_BLEND)) {
663 FIXME("TODO\n");
664 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
665 FIXME("TODO\n");
667 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
668 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
674 if (normal) {
675 glNormalPointer(GL_FLOAT, skip, curPos);
676 checkGLcall("glNormalPointer");
677 glEnableClientState(GL_NORMAL_ARRAY);
678 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
679 curPos += 3 * sizeof(float);
680 } else {
681 glDisableClientState(GL_NORMAL_ARRAY);
682 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
683 glNormal3f(0, 0, 1);
684 checkGLcall("glNormal3f(0, 0, 1)");
687 if (isPtSize) {
688 /* no such functionality in the fixed function GL pipeline */
689 /* FIXME: Wont get here as will drop to slow method */
690 FIXME("Cannot change ptSize here in openGl\n");
691 curPos = curPos + sizeof(float);
694 if (isDiffuse) {
695 glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
696 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
697 glEnableClientState(GL_COLOR_ARRAY);
698 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
699 curPos += sizeof(DWORD);
701 else {
702 glDisableClientState(GL_COLOR_ARRAY);
703 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
704 glColor4f(1, 1, 1, 1);
705 checkGLcall("glColor4f(1, 1, 1, 1)");
708 /* Requires secondary color extensions to compile... */
709 if (isSpecular) {
710 #if defined(GL_VERSION_1_4)
711 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
712 checkGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos)");
713 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
714 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
715 #else
716 # if 0
717 /* FIXME: check for GL_EXT_secondary_color */
718 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos);
719 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
720 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
721 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
722 # endif
723 #endif
724 curPos += sizeof(DWORD);
725 } else {
726 #if defined(GL_VERSION_1_4)
727 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
728 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
729 glSecondaryColor3f(0, 0, 0);
730 checkGLcall("glSecondaryColor3f(0, 0, 0)");
731 #else
732 #if 0
733 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
734 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
735 glSecondaryColor3fEXT(0, 0, 0);
736 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
737 #endif
738 #endif
742 /* ToDo: Texture coords */
743 for (textureNo = 0;textureNo<numTextures; textureNo++) {
745 /* Query tex coords */
746 #if defined(GL_VERSION_1_3)
747 glClientActiveTexture(GL_TEXTURE0 + textureNo);
748 #else
749 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
750 #endif
751 if (This->StateBlock->textures[textureNo] != NULL) {
752 enableTexture = TRUE;
753 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
754 case D3DRTYPE_TEXTURE:
755 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
756 VTRACE("Skip tex coords, as being system generated\n");
757 } else {
758 glTexCoordPointer(2, GL_FLOAT, skip, curPos);
759 checkGLcall("glTexCoordPointer(2, ...)");
761 curPos += 2*sizeof(float);
762 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
763 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
764 break;
766 case D3DRTYPE_VOLUMETEXTURE:
767 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
768 VTRACE("Skip tex coords, as being system generated\n");
769 } else {
770 glTexCoordPointer(3, GL_FLOAT, skip, curPos);
771 checkGLcall("glTexCoordPointer(3, ...)");
773 curPos += 3*sizeof(float);
774 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
775 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
776 break;
778 default:
779 FIXME("Unhandled texture type\n");
780 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
781 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
784 } else {
786 /* Note I have seen a program actually do this, so just hide it and continue */
787 TRACE("Very odd - texture requested in FVF but not bound!\n");
788 #if defined(GL_VERSION_1_3)
789 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
790 checkGLcall("glMultiTexCoord4f(... , 0, 0, 0, 1)");
791 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
792 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
793 #else
794 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
795 checkGLcall("glMultiTexCoord4fARB(... , 0, 0, 0, 1)");
796 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
797 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
798 #endif
803 /* Finally do the drawing */
804 if (isIndexed) {
806 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
807 if (idxBytes==2) {
808 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
809 glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
810 (char *)idxData+(2 * StartIdx));
811 #else
812 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
813 GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
814 #endif
815 } else {
816 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
817 glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
818 (char *)idxData+(4 * StartIdx));
819 #else
820 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
821 GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
822 #endif
824 checkGLcall("glDrawRangeElements");
826 } else {
828 /* Note first is now zero as we shuffled along earlier */
829 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
830 glDrawArrays(primType, 0, NumVertexes);
831 checkGLcall("glDrawArrays");
836 /* If no normals, restore previous lighting state */
837 if (!normal) {
838 if (isLightingOn) glEnable(GL_LIGHTING);
839 else glDisable(GL_LIGHTING);
840 TRACE("Restored lighting to original state\n");
844 LEAVE_GL();
846 TRACE("glEnd\n");
850 Simple utility routines used for dx -> gl mapping of byte formats
852 SHORT bytesPerPixel(D3DFORMAT fmt) {
853 SHORT retVal;
855 switch (fmt) {
856 /* color buffer */
857 case D3DFMT_A4R4G4B4: retVal = 2; break;
858 case D3DFMT_A8R8G8B8: retVal = 4; break;
859 case D3DFMT_X8R8G8B8: retVal = 4; break;
860 case D3DFMT_R8G8B8: retVal = 3; break;
861 case D3DFMT_R5G6B5: retVal = 2; break;
862 case D3DFMT_A1R5G5B5: retVal = 2; break;
863 /* depth/stencil buffer */
864 case D3DFMT_D16_LOCKABLE: retVal = 2; break;
865 case D3DFMT_D32: retVal = 4; break;
866 case D3DFMT_D15S1: retVal = 2; break;
867 case D3DFMT_D24S8: retVal = 4; break;
868 case D3DFMT_D16: retVal = 2; break;
869 case D3DFMT_D24X8: retVal = 4; break;
870 case D3DFMT_D24X4S4: retVal = 4; break;
871 /* unknown */
872 case D3DFMT_UNKNOWN:
873 /* Guess at the highest value of the above */
874 TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %d\n", fmt);
875 retVal = 4;
876 break;
877 default:
878 FIXME("Unhandled fmt %d\n", fmt);
879 retVal = 4;
881 TRACE("bytes/Pxl for fmt %d = %d\n", fmt, retVal);
882 return retVal;
885 GLint fmt2glintFmt(D3DFORMAT fmt) {
886 GLint retVal;
888 switch (fmt) {
889 case D3DFMT_A4R4G4B4: retVal = GL_RGBA4; break;
890 case D3DFMT_A8R8G8B8: retVal = GL_RGBA8; break;
891 case D3DFMT_X8R8G8B8: retVal = GL_RGB8; break;
892 case D3DFMT_R8G8B8: retVal = GL_RGB8; break;
893 case D3DFMT_R5G6B5: retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
894 case D3DFMT_A1R5G5B5: retVal = GL_RGB5_A1; break;
895 default:
896 FIXME("Unhandled fmt %d\n", fmt);
897 retVal = 4;
899 TRACE("fmt2glintFmt for fmt %d = %x\n", fmt, retVal);
900 return retVal;
902 GLenum fmt2glFmt(D3DFORMAT fmt) {
903 GLenum retVal;
905 switch (fmt) {
906 case D3DFMT_A4R4G4B4: retVal = GL_BGRA; break;
907 case D3DFMT_A8R8G8B8: retVal = GL_BGRA; break;
908 case D3DFMT_X8R8G8B8: retVal = GL_BGRA; break;
909 case D3DFMT_R8G8B8: retVal = GL_BGR; break;
910 case D3DFMT_R5G6B5: retVal = GL_RGB; break;
911 case D3DFMT_A1R5G5B5: retVal = GL_BGRA; break;
912 default:
913 FIXME("Unhandled fmt %d\n", fmt);
914 retVal = 4;
916 TRACE("fmt2glFmt for fmt %d = %x\n", fmt, retVal);
917 return retVal;
919 DWORD fmt2glType(D3DFORMAT fmt) {
920 GLenum retVal;
922 switch (fmt) {
923 case D3DFMT_A4R4G4B4: retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
924 case D3DFMT_A8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
925 case D3DFMT_X8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
926 case D3DFMT_R5G6B5: retVal = GL_UNSIGNED_SHORT_5_6_5_REV; break;
927 case D3DFMT_R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
928 case D3DFMT_A1R5G5B5: retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
929 default:
930 FIXME("Unhandled fmt %d\n", fmt);
931 retVal = 4;
933 TRACE("fmt2glType for fmt %d = %x\n", fmt, retVal);
934 return retVal;
937 int SOURCEx_RGB_EXT(DWORD arg) {
938 switch(arg) {
939 case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
940 case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
941 case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
942 case D3DTSS_ALPHAARG0:
943 case D3DTSS_ALPHAARG1:
944 case D3DTSS_ALPHAARG2:
945 default:
946 FIXME("Invalid arg %ld\n", arg);
947 return GL_SOURCE0_RGB_EXT;
950 int OPERANDx_RGB_EXT(DWORD arg) {
951 switch(arg) {
952 case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
953 case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
954 case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
955 case D3DTSS_ALPHAARG0:
956 case D3DTSS_ALPHAARG1:
957 case D3DTSS_ALPHAARG2:
958 default:
959 FIXME("Invalid arg %ld\n", arg);
960 return GL_OPERAND0_RGB_EXT;
963 int SOURCEx_ALPHA_EXT(DWORD arg) {
964 switch(arg) {
965 case D3DTSS_ALPHAARG0: return GL_SOURCE2_ALPHA_EXT;
966 case D3DTSS_ALPHAARG1: return GL_SOURCE0_ALPHA_EXT;
967 case D3DTSS_ALPHAARG2: return GL_SOURCE1_ALPHA_EXT;
968 case D3DTSS_COLORARG0:
969 case D3DTSS_COLORARG1:
970 case D3DTSS_COLORARG2:
971 default:
972 FIXME("Invalid arg %ld\n", arg);
973 return GL_SOURCE0_ALPHA_EXT;
976 int OPERANDx_ALPHA_EXT(DWORD arg) {
977 switch(arg) {
978 case D3DTSS_ALPHAARG0: return GL_OPERAND2_ALPHA_EXT;
979 case D3DTSS_ALPHAARG1: return GL_OPERAND0_ALPHA_EXT;
980 case D3DTSS_ALPHAARG2: return GL_OPERAND1_ALPHA_EXT;
981 case D3DTSS_COLORARG0:
982 case D3DTSS_COLORARG1:
983 case D3DTSS_COLORARG2:
984 default:
985 FIXME("Invalid arg %ld\n", arg);
986 return GL_OPERAND0_ALPHA_EXT;
989 GLenum StencilOp(DWORD op) {
990 switch(op) {
991 case D3DSTENCILOP_KEEP : return GL_KEEP;
992 case D3DSTENCILOP_ZERO : return GL_ZERO;
993 case D3DSTENCILOP_REPLACE : return GL_REPLACE;
994 case D3DSTENCILOP_INCRSAT : return GL_INCR;
995 case D3DSTENCILOP_DECRSAT : return GL_DECR;
996 case D3DSTENCILOP_INVERT : return GL_INVERT;
997 case D3DSTENCILOP_INCR : FIXME("Unsupported stencil op D3DSTENCILOP_INCR\n");
998 return GL_INCR; /* Fixme - needs to support wrap */
999 case D3DSTENCILOP_DECR : FIXME("Unsupported stencil op D3DSTENCILOP_DECR\n");
1000 return GL_DECR; /* Fixme - needs to support wrap */
1001 default:
1002 FIXME("Invalid stencil op %ld\n", op);
1003 return GL_ALWAYS;
1008 * @nodoc: todo
1010 void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand)
1012 BOOL isAlphaReplicate = FALSE;
1013 BOOL isComplement = FALSE;
1015 *operand = GL_SRC_COLOR;
1016 *source = GL_TEXTURE;
1018 /* Catch alpha replicate */
1019 if (iValue & D3DTA_ALPHAREPLICATE) {
1020 iValue = iValue & ~D3DTA_ALPHAREPLICATE;
1021 isAlphaReplicate = TRUE;
1024 /* Catch Complement */
1025 if (iValue & D3DTA_COMPLEMENT) {
1026 iValue = iValue & ~D3DTA_COMPLEMENT;
1027 isComplement = TRUE;
1030 /* Calculate the operand */
1031 if (isAlphaReplicate && !isComplement) {
1032 *operand = GL_SRC_ALPHA;
1033 } else if (isAlphaReplicate && isComplement) {
1034 *operand = GL_ONE_MINUS_SRC_ALPHA;
1035 } else if (isComplement) {
1036 if (isAlphaArg) {
1037 *operand = GL_ONE_MINUS_SRC_ALPHA;
1038 } else {
1039 *operand = GL_ONE_MINUS_SRC_COLOR;
1041 } else {
1042 if (isAlphaArg) {
1043 *operand = GL_SRC_ALPHA;
1044 } else {
1045 *operand = GL_SRC_COLOR;
1049 /* Calculate the source */
1050 switch (iValue & D3DTA_SELECTMASK) {
1051 case D3DTA_CURRENT: *source = GL_PREVIOUS_EXT;
1052 break;
1053 case D3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT;
1054 break;
1055 case D3DTA_TEXTURE: *source = GL_TEXTURE;
1056 break;
1057 case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT;
1058 break;
1059 case D3DTA_SPECULAR:
1061 * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
1062 * isnt supported until base GL supports it
1063 * There is no concept of temp registers as far as I can tell
1066 default:
1067 FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
1068 *source = GL_TEXTURE;
1073 /* Apply the current values to the specified texture stage */
1074 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
1075 ICOM_THIS(IDirect3DDevice8Impl,iface);
1076 int i=0;
1077 float col[4];
1079 /* Make appropriate texture active */
1080 if (This->isMultiTexture) {
1081 #if defined(GL_VERSION_1_3)
1082 glActiveTexture(GL_TEXTURE0 + Stage);
1083 #else
1084 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1085 #endif
1086 checkGLcall("glActiveTextureARB");
1087 } else if (Stage > 0) {
1088 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1091 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
1092 for (i=1; i<HIGHEST_TEXTURE_STATE; i++) {
1093 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1096 /* Note the D3DRS value applies to all textures, but GL has one
1097 per texture, so apply it now ready to be used! */
1098 col[0] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR]>> 16) & 0xFF) / 255.0;
1099 col[1] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 8 ) & 0xFF) / 255.0;
1100 col[2] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 0 ) & 0xFF) / 255.0;
1101 col[3] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 24 ) & 0xFF) / 255.0;
1102 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1103 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1105 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1108 /* IDirect3D IUnknown parts follow: */
1109 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1111 ICOM_THIS(IDirect3DDevice8Impl,iface);
1113 if (IsEqualGUID(riid, &IID_IUnknown)
1114 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1115 IDirect3DDevice8Impl_AddRef(iface);
1116 *ppobj = This;
1117 return D3D_OK;
1120 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1121 return E_NOINTERFACE;
1124 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1125 ICOM_THIS(IDirect3DDevice8Impl,iface);
1126 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1127 return ++(This->ref);
1130 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1131 ICOM_THIS(IDirect3DDevice8Impl,iface);
1132 ULONG ref = --This->ref;
1133 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1134 if (ref == 0) {
1135 HeapFree(GetProcessHeap(), 0, This);
1137 return ref;
1140 /* IDirect3DDevice Interface follow: */
1141 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1142 ICOM_THIS(IDirect3DDevice8Impl,iface);
1143 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
1144 return D3D_OK;
1147 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1148 ICOM_THIS(IDirect3DDevice8Impl,iface);
1149 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1151 * pretend we have 32MB of any type of memory queried.
1153 return (1024*1024*32);
1156 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1157 ICOM_THIS(IDirect3DDevice8Impl,iface);
1158 FIXME("(%p) : stub\n", This); return D3D_OK;
1160 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1161 ICOM_THIS(IDirect3DDevice8Impl,iface);
1162 TRACE("(%p) : returning %p\n", This, This->direct3d8);
1164 /* Inc ref count */
1165 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1167 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1168 return D3D_OK;
1170 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1171 ICOM_THIS(IDirect3DDevice8Impl,iface);
1172 FIXME("(%p) : stub, calling idirect3d for now\n", This);
1173 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1174 return D3D_OK;
1176 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1178 HDC hdc;
1179 int bpp = 0;
1181 ICOM_THIS(IDirect3DDevice8Impl,iface);
1182 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
1183 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
1184 pMode->RefreshRate = 85; /*FIXME: How to identify? */
1186 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1187 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1188 DeleteDC(hdc);
1190 switch (bpp) {
1191 case 8: pMode->Format = D3DFMT_R8G8B8; break;
1192 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1193 case 24: pMode->Format = D3DFMT_R8G8B8; break;
1194 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1195 default:
1196 FIXME("Unrecognized display mode format\n");
1197 pMode->Format = D3DFMT_UNKNOWN;
1200 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%d)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format);
1201 return D3D_OK;
1203 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1204 ICOM_THIS(IDirect3DDevice8Impl,iface);
1205 TRACE("(%p) copying to %p\n", This, pParameters);
1206 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1207 return D3D_OK;
1209 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1210 ICOM_THIS(IDirect3DDevice8Impl,iface);
1211 FIXME("(%p) : stub\n", This); return D3D_OK;
1213 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace,DWORD Flags) {
1214 ICOM_THIS(IDirect3DDevice8Impl,iface);
1215 FIXME("(%p) : stub\n", This); return;
1217 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1218 ICOM_THIS(IDirect3DDevice8Impl,iface);
1219 FIXME("(%p) : stub\n", This); return D3D_OK;
1221 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1222 ICOM_THIS(IDirect3DDevice8Impl,iface);
1223 FIXME("(%p) : stub\n", This);
1224 *pSwapChain = NULL;
1225 return D3D_OK;
1227 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1228 ICOM_THIS(IDirect3DDevice8Impl,iface);
1229 FIXME("(%p) : stub\n", This); return D3D_OK;
1231 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1232 ICOM_THIS(IDirect3DDevice8Impl,iface);
1233 TRACE("(%p) : complete stub!\n", This);
1235 ENTER_GL();
1237 glXSwapBuffers(This->display, This->win);
1238 checkGLcall("glXSwapBuffers");
1240 LEAVE_GL();
1242 return D3D_OK;
1244 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
1245 ICOM_THIS(IDirect3DDevice8Impl,iface);
1246 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1247 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1249 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
1250 FIXME("Only one backBuffer currently supported\n");
1251 return D3DERR_INVALIDCALL;
1254 /* Note inc ref on returned surface */
1255 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1257 return D3D_OK;
1259 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1260 ICOM_THIS(IDirect3DDevice8Impl,iface);
1261 FIXME("(%p) : stub\n", This);
1262 return D3D_OK;
1264 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags,CONST D3DGAMMARAMP* pRamp) {
1265 ICOM_THIS(IDirect3DDevice8Impl,iface);
1266 FIXME("(%p) : stub\n", This); return;
1268 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1269 ICOM_THIS(IDirect3DDevice8Impl,iface);
1270 FIXME("(%p) : stub\n", This); return;
1272 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1273 D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture8** ppTexture) {
1274 IDirect3DTexture8Impl *object;
1275 int i;
1276 UINT tmpW;
1277 UINT tmpH;
1279 ICOM_THIS(IDirect3DDevice8Impl,iface);
1281 /* Allocate the storage for the device */
1282 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool);
1283 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1284 object->lpVtbl = &Direct3DTexture8_Vtbl;
1285 object->Device = This; /* FIXME: AddRef(This) */
1286 object->ResourceType = D3DRTYPE_TEXTURE;
1287 object->ref = 1;
1288 object->width = Width;
1289 object->height = Height;
1290 object->levels = Levels;
1291 object->usage = Usage;
1292 object->format = Format;
1293 object->device = This;
1294 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->device);*/
1296 /* Calculate levels for mip mapping */
1297 if (Levels == 0) {
1298 object->levels++;
1299 tmpW = Width;
1300 tmpH = Height;
1301 while (tmpW > 1 && tmpH > 1) {
1302 tmpW = max(1,tmpW / 2);
1303 tmpH = max(1, tmpH / 2);
1304 object->levels++;
1306 TRACE("Calculated levels = %d\n", object->levels);
1309 /* Generate all the surfaces */
1310 tmpW = Width;
1311 tmpH = Height;
1312 for (i=0; i<object->levels; i++)
1314 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1315 object->surfaces[i]->Container = (IUnknown*) object;
1316 /*IUnknown_AddRef(object->surfaces[i]->Container);*/
1317 object->surfaces[i]->myDesc.Usage = Usage;
1318 object->surfaces[i]->myDesc.Pool = Pool ;
1320 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1321 tmpW = max(1, tmpW / 2);
1322 tmpH = max(1, tmpH / 2);
1325 *ppTexture = (LPDIRECT3DTEXTURE8)object;
1326 return D3D_OK;
1328 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture) {
1330 IDirect3DVolumeTexture8Impl *object;
1331 int i;
1332 UINT tmpW;
1333 UINT tmpH;
1334 UINT tmpD;
1336 ICOM_THIS(IDirect3DDevice8Impl,iface);
1338 /* Allocate the storage for it */
1339 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Depth, Levels, Usage, Format, Pool);
1340 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1341 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1342 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1343 object->Device = This;
1344 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1345 object->ref = 1;
1347 object->width = Width;
1348 object->height = Height;
1349 object->depth = Depth;
1350 object->levels = Levels;
1351 object->usage = Usage;
1352 object->format = Format;
1354 /* Calculate levels for mip mapping */
1355 if (Levels == 0) {
1356 object->levels++;
1357 tmpW = Width;
1358 tmpH = Height;
1359 tmpD = Depth;
1360 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1361 tmpW = max(1, tmpW / 2);
1362 tmpH = max(1, tmpH / 2);
1363 tmpD = max(1, tmpD / 2);
1364 object->levels++;
1366 TRACE("Calculated levels = %d\n", object->levels);
1369 /* Generate all the surfaces */
1370 tmpW = Width;
1371 tmpH = Height;
1372 tmpD = Depth;
1374 for (i = 0; i< object->levels; i++)
1376 IDirect3DVolume8Impl *volume;
1378 /* Create the volume - No entry point for this seperately?? */
1379 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1380 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1382 volume->lpVtbl = &Direct3DVolume8_Vtbl;
1383 volume->Device = This;
1384 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) volume->Device);*/
1385 volume->ResourceType = D3DRTYPE_VOLUME;
1386 volume->Container = (IUnknown*) object;
1387 /*IUnknown_AddRef(volume->Container);*/
1388 volume->ref = 1;
1390 volume->myDesc.Width = Width;
1391 volume->myDesc.Height= Height;
1392 volume->myDesc.Depth = Depth;
1393 volume->myDesc.Format= Format;
1394 volume->myDesc.Type = D3DRTYPE_VOLUME;
1395 volume->myDesc.Pool = Pool;
1396 volume->myDesc.Usage = Usage;
1397 volume->bytesPerPixel = bytesPerPixel(Format);
1398 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
1399 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1401 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Depth, Format,
1402 volume, volume->allocatedMemory, volume->myDesc.Size);
1404 tmpW = max(1,tmpW / 2);
1405 tmpH = max(1, tmpH / 2);
1406 tmpD = max(1, tmpD / 2);
1409 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8)object;
1410 return D3D_OK;
1412 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture8** ppCubeTexture) {
1414 IDirect3DCubeTexture8Impl *object;
1415 ICOM_THIS(IDirect3DDevice8Impl,iface);
1416 int i,j;
1417 UINT tmpW;
1419 /* Allocate the storage for it */
1420 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, Pool);
1421 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1422 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1423 object->ref = 1;
1424 object->Device = This;
1425 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1426 object->ResourceType = D3DRTYPE_CUBETEXTURE;
1428 object->edgeLength = EdgeLength;
1429 object->levels = Levels;
1430 object->usage = Usage;
1431 object->format = Format;
1433 /* Calculate levels for mip mapping */
1434 if (Levels == 0) {
1435 object->levels++;
1436 tmpW = EdgeLength;
1437 while (tmpW > 1) {
1438 tmpW = max(1,tmpW / 2);
1439 object->levels++;
1441 TRACE("Calculated levels = %d\n", object->levels);
1444 /* Generate all the surfaces */
1445 tmpW = EdgeLength;
1446 for (i = 0; i < object->levels; i++)
1448 /* Create the 6 faces */
1449 for (j = 0;j < 6; j++) {
1450 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1451 object->surfaces[j][i]->Container = (IUnknown*) object;
1452 /*IUnknown_AddRef(object->surfaces[j][i]->Container);*/
1453 object->surfaces[j][i]->myDesc.Usage = Usage;
1454 object->surfaces[j][i]->myDesc.Pool = Pool ;
1456 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1457 tmpW = max(1, tmpW / 2);
1461 TRACE("(%p) : Iface@%p\n", This, object);
1462 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1463 return D3D_OK;
1465 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1466 IDirect3DVertexBuffer8Impl *object;
1468 ICOM_THIS(IDirect3DDevice8Impl,iface);
1470 /* Allocate the storage for the device */
1471 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1472 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1473 object->Device = This;
1474 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1475 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1476 object->ref = 1;
1477 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1478 object->currentDesc.Usage = Usage;
1479 object->currentDesc.Pool = Pool;
1480 object->currentDesc.FVF = FVF;
1481 object->currentDesc.Size = Size;
1483 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1485 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1487 return D3D_OK;
1489 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
1490 IDirect3DIndexBuffer8Impl *object;
1492 ICOM_THIS(IDirect3DDevice8Impl,iface);
1493 TRACE("(%p) : Len=%d, Use=%lx, Format=%x, Pool=%d\n", This, Length, Usage, Format, Pool);
1495 /* Allocate the storage for the device */
1496 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1497 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1498 object->Device = This;
1499 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1500 object->ref = 1;
1501 object->ResourceType = D3DRTYPE_INDEXBUFFER;
1503 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1504 object->currentDesc.Usage = Usage;
1505 object->currentDesc.Pool = Pool;
1506 object->currentDesc.Format = Format;
1507 object->currentDesc.Size = Length;
1509 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1511 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1513 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1515 return D3D_OK;
1517 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
1518 IDirect3DSurface8Impl *object;
1520 ICOM_THIS(IDirect3DDevice8Impl,iface);
1522 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1523 *ppSurface = (LPDIRECT3DSURFACE8) object;
1524 object->lpVtbl = &Direct3DSurface8_Vtbl;
1525 object->Device = This;
1526 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1527 object->ResourceType = D3DRTYPE_SURFACE;
1528 object->Container = (IUnknown*) This;
1529 /*IUnknown_AddRef(object->Container);*/
1531 object->ref = 1;
1532 object->myDesc.Width = Width;
1533 object->myDesc.Height = Height;
1534 object->myDesc.Format = Format;
1535 object->myDesc.Type = D3DRTYPE_SURFACE;
1536 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
1537 object->myDesc.Pool = D3DPOOL_MANAGED;
1538 object->myDesc.MultiSampleType = MultiSample;
1539 object->bytesPerPixel = bytesPerPixel(Format);
1540 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1541 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1542 object->lockable = Lockable;
1543 object->locked = FALSE;
1545 TRACE("(%p) : w(%d) h(%d) fmt(%d) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, Lockable, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1546 return D3D_OK;
1548 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
1549 IDirect3DSurface8Impl *object;
1551 ICOM_THIS(IDirect3DDevice8Impl,iface);
1553 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1554 *ppSurface = (LPDIRECT3DSURFACE8) object;
1555 object->lpVtbl = &Direct3DSurface8_Vtbl;
1556 object->Device = This;
1557 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1558 object->ResourceType = D3DRTYPE_SURFACE;
1559 object->Container = (IUnknown*) This;
1560 /*IUnknown_AddRef(object->Container);*/
1562 object->ref = 1;
1563 object->myDesc.Width = Width;
1564 object->myDesc.Height = Height;
1565 object->myDesc.Format = Format;
1566 object->myDesc.Type = D3DRTYPE_SURFACE;
1567 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
1568 object->myDesc.Pool = D3DPOOL_MANAGED;
1569 object->myDesc.MultiSampleType = MultiSample;
1570 object->bytesPerPixel = bytesPerPixel(Format);
1571 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1572 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1573 object->lockable = TRUE;
1574 object->locked = FALSE;
1576 TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1577 return D3D_OK;
1579 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
1580 IDirect3DSurface8Impl *object;
1582 ICOM_THIS(IDirect3DDevice8Impl,iface);
1584 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1585 *ppSurface = (LPDIRECT3DSURFACE8) object;
1586 object->lpVtbl = &Direct3DSurface8_Vtbl;
1587 object->Device = This;
1588 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1589 object->ResourceType = D3DRTYPE_SURFACE;
1590 object->Container = (IUnknown*) This;
1591 /*IUnknown_AddRef(object->Container);*/
1593 object->ref = 1;
1594 object->myDesc.Width = Width;
1595 object->myDesc.Height = Height;
1596 object->myDesc.Format = Format;
1597 object->myDesc.Type = D3DRTYPE_SURFACE;
1598 object->myDesc.Usage = 0;
1599 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
1600 object->bytesPerPixel = bytesPerPixel(Format);
1601 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1602 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1603 object->lockable = TRUE;
1604 object->locked = FALSE;
1606 TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, *ppSurface, object->allocatedMemory, object->myDesc.Size);
1607 return D3D_OK;
1609 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pSourceSurface,CONST RECT* pSourceRectsArray,UINT cRects,
1610 IDirect3DSurface8* pDestinationSurface,CONST POINT* pDestPointsArray) {
1612 HRESULT rc = D3D_OK;
1613 IDirect3DBaseTexture8* texture = NULL;
1616 IDirect3DSurface8Impl *src = (IDirect3DSurface8Impl*) pSourceSurface;
1617 IDirect3DSurface8Impl *dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1619 ICOM_THIS(IDirect3DDevice8Impl,iface);
1620 TRACE("(%p) srcsur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1621 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1623 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1624 a sample and doesnt seem to break anything as far as I can tell */
1625 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1626 TRACE("Formats do not match %x / %x\n", src->myDesc.Format, dst->myDesc.Format);
1627 rc = D3DERR_INVALIDCALL;
1629 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1630 TRACE("Converting dest to same format as source, since dest was unknown\n");
1631 dst->myDesc.Format = src->myDesc.Format;
1633 /* Convert container as well */
1634 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1635 if (texture != NULL) {
1637 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1638 case D3DRTYPE_TEXTURE:
1639 ((IDirect3DTexture8Impl *)texture)->format = src->myDesc.Format;
1640 break;
1641 case D3DRTYPE_VOLUMETEXTURE:
1642 ((IDirect3DVolumeTexture8Impl *)texture)->format = src->myDesc.Format;
1643 break;
1644 case D3DRTYPE_CUBETEXTURE:
1645 ((IDirect3DCubeTexture8Impl *)texture)->format = src->myDesc.Format;
1646 break;
1647 default:
1648 FIXME("Unhandled texture type\n");
1651 /** Releasing texture after GetContainer */
1652 IDirect3DBaseTexture8_Release(texture);
1656 /* Quick if complete copy ... */
1657 if (rc == D3D_OK && (cRects == 0 && pSourceRectsArray==NULL && pDestPointsArray==NULL &&
1658 src->myDesc.Width == dst->myDesc.Width &&
1659 src->myDesc.Height == dst->myDesc.Height)) {
1660 TRACE("Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1661 memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);
1663 } else {
1664 int i;
1665 int bytesPerPixel = ((IDirect3DSurface8Impl *)pSourceSurface)->bytesPerPixel;
1666 int pitchFrom = ((IDirect3DSurface8Impl *)pSourceSurface)->myDesc.Width * bytesPerPixel;
1667 int pitchTo = ((IDirect3DSurface8Impl *)pDestinationSurface)->myDesc.Width * bytesPerPixel;
1669 char *copyfrom = ((IDirect3DSurface8Impl *)pSourceSurface)->allocatedMemory;
1670 char *copyto = ((IDirect3DSurface8Impl *)pDestinationSurface)->allocatedMemory;
1672 /* Copy rect by rect */
1673 for (i=0; i<cRects; i++) {
1674 CONST RECT *r = &pSourceRectsArray[i];
1675 CONST POINT *p = &pDestPointsArray[i];
1676 char *from;
1677 char *to;
1678 int copyperline = (r->right - r->left) * bytesPerPixel;
1679 int j;
1681 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top,
1682 r->right, r->bottom, p->x, p->y);
1684 /* Find where to start */
1685 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1686 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
1688 /* Copy line by line */
1689 for (j=0; j<(r->bottom - r->top); j++) {
1690 memcpy(to + (j*pitchTo), from + (j*pitchFrom), copyperline);
1695 /* Set dirty */
1696 if (rc == D3D_OK) {
1697 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1698 if (texture != NULL) {
1700 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1701 case D3DRTYPE_TEXTURE:
1703 IDirect3DTexture8Impl *pTexture = (IDirect3DTexture8Impl *)texture;
1704 pTexture->Dirty = TRUE;
1706 break;
1707 case D3DRTYPE_VOLUMETEXTURE:
1709 IDirect3DVolumeTexture8Impl *pTexture = (IDirect3DVolumeTexture8Impl *)texture;
1710 pTexture->Dirty = TRUE;
1712 break;
1713 case D3DRTYPE_CUBETEXTURE:
1715 IDirect3DCubeTexture8Impl *pTexture = (IDirect3DCubeTexture8Impl *)texture;
1716 pTexture->Dirty = TRUE;
1718 break;
1719 default:
1720 FIXME("Unhandled texture type\n");
1723 /** Releasing texture after GetContainer */
1724 IDirect3DBaseTexture8_Release(texture);
1728 return D3D_OK;
1730 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture,IDirect3DBaseTexture8* pDestinationTexture) {
1731 ICOM_THIS(IDirect3DDevice8Impl,iface);
1732 FIXME("(%p) : stub\n", This); return D3D_OK;
1734 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1735 HRESULT hr;
1736 D3DLOCKED_RECT lockedRect;
1737 GLint prev_store;
1738 GLenum prev_read;
1740 ICOM_THIS(IDirect3DDevice8Impl,iface);
1742 FIXME("(%p) : stub\n", This);
1744 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1745 return D3DERR_INVALIDCALL;
1748 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, NULL, 0);
1749 if (FAILED(hr)) {
1750 return D3DERR_INVALIDCALL;
1753 ENTER_GL();
1755 glFlush();
1756 vcheckGLcall("glFlush");
1757 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1758 vcheckGLcall("glIntegerv");
1759 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1760 vcheckGLcall("glIntegerv");
1762 glReadBuffer(GL_FRONT);
1763 vcheckGLcall("glReadBuffer");
1764 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1765 vcheckGLcall("glPixelStorei");
1766 glReadPixels(0, 0, This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight,
1767 GL_BGRA, GL_UNSIGNED_BYTE, lockedRect.pBits);
1768 vcheckGLcall("glReadPixels");
1769 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1770 vcheckGLcall("glPixelStorei");
1771 glReadBuffer(prev_read);
1772 vcheckGLcall("glReadBuffer");
1773 LEAVE_GL();
1775 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1776 return hr;
1778 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget,IDirect3DSurface8* pNewZStencil) {
1779 ICOM_THIS(IDirect3DDevice8Impl,iface);
1780 FIXME("(%p) : invalid stub expect crash\n", This);
1782 return D3D_OK;
1784 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1785 ICOM_THIS(IDirect3DDevice8Impl,iface);
1787 TRACE("(%p)->(%p)\n", This, This->frontBuffer);
1789 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->frontBuffer;
1790 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1792 return D3D_OK;
1794 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1795 ICOM_THIS(IDirect3DDevice8Impl,iface);
1797 TRACE("(%p)->(%p)\n", This, ppZStencilSurface);
1799 /* Note inc ref on returned surface */
1800 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8)This->depthStencilBuffer);
1801 *ppZStencilSurface = (LPDIRECT3DSURFACE8)This->depthStencilBuffer;
1803 return D3D_OK;
1806 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1807 ICOM_THIS(IDirect3DDevice8Impl,iface);
1808 TRACE("(%p) : stub\n", This);
1809 return D3D_OK;
1811 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1812 ICOM_THIS(IDirect3DDevice8Impl,iface);
1813 TRACE("(%p)\n", This);
1815 ENTER_GL();
1817 glFlush();
1818 checkGLcall("glFlush");
1820 /* Useful for debugging sometimes!
1821 printf("Hit Enter ...\n");
1822 getchar(); */
1824 LEAVE_GL();
1825 return D3D_OK;
1827 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) {
1828 ICOM_THIS(IDirect3DDevice8Impl,iface);
1830 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1831 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1832 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1833 GLbitfield glMask = 0;
1834 int i;
1835 CONST D3DRECT *curRect;
1837 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1838 Count, pRects, Flags, Z, Stencil);
1840 ENTER_GL();
1841 if (Count > 0 && pRects) {
1842 glEnable(GL_SCISSOR_TEST);
1843 checkGLcall("glEnable GL_SCISSOR_TEST");
1844 curRect = pRects;
1845 } else {
1846 curRect = NULL;
1849 for (i = 0; i < Count || i == 0; i++) {
1851 if (curRect) {
1852 /* Note gl uses lower left, width/height */
1853 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1854 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1855 curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1856 glScissor(curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1857 checkGLcall("glScissor");
1860 /* Clear the whole screen */
1861 if (Flags & D3DCLEAR_STENCIL) {
1862 glClearStencil(Stencil);
1863 checkGLcall("glClearStencil");
1864 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1867 if (Flags & D3DCLEAR_ZBUFFER) {
1868 glClearDepth(Z);
1869 checkGLcall("glClearDepth");
1870 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1873 if (Flags & D3DCLEAR_TARGET) {
1874 TRACE("Clearing screen with glClear to color %lx\n", Color);
1875 glClearColor(((Color >> 16) & 0xFF) / 255.0, ((Color >> 8) & 0xFF) / 255.0,
1876 ((Color >> 0) & 0xFF) / 255.0, ((Color >> 24) & 0xFF) / 255.0);
1877 checkGLcall("glClearColor");
1878 glMask = glMask | GL_COLOR_BUFFER_BIT;
1881 glClear(glMask);
1882 checkGLcall("glClear");
1884 if (curRect) curRect = curRect + sizeof(D3DRECT);
1887 if (Count > 0 && pRects) {
1888 glDisable(GL_SCISSOR_TEST);
1889 checkGLcall("glDisable");
1891 LEAVE_GL();
1893 return D3D_OK;
1895 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
1896 ICOM_THIS(IDirect3DDevice8Impl,iface);
1897 D3DMATRIX m;
1898 int k;
1899 float f;
1900 BOOL viewChanged = TRUE;
1901 int Stage;
1903 /* Most of this routine, comments included copied from ddraw tree initially: */
1904 TRACE("(%p) : State=%d\n", This, d3dts);
1906 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1907 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1908 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1910 /* Handle recording of state blocks */
1911 if (This->isRecordingState) {
1912 TRACE("Recording... not performing anything\n");
1913 return D3D_OK;
1917 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1919 where ViewMat = Camera space, WorldMat = world space.
1921 In OpenGL, camera and world space is combined into GL_MODELVIEW
1922 matrix. The Projection matrix stay projection matrix. */
1924 /* After reading through both OpenGL and Direct3D documentations, I
1925 thought that D3D matrices were written in 'line major mode' transposed
1926 from OpenGL's 'column major mode'. But I found out that a simple memcpy
1927 works fine to transfer one matrix format to the other (it did not work
1928 when transposing)....
1930 So :
1931 1) are the documentations wrong
1932 2) does the matrix work even if they are not read correctly
1933 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
1934 loading using glLoadMatrix ?
1936 Anyway, I always use 'conv_mat' to transfer the matrices from one format
1937 to the other so that if I ever find out that I need to transpose them, I
1938 will able to do it quickly, only by changing the macro conv_mat. */
1940 if (d3dts <= 256) { /* WORLDMATRIX(0) == 256! */
1941 switch (d3dts) {
1942 case D3DTS_WORLDMATRIX(0):
1943 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)]);
1944 break;
1946 case D3DTS_VIEW:
1947 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
1948 break;
1950 case D3DTS_PROJECTION:
1951 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
1952 break;
1954 case D3DTS_TEXTURE0:
1955 case D3DTS_TEXTURE1:
1956 case D3DTS_TEXTURE2:
1957 case D3DTS_TEXTURE3:
1958 case D3DTS_TEXTURE4:
1959 case D3DTS_TEXTURE5:
1960 case D3DTS_TEXTURE6:
1961 case D3DTS_TEXTURE7:
1962 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
1963 break;
1965 default:
1966 FIXME("Unhandled transform state!!\n");
1967 break;
1969 } else {
1970 /**
1971 * Indexed Vertex Blending Matrices 256 -> 511
1973 /** store it */
1974 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
1975 if (checkGLSupport(ARB_VERTEX_BLEND)) {
1976 FIXME("TODO\n");
1977 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
1978 FIXME("TODO\n");
1983 * Move the GL operation to outside of switch to make it work
1984 * regardless of transform set order.
1986 ENTER_GL();
1987 if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
1988 glMatrixMode(GL_PROJECTION);
1989 checkGLcall("glMatrixMode");
1990 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
1991 checkGLcall("glLoadMatrixf");
1992 memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
1993 } else {
1994 TRACE("Skipping as projection already correct\n");
1997 glMatrixMode(GL_MODELVIEW);
1998 checkGLcall("glMatrixMode");
1999 viewChanged = FALSE;
2000 if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
2001 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2002 checkGLcall("glLoadMatrixf");
2003 memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
2004 viewChanged = TRUE;
2006 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
2007 if (d3dts == D3DTS_VIEW) {
2009 /* NOTE: We have to reset the positions even if the light/plane is not currently
2010 enabled, since the call to enable it will not reset the position. */
2012 /* Reset lights */
2013 for (k = 0; k < This->maxLights; k++) {
2014 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
2015 checkGLcall("glLightfv posn");
2016 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
2017 checkGLcall("glLightfv dirn");
2020 /* Reset Clipping Planes if clipping is enabled */
2021 for (k = 0; k < This->clipPlanes; k++) {
2022 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
2023 checkGLcall("glClipPlane");
2026 /* Reapply texture transforms as based off modelview when applied */
2027 for (Stage = 0; Stage < This->TextureUnits; Stage++) {
2029 /* Now apply texture transforms if not applying to the dummy textures */
2030 #if defined(GL_VERSION_1_3)
2031 glActiveTexture(GL_TEXTURE0 + Stage);
2032 #else
2033 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2034 #endif
2035 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
2037 glMatrixMode(GL_TEXTURE);
2038 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2039 glLoadIdentity();
2040 } else {
2041 D3DMATRIX fred;
2042 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2043 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2045 checkGLcall("Load matrix for texture");
2047 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2049 } else if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) {
2050 /* Now apply texture transforms if not applying to the dummy textures */
2051 Stage = d3dts-D3DTS_TEXTURE0;
2053 if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX))) {
2054 memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX));
2056 #if defined(GL_VERSION_1_3)
2057 glActiveTexture(GL_TEXTURE0 + Stage);
2058 #else
2059 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2060 #endif
2061 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
2063 glMatrixMode(GL_TEXTURE);
2064 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2065 glLoadIdentity();
2066 } else {
2067 D3DMATRIX fred;
2068 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2069 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2071 checkGLcall("Load matrix for texture");
2072 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2073 } else {
2074 TRACE("Skipping texture transform as already correct\n");
2077 } else {
2078 TRACE("Skipping view setup as view already correct\n");
2082 * Vertex Blending as described
2083 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
2085 switch (This->UpdateStateBlock->vertex_blend) {
2086 case D3DVBF_DISABLE:
2088 if (viewChanged == TRUE ||
2089 (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
2090 memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
2091 if (viewChanged==FALSE) {
2092 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2093 checkGLcall("glLoadMatrixf");
2095 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
2096 checkGLcall("glMultMatrixf");
2097 } else {
2098 TRACE("Skipping as world already correct\n");
2101 break;
2102 case D3DVBF_1WEIGHTS:
2103 case D3DVBF_2WEIGHTS:
2104 case D3DVBF_3WEIGHTS:
2106 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
2108 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
2109 * so waiting for the values before matrix work
2110 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
2111 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
2112 checkGLcall("glMultMatrixf");
2116 break;
2117 case D3DVBF_TWEENING:
2119 FIXME("valid/correct D3DVBF_TWEENING\n");
2120 f = This->UpdateStateBlock->tween_factor;
2121 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
2122 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
2123 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
2124 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
2125 if (viewChanged==FALSE) {
2126 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2127 checkGLcall("glLoadMatrixf");
2129 glMultMatrixf((float *) &m.u.m[0][0]);
2130 checkGLcall("glMultMatrixf");
2132 break;
2133 case D3DVBF_0WEIGHTS:
2135 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
2136 /* single matrix of weight 1.0f */
2137 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
2138 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
2139 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
2140 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
2141 if (viewChanged == FALSE) {
2142 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2143 checkGLcall("glLoadMatrixf");
2145 glMultMatrixf((float *) &m.u.m[0][0]);
2146 checkGLcall("glMultMatrixf");
2148 break;
2149 default:
2150 break; /* stupid compilator */
2153 LEAVE_GL();
2155 return D3D_OK;
2158 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
2159 ICOM_THIS(IDirect3DDevice8Impl,iface);
2160 TRACE("(%p) : for State %d\n", This, State);
2161 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
2162 return D3D_OK;
2165 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2166 D3DMATRIX *mat = NULL;
2167 D3DMATRIX temp;
2169 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
2170 but works regardless of recording being on.
2171 If this is found to be wrong, change to StateBlock. */
2172 ICOM_THIS(IDirect3DDevice8Impl,iface);
2173 TRACE("(%p) : For state %u\n", This, State);
2175 if (State < HIGHEST_TRANSFORMSTATE)
2177 mat = &This->UpdateStateBlock->transforms[State];
2178 } else {
2179 FIXME("Unhandled transform state!!\n");
2182 /* Copied from ddraw code: */
2183 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);
2184 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);
2185 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);
2186 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);
2188 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);
2189 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);
2190 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);
2191 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);
2193 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);
2194 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);
2195 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);
2196 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);
2198 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);
2199 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);
2200 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);
2201 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);
2203 /* Apply change via set transform - will reapply to eg. lights this way */
2204 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
2205 return D3D_OK;
2207 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
2208 ICOM_THIS(IDirect3DDevice8Impl,iface);
2210 TRACE("(%p)\n", This);
2211 This->UpdateStateBlock->Changed.viewport = TRUE;
2212 This->UpdateStateBlock->Set.viewport = TRUE;
2213 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
2215 /* Handle recording of state blocks */
2216 if (This->isRecordingState) {
2217 TRACE("Recording... not performing anything\n");
2218 return D3D_OK;
2221 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2222 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2224 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2225 checkGLcall("glDepthRange");
2226 /* Fixme? Note GL requires lower left, DirectX supplies upper left */
2227 glViewport(pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height);
2228 checkGLcall("glViewport");
2231 return D3D_OK;
2234 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
2235 ICOM_THIS(IDirect3DDevice8Impl,iface);
2236 TRACE("(%p)\n", This);
2237 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
2238 return D3D_OK;
2241 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
2242 ICOM_THIS(IDirect3DDevice8Impl,iface);
2244 This->UpdateStateBlock->Changed.material = TRUE;
2245 This->UpdateStateBlock->Set.material = TRUE;
2246 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
2248 /* Handle recording of state blocks */
2249 if (This->isRecordingState) {
2250 TRACE("Recording... not performing anything\n");
2251 return D3D_OK;
2254 ENTER_GL();
2255 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2256 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2257 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2258 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2259 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2261 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&This->UpdateStateBlock->material.Ambient);
2262 checkGLcall("glMaterialfv");
2263 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&This->UpdateStateBlock->material.Diffuse);
2264 checkGLcall("glMaterialfv");
2266 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&This->UpdateStateBlock->material.Specular);
2267 checkGLcall("glMaterialfv");
2268 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&This->UpdateStateBlock->material.Emissive);
2269 checkGLcall("glMaterialfv");
2270 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
2271 checkGLcall("glMaterialf");
2273 LEAVE_GL();
2274 return D3D_OK;
2276 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
2277 ICOM_THIS(IDirect3DDevice8Impl,iface);
2278 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
2279 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2280 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2281 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2282 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2283 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2284 return D3D_OK;
2287 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
2288 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
2289 float rho;
2290 float quad_att;
2292 ICOM_THIS(IDirect3DDevice8Impl,iface);
2293 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2295 if (Index > This->maxLights) {
2296 FIXME("Cannot handle more lights than device supports\n");
2297 return D3DERR_INVALIDCALL;
2300 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,
2301 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2302 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2303 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2304 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2305 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2306 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2308 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
2309 This->UpdateStateBlock->Set.lights[Index] = TRUE;
2310 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
2312 /* Handle recording of state blocks */
2313 if (This->isRecordingState) {
2314 TRACE("Recording... not performing anything\n");
2315 return D3D_OK;
2318 /* Diffuse: */
2319 colRGBA[0] = pLight->Diffuse.r;
2320 colRGBA[1] = pLight->Diffuse.g;
2321 colRGBA[2] = pLight->Diffuse.b;
2322 colRGBA[3] = pLight->Diffuse.a;
2323 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2324 checkGLcall("glLightfv");
2326 /* Specular */
2327 colRGBA[0] = pLight->Specular.r;
2328 colRGBA[1] = pLight->Specular.g;
2329 colRGBA[2] = pLight->Specular.b;
2330 colRGBA[3] = pLight->Specular.a;
2331 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2332 checkGLcall("glLightfv");
2334 /* Ambient */
2335 colRGBA[0] = pLight->Ambient.r;
2336 colRGBA[1] = pLight->Ambient.g;
2337 colRGBA[2] = pLight->Ambient.b;
2338 colRGBA[3] = pLight->Ambient.a;
2339 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2340 checkGLcall("glLightfv");
2342 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2343 glMatrixMode(GL_MODELVIEW);
2344 glPushMatrix();
2345 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2347 /* Attenuation - Are these right? guessing... */
2348 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
2349 checkGLcall("glLightf");
2350 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
2351 checkGLcall("glLightf");
2353 quad_att = 1.4/(pLight->Range*pLight->Range);
2354 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2355 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2356 checkGLcall("glLightf");
2358 switch (pLight->Type) {
2359 case D3DLIGHT_POINT:
2360 /* Position */
2361 This->lightPosn[Index][0] = pLight->Position.x;
2362 This->lightPosn[Index][1] = pLight->Position.y;
2363 This->lightPosn[Index][2] = pLight->Position.z;
2364 This->lightPosn[Index][3] = 1.0;
2365 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2366 checkGLcall("glLightfv");
2368 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2369 checkGLcall("glLightf");
2371 /* FIXME: Range */
2372 break;
2374 case D3DLIGHT_SPOT:
2375 /* Position */
2376 This->lightPosn[Index][0] = pLight->Position.x;
2377 This->lightPosn[Index][1] = pLight->Position.y;
2378 This->lightPosn[Index][2] = pLight->Position.z;
2379 This->lightPosn[Index][3] = 1.0;
2380 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2381 checkGLcall("glLightfv");
2383 /* Direction */
2384 This->lightDirn[Index][0] = pLight->Direction.x;
2385 This->lightDirn[Index][1] = pLight->Direction.y;
2386 This->lightDirn[Index][2] = pLight->Direction.z;
2387 This->lightDirn[Index][3] = 1.0;
2388 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2389 checkGLcall("glLightfv");
2392 * opengl-ish and d3d-ish spot lights use too different models for the
2393 * light "intensity" as a function of the angle towards the main light direction,
2394 * so we only can approximate very roughly.
2395 * however spot lights are rather rarely used in games (if ever used at all).
2396 * furthermore if still used, probably nobody pays attention to such details.
2398 if (pLight->Falloff == 0) {
2399 rho = 6.28f;
2400 } else {
2401 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2403 if (rho < 0.0001) rho = 0.0001f;
2404 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2405 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2407 /* FIXME: Range */
2408 break;
2409 case D3DLIGHT_DIRECTIONAL:
2410 /* Direction */
2411 This->lightPosn[Index][0] = -pLight->Direction.x;
2412 This->lightPosn[Index][1] = -pLight->Direction.y;
2413 This->lightPosn[Index][2] = -pLight->Direction.z;
2414 This->lightPosn[Index][3] = 0.0;
2415 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2416 checkGLcall("glLightfv");
2418 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2419 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2422 break;
2423 default:
2424 FIXME("Unrecognized light type %d\n", pLight->Type);
2427 /* Restore the modelview matrix */
2428 glPopMatrix();
2430 return D3D_OK;
2432 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2433 ICOM_THIS(IDirect3DDevice8Impl,iface);
2434 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2436 if (Index > This->maxLights) {
2437 FIXME("Cannot handle more lights than device supports\n");
2438 return D3DERR_INVALIDCALL;
2441 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2442 return D3D_OK;
2444 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2445 ICOM_THIS(IDirect3DDevice8Impl,iface);
2446 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2448 if (Index > This->maxLights) {
2449 FIXME("Cannot handle more lights than device supports\n");
2450 return D3DERR_INVALIDCALL;
2453 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2454 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2455 This->UpdateStateBlock->lightEnable[Index] = Enable;
2457 /* Handle recording of state blocks */
2458 if (This->isRecordingState) {
2459 TRACE("Recording... not performing anything\n");
2460 return D3D_OK;
2463 if (Enable) {
2464 glEnable(GL_LIGHT0+Index);
2465 checkGLcall("glEnable GL_LIGHT0+Index");
2466 } else {
2467 glDisable(GL_LIGHT0+Index);
2468 checkGLcall("glDisable GL_LIGHT0+Index");
2470 return D3D_OK;
2472 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2473 ICOM_THIS(IDirect3DDevice8Impl,iface);
2474 TRACE("(%p) : for idx(%ld)\n", This, Index);
2476 if (Index > This->maxLights) {
2477 FIXME("Cannot handle more lights than device supports\n");
2478 return D3DERR_INVALIDCALL;
2481 *pEnable = This->StateBlock->lightEnable[Index];
2482 return D3D_OK;
2484 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2485 ICOM_THIS(IDirect3DDevice8Impl,iface);
2486 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2488 /* Validate Index */
2489 if (Index >= This->clipPlanes ) {
2490 TRACE("Application has requested clipplane this device doesnt support\n");
2491 return D3DERR_INVALIDCALL;
2494 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2495 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2496 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2497 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2498 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2499 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2501 /* Handle recording of state blocks */
2502 if (This->isRecordingState) {
2503 TRACE("Recording... not performing anything\n");
2504 return D3D_OK;
2507 /* Apply it */
2509 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2510 glMatrixMode(GL_MODELVIEW);
2511 glPushMatrix();
2512 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2514 TRACE("Clipplane [%f,%f,%f,%f]\n", This->UpdateStateBlock->clipplane[Index][0], This->UpdateStateBlock->clipplane[Index][1],
2515 This->UpdateStateBlock->clipplane[Index][2], This->UpdateStateBlock->clipplane[Index][3]);
2516 glClipPlane(GL_CLIP_PLANE0+Index, This->UpdateStateBlock->clipplane[Index]);
2518 glPopMatrix();
2519 checkGLcall("glClipPlane");
2521 return D3D_OK;
2523 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2524 ICOM_THIS(IDirect3DDevice8Impl,iface);
2525 TRACE("(%p) : for idx %ld\n", This, Index);
2527 /* Validate Index */
2528 if (Index >= This->clipPlanes ) {
2529 TRACE("Application has requested clipplane this device doesnt support\n");
2530 return D3DERR_INVALIDCALL;
2533 pPlane[0] = This->StateBlock->clipplane[Index][0];
2534 pPlane[1] = This->StateBlock->clipplane[Index][0];
2535 pPlane[2] = This->StateBlock->clipplane[Index][0];
2536 pPlane[3] = This->StateBlock->clipplane[Index][0];
2537 return D3D_OK;
2539 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2540 ICOM_THIS(IDirect3DDevice8Impl,iface);
2541 DWORD OldValue = This->StateBlock->renderstate[State];
2543 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2544 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2545 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2546 This->UpdateStateBlock->renderstate[State] = Value;
2548 /* Handle recording of state blocks */
2549 if (This->isRecordingState) {
2550 TRACE("Recording... not performing anything\n");
2551 return D3D_OK;
2554 switch (State) {
2555 case D3DRS_FILLMODE :
2556 switch ((D3DFILLMODE) Value) {
2557 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2558 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2559 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2560 default:
2561 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2563 checkGLcall("glPolygonMode (fillmode)");
2564 break;
2566 case D3DRS_LIGHTING :
2567 if (Value) {
2568 glEnable(GL_LIGHTING);
2569 checkGLcall("glEnable GL_LIGHTING");
2570 } else {
2571 glDisable(GL_LIGHTING);
2572 checkGLcall("glDisable GL_LIGHTING");
2574 break;
2576 case D3DRS_ZENABLE :
2577 switch ((D3DZBUFFERTYPE) Value) {
2578 case D3DZB_FALSE:
2579 glDisable(GL_DEPTH_TEST);
2580 checkGLcall("glDisable GL_DEPTH_TEST");
2581 break;
2582 case D3DZB_TRUE:
2583 glEnable(GL_DEPTH_TEST);
2584 checkGLcall("glEnable GL_DEPTH_TEST");
2585 break;
2587 case D3DZB_USEW:
2588 default:
2589 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2591 break;
2593 case D3DRS_CULLMODE :
2595 /* If we are culling "back faces with clockwise vertices" then
2596 set front faces to be counter clockwise and enable culling
2597 of back faces */
2598 switch ((D3DCULL) Value) {
2599 case D3DCULL_NONE:
2600 glDisable(GL_CULL_FACE);
2601 checkGLcall("glDisable GL_CULL_FACE");
2602 break;
2603 case D3DCULL_CW:
2604 glEnable(GL_CULL_FACE);
2605 checkGLcall("glEnable GL_CULL_FACE");
2606 glFrontFace(GL_CCW);
2607 checkGLcall("glFrontFace GL_CCW");
2608 glCullFace(GL_BACK);
2609 break;
2610 case D3DCULL_CCW:
2611 glEnable(GL_CULL_FACE);
2612 checkGLcall("glEnable GL_CULL_FACE");
2613 glFrontFace(GL_CW);
2614 checkGLcall("glFrontFace GL_CW");
2615 glCullFace(GL_BACK);
2616 break;
2617 default:
2618 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2620 break;
2622 case D3DRS_SHADEMODE :
2623 switch ((D3DSHADEMODE) Value) {
2624 case D3DSHADE_FLAT:
2625 glShadeModel(GL_FLAT);
2626 checkGLcall("glShadeModel");
2627 break;
2628 case D3DSHADE_GOURAUD:
2629 glShadeModel(GL_SMOOTH);
2630 checkGLcall("glShadeModel");
2631 break;
2632 case D3DSHADE_PHONG:
2633 FIXME("D3DSHADE_PHONG isnt supported?\n");
2634 return D3DERR_INVALIDCALL;
2635 default:
2636 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2638 break;
2640 case D3DRS_DITHERENABLE :
2641 if (Value) {
2642 glEnable(GL_DITHER);
2643 checkGLcall("glEnable GL_DITHER");
2644 } else {
2645 glDisable(GL_DITHER);
2646 checkGLcall("glDisable GL_DITHER");
2648 break;
2650 case D3DRS_ZWRITEENABLE :
2651 if (Value) {
2652 glDepthMask(1);
2653 checkGLcall("glDepthMask");
2654 } else {
2655 glDepthMask(0);
2656 checkGLcall("glDepthMask");
2658 break;
2660 case D3DRS_ZFUNC :
2662 int glParm = GL_LESS;
2664 switch ((D3DCMPFUNC) Value) {
2665 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2666 case D3DCMP_LESS: glParm=GL_LESS; break;
2667 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2668 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2669 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2670 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2671 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2672 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2673 default:
2674 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2676 glDepthFunc(glParm);
2677 checkGLcall("glDepthFunc");
2679 break;
2681 case D3DRS_AMBIENT :
2684 float col[4];
2685 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2686 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2687 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2688 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2689 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0],col[1],col[2],col[3]);
2690 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2691 checkGLcall("glLightModel for MODEL_AMBIENT");
2694 break;
2696 case D3DRS_ALPHABLENDENABLE :
2697 if (Value) {
2698 glEnable(GL_BLEND);
2699 checkGLcall("glEnable GL_BLEND");
2700 } else {
2701 glDisable(GL_BLEND);
2702 checkGLcall("glDisable GL_BLEND");
2704 break;
2706 case D3DRS_SRCBLEND :
2707 case D3DRS_DESTBLEND :
2709 int newVal = GL_ZERO;
2710 switch (Value) {
2711 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2712 case D3DBLEND_ONE : newVal = GL_ONE; break;
2713 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2714 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2715 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2716 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2717 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2718 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2719 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2720 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2721 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2723 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2724 This->srcBlend = newVal;
2725 This->dstBlend = newVal;
2726 break;
2728 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2729 This->srcBlend = newVal;
2730 This->dstBlend = newVal;
2731 break;
2732 default:
2733 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2736 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2737 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2738 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2739 glBlendFunc(This->srcBlend, This->dstBlend);
2741 checkGLcall("glBlendFunc");
2743 break;
2745 case D3DRS_ALPHATESTENABLE :
2746 if (Value) {
2747 glEnable(GL_ALPHA_TEST);
2748 checkGLcall("glEnable GL_ALPHA_TEST");
2749 } else {
2750 glDisable(GL_ALPHA_TEST);
2751 checkGLcall("glDisable GL_ALPHA_TEST");
2753 break;
2755 case D3DRS_ALPHAFUNC :
2757 int glParm = GL_LESS;
2758 float ref = 1.0;
2760 glGetFloatv(GL_ALPHA_TEST_REF, &ref);
2761 checkGLcall("glGetFloatv(GL_ALPHA_TEST_REF, &ref);");
2763 switch ((D3DCMPFUNC) Value) {
2764 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2765 case D3DCMP_LESS: glParm=GL_LESS; break;
2766 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2767 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2768 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2769 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2770 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2771 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2772 default:
2773 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2775 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2776 glAlphaFunc(glParm, ref);
2777 checkGLcall("glAlphaFunc");
2779 break;
2781 case D3DRS_ALPHAREF :
2783 int glParm = GL_LESS;
2784 float ref = 1.0;
2786 glGetIntegerv(GL_ALPHA_TEST_FUNC, &glParm);
2787 checkGLcall("glGetFloatv(GL_ALPHA_TEST_FUNC, &glParm);");
2789 ref = ((float) Value) / 255.0;
2790 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2791 glAlphaFunc(glParm, ref);
2792 checkGLcall("glAlphaFunc");
2794 break;
2796 case D3DRS_CLIPPLANEENABLE :
2797 case D3DRS_CLIPPING :
2799 /* Ensure we only do the changed clip planes */
2800 DWORD enable = 0xFFFFFFFF;
2801 DWORD disable = 0x00000000;
2803 /* If enabling / disabling all */
2804 if (State == D3DRS_CLIPPING) {
2805 if (Value) {
2806 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2807 disable = 0x00;
2808 } else {
2809 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2810 enable = 0x00;
2812 } else {
2813 enable = Value & ~OldValue;
2814 disable = ~Value & OldValue;
2817 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2818 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2819 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2820 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2821 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2822 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2824 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2825 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2826 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2827 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2828 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2829 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2831 break;
2833 case D3DRS_BLENDOP :
2835 int glParm = GL_FUNC_ADD;
2837 switch ((D3DBLENDOP) Value) {
2838 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2839 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2840 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2841 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2842 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2843 default:
2844 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2846 TRACE("glBlendEquation(%x)\n", glParm);
2847 glBlendEquation(glParm);
2848 checkGLcall("glBlendEquation");
2850 break;
2852 case D3DRS_TEXTUREFACTOR :
2854 int i;
2856 /* Note the texture color applies to all textures whereas
2857 GL_TEXTURE_ENV_COLOR applies to active only */
2858 float col[4];
2859 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2860 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2861 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2862 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2864 /* Set the default alpha blend color */
2865 glBlendColor(col[0], col[1], col[2], col[3]);
2866 checkGLcall("glBlendColor");
2868 /* And now the default texture color as well */
2869 for (i = 0; i < This->TextureUnits; i++) {
2871 /* Note the D3DRS value applies to all textures, but GL has one
2872 per texture, so apply it now ready to be used! */
2873 if (This->isMultiTexture) {
2874 #if defined(GL_VERSION_1_3)
2875 glActiveTexture(GL_TEXTURE0 + i);
2876 #else
2877 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2878 #endif
2879 checkGLcall("Activate texture.. to update const color");
2880 } else if (i>0) {
2881 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2884 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2885 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2888 break;
2890 case D3DRS_SPECULARENABLE :
2892 if (Value) {
2893 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
2894 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);");
2895 } else {
2896 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
2897 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);");
2900 break;
2902 case D3DRS_STENCILENABLE :
2903 if (Value) {
2904 glEnable(GL_STENCIL_TEST);
2905 checkGLcall("glEnable GL_STENCIL_TEST");
2906 } else {
2907 glDisable(GL_STENCIL_TEST);
2908 checkGLcall("glDisable GL_STENCIL_TEST");
2910 break;
2912 case D3DRS_STENCILFUNC :
2914 int glParm = GL_ALWAYS;
2915 int ref = 0;
2916 GLuint mask = 0xFFFFFFFF;
2918 glGetIntegerv(GL_STENCIL_REF, &ref);
2919 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
2920 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
2921 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
2923 switch ((D3DCMPFUNC) Value) {
2924 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2925 case D3DCMP_LESS: glParm=GL_LESS; break;
2926 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2927 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2928 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2929 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2930 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2931 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2932 default:
2933 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2935 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2936 glStencilFunc(glParm, ref, mask);
2937 checkGLcall("glStencilFunc");
2939 break;
2941 case D3DRS_STENCILREF :
2943 int glParm = GL_ALWAYS;
2944 int ref = 0;
2945 GLuint mask = 0xFFFFFFFF;
2947 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
2948 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
2949 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
2950 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
2952 ref = Value;
2953 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2954 glStencilFunc(glParm, ref, mask);
2955 checkGLcall("glStencilFunc");
2957 break;
2959 case D3DRS_STENCILMASK :
2961 int glParm = GL_ALWAYS;
2962 int ref = 0.0;
2963 GLuint mask = Value;
2965 glGetIntegerv(GL_STENCIL_REF, &ref);
2966 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
2967 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
2968 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
2970 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2971 glStencilFunc(glParm, ref, mask);
2972 checkGLcall("glStencilFunc");
2974 break;
2976 case D3DRS_STENCILFAIL :
2978 GLenum fail ;
2979 GLenum zpass ;
2980 GLenum zfail ;
2982 fail = StencilOp(Value);
2983 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2984 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2985 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2986 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2988 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2989 glStencilOp(fail, zfail, zpass);
2990 checkGLcall("glStencilOp(fail, zfail, zpass);");
2992 break;
2993 case D3DRS_STENCILZFAIL :
2995 GLenum fail ;
2996 GLenum zpass ;
2997 GLenum zfail ;
2999 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3000 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3001 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3002 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3003 zfail = StencilOp(Value);
3005 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3006 glStencilOp(fail, zfail, zpass);
3007 checkGLcall("glStencilOp(fail, zfail, zpass);");
3009 break;
3010 case D3DRS_STENCILPASS :
3012 GLenum fail ;
3013 GLenum zpass ;
3014 GLenum zfail ;
3016 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3017 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3018 zpass = StencilOp(Value);
3019 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3020 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3022 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3023 glStencilOp(fail, zfail, zpass);
3024 checkGLcall("glStencilOp(fail, zfail, zpass);");
3026 break;
3028 case D3DRS_STENCILWRITEMASK :
3030 glStencilMask(Value);
3031 TRACE("glStencilMask(%lu)\n", Value);
3032 checkGLcall("glStencilMask");
3034 break;
3036 case D3DRS_FOGENABLE :
3038 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
3039 glEnable(GL_FOG);
3040 checkGLcall("glEnable GL_FOG\n");
3041 } else {
3042 glDisable(GL_FOG);
3043 checkGLcall("glDisable GL_FOG\n");
3046 break;
3048 case D3DRS_FOGCOLOR :
3050 float col[4];
3051 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3052 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
3053 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
3054 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
3056 /* Set the default alpha blend color */
3057 glFogfv(GL_FOG_COLOR, &col[0]);
3058 checkGLcall("glFog GL_FOG_COLOR");
3060 break;
3062 case D3DRS_FOGSTART :
3064 float *f = (float *)&Value;
3065 glFogfv(GL_FOG_START, f);
3066 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3067 TRACE("Fog Start == %f\n", *f);
3069 break;
3071 case D3DRS_FOGEND :
3073 float *f = (float *)&Value;
3074 glFogfv(GL_FOG_END, f);
3075 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3076 TRACE("Fog End == %f\n", *f);
3078 break;
3080 case D3DRS_FOGDENSITY :
3082 glFogf(GL_FOG_DENSITY, (float) Value);
3083 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3085 break;
3087 case D3DRS_VERTEXBLEND :
3089 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3090 TRACE("Vertex Blending state to %ld\n", Value);
3092 break;
3094 case D3DRS_TWEENFACTOR :
3096 This->UpdateStateBlock->tween_factor = *((float*) &Value);
3097 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
3099 break;
3101 case D3DRS_INDEXEDVERTEXBLENDENABLE :
3103 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3105 break;
3108 case D3DRS_COLORVERTEX :
3109 case D3DRS_DIFFUSEMATERIALSOURCE :
3110 case D3DRS_SPECULARMATERIALSOURCE :
3111 case D3DRS_AMBIENTMATERIALSOURCE :
3112 case D3DRS_EMISSIVEMATERIALSOURCE :
3114 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3116 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
3117 glEnable(GL_COLOR_MATERIAL);
3118 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
3120 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3121 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
3122 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
3123 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
3124 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
3126 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3127 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3128 Parm = GL_AMBIENT_AND_DIFFUSE;
3129 } else {
3130 Parm = GL_DIFFUSE;
3132 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3133 Parm = GL_AMBIENT;
3134 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3135 Parm = GL_EMISSION;
3136 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3137 Parm = GL_SPECULAR;
3138 } else {
3139 Parm = -1;
3142 if (Parm == -1) {
3143 glDisable(GL_COLOR_MATERIAL);
3144 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3145 } else {
3146 TRACE("glColorMaterial Parm=%d\n", Parm);
3147 glColorMaterial(GL_FRONT_AND_BACK, Parm);
3148 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
3151 } else {
3152 glDisable(GL_COLOR_MATERIAL);
3153 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3156 break;
3158 /* Unhandled yet...! */
3159 case D3DRS_LINEPATTERN :
3160 case D3DRS_LASTPIXEL :
3161 case D3DRS_ZVISIBLE :
3162 case D3DRS_FOGTABLEMODE :
3163 case D3DRS_EDGEANTIALIAS :
3164 case D3DRS_ZBIAS :
3165 case D3DRS_RANGEFOGENABLE :
3166 case D3DRS_WRAP0 :
3167 case D3DRS_WRAP1 :
3168 case D3DRS_WRAP2 :
3169 case D3DRS_WRAP3 :
3170 case D3DRS_WRAP4 :
3171 case D3DRS_WRAP5 :
3172 case D3DRS_WRAP6 :
3173 case D3DRS_WRAP7 :
3174 case D3DRS_FOGVERTEXMODE :
3175 case D3DRS_LOCALVIEWER :
3176 case D3DRS_NORMALIZENORMALS :
3177 case D3DRS_SOFTWAREVERTEXPROCESSING :
3178 case D3DRS_POINTSIZE :
3179 case D3DRS_POINTSIZE_MIN :
3180 case D3DRS_POINTSPRITEENABLE :
3181 case D3DRS_POINTSCALEENABLE :
3182 case D3DRS_POINTSCALE_A :
3183 case D3DRS_POINTSCALE_B :
3184 case D3DRS_POINTSCALE_C :
3185 case D3DRS_MULTISAMPLEANTIALIAS :
3186 case D3DRS_MULTISAMPLEMASK :
3187 case D3DRS_PATCHEDGESTYLE :
3188 case D3DRS_PATCHSEGMENTS :
3189 case D3DRS_DEBUGMONITORTOKEN :
3190 case D3DRS_POINTSIZE_MAX :
3191 case D3DRS_COLORWRITEENABLE :
3192 case D3DRS_POSITIONORDER :
3193 case D3DRS_NORMALORDER :
3194 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3195 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3196 break;
3197 default:
3198 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3201 return D3D_OK;
3203 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3204 ICOM_THIS(IDirect3DDevice8Impl,iface);
3205 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3206 *pValue = This->StateBlock->renderstate[State];
3207 return D3D_OK;
3209 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3210 ICOM_THIS(IDirect3DDevice8Impl,iface);
3212 TRACE("(%p)\n", This);
3214 return IDirect3DDeviceImpl_BeginStateBlock(This);
3216 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3217 IDirect3DStateBlockImpl* pSB;
3218 ICOM_THIS(IDirect3DDevice8Impl,iface);
3219 HRESULT res;
3221 TRACE("(%p)\n", This);
3223 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3224 *pToken = (DWORD) pSB;
3225 return res;
3228 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3229 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3230 ICOM_THIS(IDirect3DDevice8Impl,iface);
3232 TRACE("(%p)\n", This);
3234 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3237 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3238 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3239 ICOM_THIS(IDirect3DDevice8Impl,iface);
3241 TRACE("(%p)\n", This);
3243 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3245 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3246 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3247 ICOM_THIS(IDirect3DDevice8Impl,iface);
3249 TRACE("(%p)\n", This);
3251 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3254 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3255 IDirect3DStateBlockImpl* pSB;
3256 ICOM_THIS(IDirect3DDevice8Impl,iface);
3257 HRESULT res;
3259 TRACE("(%p) : for type %d\n", This, Type);
3261 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3262 *pToken = (DWORD) pSB;
3263 return res;
3266 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3267 ICOM_THIS(IDirect3DDevice8Impl,iface);
3268 FIXME("(%p) : stub\n", This); return D3D_OK;
3270 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3271 ICOM_THIS(IDirect3DDevice8Impl,iface);
3272 FIXME("(%p) : stub\n", This); return D3D_OK;
3274 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3275 ICOM_THIS(IDirect3DDevice8Impl,iface);
3276 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3277 *ppTexture = (LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage];
3278 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3279 return D3D_OK;
3281 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8* pTexture) {
3283 IDirect3DBaseTexture8 *oldTxt;
3284 BOOL reapplyStates = TRUE;
3286 ICOM_THIS(IDirect3DDevice8Impl,iface);
3287 D3DRESOURCETYPE textureType;
3289 oldTxt = This->UpdateStateBlock->textures[Stage];
3290 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3292 /* Reject invalid texture units */
3293 if (Stage >= This->TextureUnits) {
3294 TRACE("Attempt to access invalid texture rejected\n");
3295 return D3DERR_INVALIDCALL;
3298 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3299 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3300 This->UpdateStateBlock->textures[Stage] = pTexture;
3302 /* Handle recording of state blocks */
3303 if (This->isRecordingState) {
3304 TRACE("Recording... not performing anything\n");
3305 return D3D_OK;
3308 /* Make appropriate texture active */
3309 if (This->isMultiTexture) {
3310 #if defined(GL_VERSION_1_3)
3311 glActiveTexture(GL_TEXTURE0 + Stage);
3312 #else
3313 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3314 #endif
3315 checkGLcall("glActiveTextureARB");
3316 } else if (Stage>0) {
3317 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3320 /* Decrement the count of the previous texture */
3321 if (oldTxt != NULL) {
3322 IDirect3DBaseTexture8Impl_Release(oldTxt);
3325 if (pTexture) {
3326 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage]);
3328 /* Now setup the texture appropraitly */
3329 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3331 if (textureType == D3DRTYPE_TEXTURE) {
3332 IDirect3DTexture8Impl *pTexture2 = (IDirect3DTexture8Impl *) pTexture;
3334 if ((void *)oldTxt == (void *)pTexture2 && pTexture2->Dirty == FALSE) {
3335 TRACE("Skipping setting texture as old == new\n");
3336 reapplyStates = FALSE;
3337 } else {
3339 /* Standard 2D texture */
3340 TRACE("Standard 2d texture\n");
3341 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3343 /* Load up the texture now */
3344 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8)pTexture);
3346 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3347 IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture;
3348 int i;
3350 /* Standard 3D (volume) texture */
3351 TRACE("Standard 3d texture\n");
3352 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3354 for (i=0; i<pTexture2->levels; i++)
3357 if (i==0 && pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3358 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3359 checkGLcall("glBindTexture");
3360 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3362 /* No need to walk through all mip-map levels, since already all assigned */
3363 i = pTexture2->levels;
3364 } else {
3365 if (i==0) {
3367 if (pTexture2->volumes[i]->textureName == 0) {
3368 glGenTextures(1, &pTexture2->volumes[i]->textureName);
3369 checkGLcall("glGenTextures");
3370 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3373 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3374 checkGLcall("glBindTexture");
3376 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1);
3377 checkGLcall("glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1)");
3380 TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3381 GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width,
3382 pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth,
3383 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3384 pTexture2->volumes[i]->allocatedMemory);
3385 glTexImage3D(GL_TEXTURE_3D, i,
3386 fmt2glintFmt(pTexture2->format),
3387 pTexture2->volumes[i]->myDesc.Width,
3388 pTexture2->volumes[i]->myDesc.Height,
3389 pTexture2->volumes[i]->myDesc.Depth,
3391 fmt2glFmt(pTexture2->format),
3392 fmt2glType(pTexture2->format),
3393 pTexture2->volumes[i]->allocatedMemory
3395 checkGLcall("glTexImage3D");
3397 /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3398 pTexture2->Dirty = FALSE;
3402 } else {
3403 FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType);
3405 } else {
3406 TRACE("Setting to no texture (ie default texture)\n");
3407 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3408 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3409 checkGLcall("glBindTexture");
3410 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3413 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3414 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3415 if (reapplyStates) {
3416 setupTextureStates (iface, Stage);
3419 return D3D_OK;
3422 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3423 ICOM_THIS(IDirect3DDevice8Impl,iface);
3424 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3425 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3426 return D3D_OK;
3429 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) {
3430 ICOM_THIS(IDirect3DDevice8Impl,iface);
3432 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3434 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value);
3436 /* Reject invalid texture units */
3437 if (Stage >= This->TextureUnits) {
3438 TRACE("Attempt to access invalid texture rejected\n");
3439 return D3DERR_INVALIDCALL;
3442 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3443 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3444 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3446 /* Handle recording of state blocks */
3447 if (This->isRecordingState) {
3448 TRACE("Recording... not performing anything\n");
3449 return D3D_OK;
3452 /* Make appropriate texture active */
3453 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3454 if (This->isMultiTexture) {
3455 #if defined(GL_VERSION_1_3)
3456 glActiveTexture(GL_TEXTURE0 + Stage);
3457 vcheckGLcall("glActiveTexture");
3458 #else
3459 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3460 vcheckGLcall("glActiveTextureARB");
3461 #endif
3462 } else if (Stage > 0) {
3463 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3466 switch (Type) {
3468 case D3DTSS_MINFILTER :
3469 case D3DTSS_MIPFILTER :
3471 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3472 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3473 GLint realVal = GL_LINEAR;
3475 if (ValueMIN == D3DTEXF_POINT) {
3476 /* GL_NEAREST_* */
3477 if (ValueMIP == D3DTEXF_POINT) {
3478 realVal = GL_NEAREST_MIPMAP_NEAREST;
3479 } else if (ValueMIP == D3DTEXF_LINEAR) {
3480 realVal = GL_NEAREST_MIPMAP_LINEAR;
3481 } else if (ValueMIP == D3DTEXF_NONE) {
3482 realVal = GL_NEAREST;
3483 } else {
3484 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3485 realVal = GL_NEAREST_MIPMAP_LINEAR;
3487 } else if (ValueMIN == D3DTEXF_LINEAR) {
3488 /* GL_LINEAR_* */
3489 if (ValueMIP == D3DTEXF_POINT) {
3490 realVal = GL_LINEAR_MIPMAP_NEAREST;
3491 } else if (ValueMIP == D3DTEXF_LINEAR) {
3492 realVal = GL_LINEAR_MIPMAP_LINEAR;
3493 } else if (ValueMIP == D3DTEXF_NONE) {
3494 realVal = GL_LINEAR;
3495 } else {
3496 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3497 realVal = GL_LINEAR_MIPMAP_LINEAR;
3499 } else if (ValueMIN == D3DTEXF_NONE) {
3500 /* Doesnt really make sense - Windows just seems to disable
3501 mipmapping when this occurs */
3502 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3503 realVal = GL_LINEAR;
3505 } else {
3506 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3507 realVal = GL_LINEAR_MIPMAP_LINEAR;
3510 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3511 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3512 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3514 break;
3517 case D3DTSS_MAGFILTER :
3518 if (Value == D3DTEXF_POINT) {
3519 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3520 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3521 } else if (Value == D3DTEXF_LINEAR) {
3522 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3523 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3524 } else {
3525 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3527 break;
3529 case D3DTSS_COLORARG0 :
3530 case D3DTSS_ALPHAARG0 :
3531 /* FIXME: Mesa seems to struggle setting these at the moment */
3532 /*FIXME("COLORARG0/ALPHAARG0 support still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);*/
3533 /*break;*/
3535 case D3DTSS_COLORARG1 :
3536 case D3DTSS_COLORARG2 :
3537 case D3DTSS_ALPHAARG1 :
3538 case D3DTSS_ALPHAARG2 :
3540 BOOL isAlphaArg = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3541 int operand = GL_SRC_COLOR;
3542 int source = GL_TEXTURE;
3544 GetSrcAndOpFromValue(Value, isAlphaArg, &source, &operand);
3545 if (isAlphaArg) {
3546 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
3547 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
3548 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
3549 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
3550 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
3551 } else {
3552 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
3553 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
3554 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
3555 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
3556 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
3559 break;
3561 case D3DTSS_ALPHAOP :
3562 case D3DTSS_COLOROP :
3565 int Scale = 1;
3566 int Parm = (Type == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
3568 if (Type == D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
3569 /* TODO: Disable by making this and all later levels disabled */
3570 glDisable(GL_TEXTURE_1D);
3571 checkGLcall("Disable GL_TEXTURE_1D");
3572 glDisable(GL_TEXTURE_2D);
3573 checkGLcall("Disable GL_TEXTURE_2D");
3574 glDisable(GL_TEXTURE_3D);
3575 checkGLcall("Disable GL_TEXTURE_3D");
3576 } else {
3578 /* Enable only the appropriate texture dimension */
3579 if (Type == D3DTSS_COLOROP) {
3580 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3581 glEnable(GL_TEXTURE_1D);
3582 checkGLcall("Enable GL_TEXTURE_1D");
3583 } else {
3584 glDisable(GL_TEXTURE_1D);
3585 checkGLcall("Disable GL_TEXTURE_1D");
3587 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3588 glEnable(GL_TEXTURE_2D);
3589 checkGLcall("Enable GL_TEXTURE_2D");
3590 } else {
3591 glDisable(GL_TEXTURE_2D);
3592 checkGLcall("Disable GL_TEXTURE_2D");
3594 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3595 glEnable(GL_TEXTURE_3D);
3596 checkGLcall("Enable GL_TEXTURE_3D");
3597 } else {
3598 glDisable(GL_TEXTURE_3D);
3599 checkGLcall("Disable GL_TEXTURE_3D");
3603 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
3604 if (Value != D3DTOP_DISABLE) {
3605 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3608 /* Now set up the operand correctly */
3609 switch (Value) {
3610 case D3DTOP_DISABLE :
3611 /* Contrary to the docs, alpha can be disabled when colorop is enabled
3612 and it works, so ignore this op */
3613 TRACE("Disable ALPHAOP but COLOROP enabled!\n");
3614 break;
3616 case D3DTOP_SELECTARG1 :
3618 FIXME("see if D3DTOP_SELECTARG1 behavior is correct now!\n");
3619 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3620 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3621 #if 0 /* don't seem to do anything */
3622 BOOL isAlphaOp = (Type == D3DTSS_ALPHAOP);
3623 DWORD dwValue = 0;
3624 GLenum source;
3625 GLenum operand;
3626 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3627 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3628 if (isAlphaOp) {
3629 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3630 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3631 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3632 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3633 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3634 } else {
3635 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3636 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3637 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3638 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3639 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3641 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3642 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3643 if (isAlphaOp) {
3644 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3645 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3646 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3647 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3648 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3649 } else {
3650 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3651 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3652 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3653 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3654 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3656 #endif
3658 break;
3660 case D3DTOP_SELECTARG2 :
3662 BOOL isAlphaOp = (Type == D3DTSS_ALPHAOP);
3663 DWORD dwValue = 0;
3664 GLenum source;
3665 GLenum operand;
3666 FIXME("see if D3DTOP_SELECTARG2 behavior is correct now!\n");
3667 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3668 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3669 /* GL_REPLACE, swap args 0 and 1? */
3670 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3671 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3672 if (isAlphaOp) {
3673 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3674 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3675 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3676 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3677 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3678 } else {
3679 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3680 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3681 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3682 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3683 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3685 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3686 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3687 if (isAlphaOp) {
3688 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3689 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3690 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3691 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3692 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3693 } else {
3694 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3695 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3696 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3697 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3698 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3701 break;
3703 case D3DTOP_MODULATE4X : Scale = Scale * 2; /* Drop through */
3704 case D3DTOP_MODULATE2X : Scale = Scale * 2; /* Drop through */
3705 case D3DTOP_MODULATE :
3707 /* Correct scale */
3708 if (Type == D3DTSS_ALPHAOP) {
3709 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
3710 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
3711 } else {
3712 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
3713 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
3715 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
3716 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
3717 break;
3719 case D3DTOP_ADD :
3720 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
3721 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
3722 break;
3724 case D3DTOP_ADDSIGNED2X : Scale = Scale * 2; /* Drop through */
3725 case D3DTOP_ADDSIGNED :
3726 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
3727 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
3728 break;
3730 case D3DTOP_DOTPRODUCT3 :
3731 #if defined(GL_VERSION_1_3)
3732 if (This->isDot3) {
3733 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
3734 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
3735 break;
3737 #endif
3738 FIXME("DotProduct3 extension requested but not supported via this version of opengl\n");
3739 break;
3741 case D3DTOP_SUBTRACT :
3742 #if defined(GL_VERSION_1_3)
3743 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT);
3744 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT)");
3745 break;
3746 #else
3748 * @TODO: to check:
3749 * if ARB_texture_env_combine is supported
3750 * we can use GL_SUBTRACT_ARB here
3752 #endif
3753 case D3DTOP_ADDSMOOTH :
3754 case D3DTOP_BLENDDIFFUSEALPHA :
3755 case D3DTOP_BLENDTEXTUREALPHA :
3756 case D3DTOP_BLENDFACTORALPHA :
3757 case D3DTOP_BLENDTEXTUREALPHAPM :
3758 case D3DTOP_BLENDCURRENTALPHA :
3759 case D3DTOP_PREMODULATE :
3760 case D3DTOP_MODULATEALPHA_ADDCOLOR :
3761 case D3DTOP_MODULATECOLOR_ADDALPHA :
3762 case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
3763 case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
3764 case D3DTOP_BUMPENVMAP :
3765 case D3DTOP_BUMPENVMAPLUMINANCE :
3766 case D3DTOP_MULTIPLYADD :
3767 case D3DTOP_LERP :
3768 default:
3769 FIXME("Unhandled texture operation %ld\n", Value);
3772 break;
3775 case D3DTSS_ADDRESSU :
3776 case D3DTSS_ADDRESSV :
3777 case D3DTSS_ADDRESSW :
3779 GLint wrapParm = GL_REPEAT;
3780 switch (Value) {
3781 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3782 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3783 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3784 #if defined(GL_VERSION_1_4)
3785 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3786 #elif defined(GL_ARB_texture_mirrored_repeat)
3787 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3788 #else
3789 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3790 #endif
3791 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3792 default:
3793 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3794 wrapParm = GL_REPEAT;
3797 switch (Type) {
3798 case D3DTSS_ADDRESSU:
3799 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3800 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3801 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3802 break;
3803 case D3DTSS_ADDRESSV:
3804 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3805 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3806 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3807 break;
3808 case D3DTSS_ADDRESSW:
3809 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3810 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3811 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3812 break;
3813 default: /* nop */
3814 break; /** stupic compilator */
3817 break;
3819 case D3DTSS_BORDERCOLOR :
3821 float col[4];
3822 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3823 col[1] = ((Value >> 8) & 0xFF) / 255.0;
3824 col[2] = ((Value >> 0) & 0xFF) / 255.0;
3825 col[3] = ((Value >> 24) & 0xFF) / 255.0;
3827 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3828 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3829 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3831 break;
3833 case D3DTSS_TEXCOORDINDEX :
3835 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3836 as the input texture coordinates for this stage's texture transformation. This
3837 equates roughly to EYE_LINEAR */
3840 * To Jason: i don't understand what to do with the (Value & 0x00FF) index
3841 * it seems a texture coordinate index (0 <= x <= 7) seeing msdn and logs
3842 * have you any idea ?
3845 /**
3846 * Be carefull the value of the mask 0xF0000 come from d3d8types.h infos
3848 switch (Value & 0xFFFFFF00) {
3849 case D3DTSS_TCI_PASSTHRU:
3850 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3851 break;
3853 case D3DTSS_TCI_CAMERASPACEPOSITION:
3855 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3856 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3857 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3858 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3859 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3861 glMatrixMode(GL_MODELVIEW);
3862 glPushMatrix();
3863 glLoadIdentity();
3864 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3865 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3866 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3867 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3868 glPopMatrix();
3870 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3871 glEnable(GL_TEXTURE_GEN_S);
3872 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3873 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3874 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3875 glEnable(GL_TEXTURE_GEN_T);
3876 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3877 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3878 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3879 glEnable(GL_TEXTURE_GEN_R);
3880 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3881 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3882 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3884 break;
3886 default:
3887 /* Todo: */
3888 /* ? disable GL_TEXTURE_GEN_n ? */
3889 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3890 break;
3893 break;
3895 /* Unhandled */
3896 case D3DTSS_BUMPENVMAT00 :
3897 case D3DTSS_BUMPENVMAT01 :
3898 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3899 break;
3900 case D3DTSS_BUMPENVMAT10 :
3901 case D3DTSS_BUMPENVMAT11 :
3902 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3903 break;
3905 case D3DTSS_MIPMAPLODBIAS :
3906 case D3DTSS_MAXMIPLEVEL :
3907 case D3DTSS_MAXANISOTROPY :
3908 case D3DTSS_BUMPENVLSCALE :
3909 case D3DTSS_BUMPENVLOFFSET :
3910 case D3DTSS_TEXTURETRANSFORMFLAGS :
3911 case D3DTSS_RESULTARG :
3912 default:
3913 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3914 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3916 return D3D_OK;
3918 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3919 ICOM_THIS(IDirect3DDevice8Impl,iface);
3920 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3921 return D3D_OK;
3923 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize) {
3924 ICOM_THIS(IDirect3DDevice8Impl,iface);
3925 FIXME("(%p) : stub\n", This); return D3D_OK;
3927 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,CONST PALETTEENTRY* pEntries) {
3928 ICOM_THIS(IDirect3DDevice8Impl,iface);
3929 FIXME("(%p) : stub\n", This); return D3D_OK;
3931 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,PALETTEENTRY* pEntries) {
3932 ICOM_THIS(IDirect3DDevice8Impl,iface);
3933 FIXME("(%p) : stub\n", This); return D3D_OK;
3935 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3936 ICOM_THIS(IDirect3DDevice8Impl,iface);
3937 FIXME("(%p) : stub\n", This); return D3D_OK;
3939 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3940 ICOM_THIS(IDirect3DDevice8Impl,iface);
3941 FIXME("(%p) : stub\n", This); return D3D_OK;
3943 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) {
3945 IDirect3DVertexBuffer8 *pVB;
3947 ICOM_THIS(IDirect3DDevice8Impl,iface);
3948 pVB = This->StateBlock->stream_source[0];
3950 TRACE("(%p) : Type=%d, Start=%d, Count=%d\n", This, PrimitiveType, StartVertex, PrimitiveCount);
3952 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
3953 This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
3955 return D3D_OK;
3957 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3958 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3959 UINT idxStride = 2;
3960 IDirect3DIndexBuffer8 *pIB;
3961 IDirect3DVertexBuffer8 *pVB;
3962 D3DINDEXBUFFER_DESC IdxBufDsc;
3964 ICOM_THIS(IDirect3DDevice8Impl,iface);
3965 pIB = This->StateBlock->pIndexData;
3966 pVB = This->StateBlock->stream_source[0];
3968 TRACE("(%p) : Type=%d, min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, PrimitiveType,
3969 minIndex, NumVertices, startIndex, primCount);
3971 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3972 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3973 idxStride = 2;
3974 } else {
3975 idxStride = 4;
3978 DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
3979 This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3980 minIndex);
3982 return D3D_OK;
3984 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3985 ICOM_THIS(IDirect3DDevice8Impl,iface);
3987 TRACE("(%p) : Type=%d, pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3989 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3991 This->StateBlock->stream_source[0] = NULL;
3992 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3993 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
3994 0, 0, 0, NULL, 0);
3995 This->StateBlock->stream_stride[0] = 0;
3997 /*stream zero settings set to null at end */
3998 return D3D_OK;
4000 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4001 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4002 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4003 UINT VertexStreamZeroStride) {
4004 int idxStride;
4005 ICOM_THIS(IDirect3DDevice8Impl,iface);
4006 TRACE("(%p) : Type=%d, MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType,
4007 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4009 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4010 if (IndexDataFormat == D3DFMT_INDEX16) {
4011 idxStride = 2;
4012 } else {
4013 idxStride = 4;
4016 This->StateBlock->stream_source[0] = NULL;
4017 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4018 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4019 This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4021 /*stream zero settings set to null at end */
4022 This->StateBlock->stream_stride[0] = 0;
4023 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4025 return D3D_OK;
4027 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4028 ICOM_THIS(IDirect3DDevice8Impl,iface);
4029 FIXME("(%p) : stub\n", This); return D3D_OK;
4031 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4032 ICOM_THIS(IDirect3DDevice8Impl,iface);
4033 IDirect3DVertexShaderImpl* object;
4034 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4035 HRESULT res;
4036 UINT i;
4038 TRACE("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
4039 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4040 return D3DERR_INVALIDCALL;
4042 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4043 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4044 return D3DERR_OUTOFVIDEOMEMORY;
4047 /** Create the Vertex Shader */
4048 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4049 /** TODO: check FAILED(res) */
4051 /** Create and Bind the Vertex Shader Declaration */
4052 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4053 /** TODO: check FAILED(res) */
4055 VertexShaders[i] = object;
4056 VertexShaderDeclarations[i] = attached_decl;
4057 *pHandle = VS_HIGHESTFIXEDFXF + i;
4059 return D3D_OK;
4061 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4062 ICOM_THIS(IDirect3DDevice8Impl,iface);
4064 This->UpdateStateBlock->VertexShader = Handle;
4065 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4066 This->UpdateStateBlock->Set.vertexShader = TRUE;
4068 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4069 FIXME("(%p) : Created shader, Handle=%lx\n", This, Handle);
4070 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4071 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4072 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4073 } else { /* use a fvf, so desactivate the vshader decl */
4074 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4075 This->UpdateStateBlock->vertexShaderDecl = NULL;
4076 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4077 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4079 /* Handle recording of state blocks */
4080 if (This->isRecordingState) {
4081 TRACE("Recording... not performing anything\n");
4082 return D3D_OK;
4085 * TODO: merge HAL shaders context switching from prototype
4087 return D3D_OK;
4089 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4090 ICOM_THIS(IDirect3DDevice8Impl,iface);
4091 TRACE("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4092 *pHandle = This->StateBlock->VertexShader;
4093 return D3D_OK;
4096 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4097 ICOM_THIS(IDirect3DDevice8Impl,iface);
4098 IDirect3DVertexShaderImpl* object;
4099 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4101 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4102 return D3DERR_INVALIDCALL;
4106 * Delete Vertex Shader
4108 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4109 if (NULL == object) {
4110 return D3DERR_INVALIDCALL;
4112 FIXME("(%p) : freing VertexShader %p\n", This, object);
4113 /* TODO: check validity of object */
4114 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4115 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4116 HeapFree(GetProcessHeap(), 0, (void *)object);
4117 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4120 * Delete Vertex Shader Declaration
4122 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4123 if (NULL == attached_decl) {
4124 return D3DERR_INVALIDCALL;
4126 FIXME("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4127 /* TODO: check validity of object */
4128 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4129 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4130 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4132 return D3D_OK;
4135 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4136 ICOM_THIS(IDirect3DDevice8Impl,iface);
4138 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4139 ERR("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4140 return D3DERR_INVALIDCALL;
4142 if (NULL == pConstantData) {
4143 return D3DERR_INVALIDCALL;
4145 if (ConstantCount > 1) {
4146 FLOAT* f = (FLOAT*)pConstantData;
4147 UINT i;
4148 TRACE("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4149 for (i = 0; i < ConstantCount; ++i) {
4150 TRACE("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4151 f += 4;
4153 } else {
4154 FLOAT* f = (FLOAT*)pConstantData;
4155 TRACE("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4157 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4158 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4159 return D3D_OK;
4161 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4162 ICOM_THIS(IDirect3DDevice8Impl,iface);
4164 TRACE("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4165 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4166 return D3DERR_INVALIDCALL;
4168 if (NULL == pConstantData) {
4169 return D3DERR_INVALIDCALL;
4171 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4172 return D3D_OK;
4174 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4175 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4176 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4178 attached_decl = VERTEX_SHADER_DECL(Handle);
4179 if (NULL == attached_decl) {
4180 return D3DERR_INVALIDCALL;
4182 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4184 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4185 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4186 IDirect3DVertexShaderImpl* object;
4188 object = VERTEX_SHADER(Handle);
4189 if (NULL == object) {
4190 return D3DERR_INVALIDCALL;
4192 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4195 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4196 ICOM_THIS(IDirect3DDevice8Impl,iface);
4197 IDirect3DIndexBuffer8 *oldIdxs;
4199 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4200 oldIdxs = This->StateBlock->pIndexData;
4202 This->UpdateStateBlock->Changed.Indices = TRUE;
4203 This->UpdateStateBlock->Set.Indices = TRUE;
4204 This->UpdateStateBlock->pIndexData = pIndexData;
4205 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4207 /* Handle recording of state blocks */
4208 if (This->isRecordingState) {
4209 TRACE("Recording... not performing anything\n");
4210 return D3D_OK;
4213 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4214 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4215 return D3D_OK;
4217 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4218 ICOM_THIS(IDirect3DDevice8Impl,iface);
4219 FIXME("(%p) : stub\n", This);
4221 *ppIndexData = This->StateBlock->pIndexData;
4222 /* up ref count on ppindexdata */
4223 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4224 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4226 return D3D_OK;
4228 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4229 ICOM_THIS(IDirect3DDevice8Impl,iface);
4230 IDirect3DPixelShaderImpl* object;
4231 UINT i;
4233 FIXME("(%p) : PixelShader not fully supported yet\n", This);
4234 if (NULL == pFunction || NULL == pHandle) {
4235 return D3DERR_INVALIDCALL;
4237 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4238 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4239 return D3DERR_OUTOFVIDEOMEMORY;
4241 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DPixelShaderImpl));
4242 if (NULL == object) {
4243 return D3DERR_OUTOFVIDEOMEMORY;
4246 object->data = NULL; /* TODO */
4248 PixelShaders[i] = object;
4249 *pHandle = VS_HIGHESTFIXEDFXF + i;
4251 object->function = pFunction;
4252 for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
4253 object->functionLength = i + 1;
4255 return D3D_OK;
4257 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4258 ICOM_THIS(IDirect3DDevice8Impl,iface);
4260 This->UpdateStateBlock->PixelShader = Handle;
4261 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4262 This->UpdateStateBlock->Set.pixelShader = TRUE;
4264 /* Handle recording of state blocks */
4265 if (This->isRecordingState) {
4266 TRACE("Recording... not performing anything\n");
4267 return D3D_OK;
4270 /* FIXME: Quieten when not being used */
4271 if (Handle != 0) {
4272 FIXME("(%p) : stub %ld\n", This, Handle);
4273 } else {
4274 TRACE("(%p) : stub %ld\n", This, Handle);
4277 return D3D_OK;
4279 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4280 ICOM_THIS(IDirect3DDevice8Impl,iface);
4281 TRACE("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4282 *pHandle = This->StateBlock->PixelShader;
4283 return D3D_OK;
4286 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4287 ICOM_THIS(IDirect3DDevice8Impl,iface);
4288 IDirect3DPixelShaderImpl* object;
4290 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4291 return D3DERR_INVALIDCALL;
4293 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4294 TRACE("(%p) : freeing PixelShader %p\n", This, object);
4295 /* TODO: check validity of object before free */
4296 HeapFree(GetProcessHeap(), 0, (void *)object);
4297 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
4298 return D3D_OK;
4301 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,CONST void* pConstantData, DWORD ConstantCount) {
4302 ICOM_THIS(IDirect3DDevice8Impl,iface);
4303 FIXME("(%p) : stub\n", This);
4304 return D3D_OK;
4306 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,void* pConstantData, DWORD ConstantCount) {
4307 ICOM_THIS(IDirect3DDevice8Impl,iface);
4308 FIXME("(%p) : stub\n", This);
4309 return D3D_OK;
4311 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4312 ICOM_THIS(IDirect3DDevice8Impl,iface);
4313 IDirect3DPixelShaderImpl* object;
4315 object = PIXEL_SHADER(Handle);
4316 if (NULL == object) {
4317 return D3DERR_INVALIDCALL;
4319 if (NULL == pData) {
4320 *pSizeOfData = object->functionLength;
4321 return D3D_OK;
4323 if (*pSizeOfData < object->functionLength) {
4324 *pSizeOfData = object->functionLength;
4325 return D3DERR_MOREDATA;
4327 TRACE("(%p) : GetPixelShaderFunction copying to %p\n", This, pData);
4328 memcpy(pData, object->function, object->functionLength);
4329 return D3D_OK;
4331 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4332 ICOM_THIS(IDirect3DDevice8Impl,iface);
4333 FIXME("(%p) : stub\n", This); return D3D_OK;
4335 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4336 ICOM_THIS(IDirect3DDevice8Impl,iface);
4337 FIXME("(%p) : stub\n", This); return D3D_OK;
4339 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4340 ICOM_THIS(IDirect3DDevice8Impl,iface);
4341 FIXME("(%p) : stub\n", This); return D3D_OK;
4344 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4345 IDirect3DVertexBuffer8 *oldSrc;
4346 ICOM_THIS(IDirect3DDevice8Impl,iface);
4348 oldSrc = This->StateBlock->stream_source[StreamNumber];
4349 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4351 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4352 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4353 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4354 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4356 /* Handle recording of state blocks */
4357 if (This->isRecordingState) {
4358 TRACE("Recording... not performing anything\n");
4359 return D3D_OK;
4362 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4363 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4364 return D3D_OK;
4366 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4367 ICOM_THIS(IDirect3DDevice8Impl,iface);
4368 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4369 *pStream = This->StateBlock->stream_source[StreamNumber];
4370 *pStride = This->StateBlock->stream_stride[StreamNumber];
4371 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4372 return D3D_OK;
4376 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4378 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4379 IDirect3DDevice8Impl_QueryInterface,
4380 IDirect3DDevice8Impl_AddRef,
4381 IDirect3DDevice8Impl_Release,
4382 IDirect3DDevice8Impl_TestCooperativeLevel,
4383 IDirect3DDevice8Impl_GetAvailableTextureMem,
4384 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4385 IDirect3DDevice8Impl_GetDirect3D,
4386 IDirect3DDevice8Impl_GetDeviceCaps,
4387 IDirect3DDevice8Impl_GetDisplayMode,
4388 IDirect3DDevice8Impl_GetCreationParameters,
4389 IDirect3DDevice8Impl_SetCursorProperties,
4390 IDirect3DDevice8Impl_SetCursorPosition,
4391 IDirect3DDevice8Impl_ShowCursor,
4392 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4393 IDirect3DDevice8Impl_Reset,
4394 IDirect3DDevice8Impl_Present,
4395 IDirect3DDevice8Impl_GetBackBuffer,
4396 IDirect3DDevice8Impl_GetRasterStatus,
4397 IDirect3DDevice8Impl_SetGammaRamp,
4398 IDirect3DDevice8Impl_GetGammaRamp,
4399 IDirect3DDevice8Impl_CreateTexture,
4400 IDirect3DDevice8Impl_CreateVolumeTexture,
4401 IDirect3DDevice8Impl_CreateCubeTexture,
4402 IDirect3DDevice8Impl_CreateVertexBuffer,
4403 IDirect3DDevice8Impl_CreateIndexBuffer,
4404 IDirect3DDevice8Impl_CreateRenderTarget,
4405 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4406 IDirect3DDevice8Impl_CreateImageSurface,
4407 IDirect3DDevice8Impl_CopyRects,
4408 IDirect3DDevice8Impl_UpdateTexture,
4409 IDirect3DDevice8Impl_GetFrontBuffer,
4410 IDirect3DDevice8Impl_SetRenderTarget,
4411 IDirect3DDevice8Impl_GetRenderTarget,
4412 IDirect3DDevice8Impl_GetDepthStencilSurface,
4413 IDirect3DDevice8Impl_BeginScene,
4414 IDirect3DDevice8Impl_EndScene,
4415 IDirect3DDevice8Impl_Clear,
4416 IDirect3DDevice8Impl_SetTransform,
4417 IDirect3DDevice8Impl_GetTransform,
4418 IDirect3DDevice8Impl_MultiplyTransform,
4419 IDirect3DDevice8Impl_SetViewport,
4420 IDirect3DDevice8Impl_GetViewport,
4421 IDirect3DDevice8Impl_SetMaterial,
4422 IDirect3DDevice8Impl_GetMaterial,
4423 IDirect3DDevice8Impl_SetLight,
4424 IDirect3DDevice8Impl_GetLight,
4425 IDirect3DDevice8Impl_LightEnable,
4426 IDirect3DDevice8Impl_GetLightEnable,
4427 IDirect3DDevice8Impl_SetClipPlane,
4428 IDirect3DDevice8Impl_GetClipPlane,
4429 IDirect3DDevice8Impl_SetRenderState,
4430 IDirect3DDevice8Impl_GetRenderState,
4431 IDirect3DDevice8Impl_BeginStateBlock,
4432 IDirect3DDevice8Impl_EndStateBlock,
4433 IDirect3DDevice8Impl_ApplyStateBlock,
4434 IDirect3DDevice8Impl_CaptureStateBlock,
4435 IDirect3DDevice8Impl_DeleteStateBlock,
4436 IDirect3DDevice8Impl_CreateStateBlock,
4437 IDirect3DDevice8Impl_SetClipStatus,
4438 IDirect3DDevice8Impl_GetClipStatus,
4439 IDirect3DDevice8Impl_GetTexture,
4440 IDirect3DDevice8Impl_SetTexture,
4441 IDirect3DDevice8Impl_GetTextureStageState,
4442 IDirect3DDevice8Impl_SetTextureStageState,
4443 IDirect3DDevice8Impl_ValidateDevice,
4444 IDirect3DDevice8Impl_GetInfo,
4445 IDirect3DDevice8Impl_SetPaletteEntries,
4446 IDirect3DDevice8Impl_GetPaletteEntries,
4447 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4448 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4449 IDirect3DDevice8Impl_DrawPrimitive,
4450 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4451 IDirect3DDevice8Impl_DrawPrimitiveUP,
4452 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4453 IDirect3DDevice8Impl_ProcessVertices,
4454 IDirect3DDevice8Impl_CreateVertexShader,
4455 IDirect3DDevice8Impl_SetVertexShader,
4456 IDirect3DDevice8Impl_GetVertexShader,
4457 IDirect3DDevice8Impl_DeleteVertexShader,
4458 IDirect3DDevice8Impl_SetVertexShaderConstant,
4459 IDirect3DDevice8Impl_GetVertexShaderConstant,
4460 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4461 IDirect3DDevice8Impl_GetVertexShaderFunction,
4462 IDirect3DDevice8Impl_SetStreamSource,
4463 IDirect3DDevice8Impl_GetStreamSource,
4464 IDirect3DDevice8Impl_SetIndices,
4465 IDirect3DDevice8Impl_GetIndices,
4466 IDirect3DDevice8Impl_CreatePixelShader,
4467 IDirect3DDevice8Impl_SetPixelShader,
4468 IDirect3DDevice8Impl_GetPixelShader,
4469 IDirect3DDevice8Impl_DeletePixelShader,
4470 IDirect3DDevice8Impl_SetPixelShaderConstant,
4471 IDirect3DDevice8Impl_GetPixelShaderConstant,
4472 IDirect3DDevice8Impl_GetPixelShaderFunction,
4473 IDirect3DDevice8Impl_DrawRectPatch,
4474 IDirect3DDevice8Impl_DrawTriPatch,
4475 IDirect3DDevice8Impl_DeletePatch