- surface pool init fixes
[wine/wine-gecko.git] / dlls / d3d8 / device.c
blob90a5f7165624810df7b9d2493350d8d9de495c69
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 case D3DRTYPE_CUBETEXTURE:
437 r = 0.0f; q = 0.0f; /* Avoid compiler warnings, need these vars later for other textures */
438 FIXME("Unhandled texture type: D3DRTYPE_CUBETEXTURE\n");
439 break;
441 default:
442 r = 0.0f; q = 0.0f; /* Avoid compiler warnings, need these vars later for other textures */
443 FIXME("Unhandled texture type: %u\n", IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo]));
445 } else {
446 /* Note I have seen a program actually do this, so just hide it and continue */
447 VTRACE(("Very odd - texture requested in FVF but not bound!\n"));
452 /** if vertex shader program specified ... using it */
453 if (TRUE == useVertexShaderFunction) {
456 * this code must become the really
457 * vs input params init
459 * because its possible to use input registers for anything
460 * and some samples use registers for other things than they are
461 * declared
464 /**
465 * no really valid declaration, user defined input register use
466 * so fill input registers as described in vertex shader declaration
468 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
469 (!isIndexed) ? (vx_index * skip) :
470 (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) :
471 ((pIdxBufL[StartIdx + vx_index]) * skip));
473 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
474 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
476 TRACE_VECTOR(vertex_shader->output.oPos);
477 TRACE_VECTOR(vertex_shader->output.oD[0]);
478 TRACE_VECTOR(vertex_shader->output.oD[1]);
479 TRACE_VECTOR(vertex_shader->output.oT[0]);
480 TRACE_VECTOR(vertex_shader->output.oT[1]);
481 TRACE_VECTOR(vertex_shader->input.V[0]);
482 TRACE_VECTOR(vertex_shader->data->C[0]);
483 TRACE_VECTOR(vertex_shader->data->C[1]);
484 TRACE_VECTOR(vertex_shader->data->C[2]);
485 TRACE_VECTOR(vertex_shader->data->C[3]);
486 TRACE_VECTOR(vertex_shader->data->C[4]);
487 TRACE_VECTOR(vertex_shader->data->C[5]);
488 TRACE_VECTOR(vertex_shader->data->C[6]);
489 TRACE_VECTOR(vertex_shader->data->C[7]);
491 x = vertex_shader->output.oPos.x;
492 y = vertex_shader->output.oPos.y;
493 z = vertex_shader->output.oPos.z;
495 if (1.0f != vertex_shader->output.oPos.w || isRHW) {
496 rhw = vertex_shader->output.oPos.w;
498 /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
499 glColor4fv((float*) &vertex_shader->output.oD[0]);
501 /* Requires secondary color extensions to compile... */
502 #if defined(GL_VERSION_1_4)
503 glSecondaryColor3fv((float*) &vertex_shader->output.oD[1]);
504 checkGLcall("glSecondaryColor3fv");
505 #else
506 if (checkGLSupport(EXT_SECONDARY_COLOR)) {
507 /*specularColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[1]);*/
508 /*GLExtCall(glSecondaryColor3fvEXT)((float*) &vertex_shader->output.oD[1]);*/
509 /*checkGLcall("glSecondaryColor3fvEXT");*/
511 #endif
512 /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
513 for (textureNo = 0; textureNo < 4; ++textureNo) {
514 float s, t, r, q;
516 if (!(This->isMultiTexture) && textureNo > 0) {
517 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
518 continue ;
520 /* Query tex coords */
521 if (This->StateBlock->textures[textureNo] != NULL) {
522 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
523 case D3DRTYPE_TEXTURE:
524 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
525 s = vertex_shader->output.oT[textureNo].x;
526 t = vertex_shader->output.oT[textureNo].y;
527 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
528 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
529 VTRACE("Skip tex coords, as being system generated\n");
530 } else {
531 if (This->isMultiTexture) {
532 #if defined(GL_VERSION_1_3)
533 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
534 #else
535 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
536 #endif
537 /*checkGLcall("glMultiTexCoord2fARB");*/
538 } else {
539 glTexCoord2f(s, t);
540 /*checkGLcall("gTexCoord2f");*/
543 break;
545 case D3DRTYPE_VOLUMETEXTURE:
546 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
547 s = vertex_shader->output.oT[textureNo].x;
548 t = vertex_shader->output.oT[textureNo].y;
549 r = vertex_shader->output.oT[textureNo].z;
550 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
551 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
552 VTRACE("Skip tex coords, as being system generated\n");
553 } else {
554 if (This->isMultiTexture) {
555 #if defined(GL_VERSION_1_3)
556 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
557 #else
558 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
559 #endif
560 /*checkGLcall("glMultiTexCoord2fARB");*/
561 } else {
562 glTexCoord3f(s, t, r);
563 /*checkGLcall("gTexCoord3f");*/
566 break;
568 default:
569 /* Avoid compiler warnings, need these vars later for other textures */
570 r = 0.0f; q = 0.0f;
571 FIXME("Unhandled texture type\n");
576 if (1.0f == rhw || rhw < 0.01f) {
577 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
578 glVertex3f(x, y, z);
579 /*checkGLcall("glVertex3f");*/
580 } else {
581 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
582 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
583 /*checkGLcall("glVertex4f");*/
585 } else {
586 /**
587 * FALSE == useVertexShaderFunction
588 * using std FVF code
591 /* Handle these vertexes */
592 if (isDiffuse) {
593 glColor4ub((diffuseColor >> 16) & 0xFF,
594 (diffuseColor >> 8) & 0xFF,
595 (diffuseColor >> 0) & 0xFF,
596 (diffuseColor >> 24) & 0xFF);
597 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
598 ((diffuseColor >> 16) & 0xFF) / 255.0f,
599 ((diffuseColor >> 8) & 0xFF) / 255.0f,
600 ((diffuseColor >> 0) & 0xFF) / 255.0f,
601 ((diffuseColor >> 24) & 0xFF) / 255.0f));
604 if (normal) {
605 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
606 glNormal3f(nx, ny, nz);
607 glVertex3f(x, y, z);
608 } else {
609 if (1.0f == rhw || rhw < 0.01f) {
610 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
611 glVertex3f(x, y, z);
612 } else {
613 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
614 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
619 if (!isIndexed) {
620 curVtx = curVtx + skip;
624 glEnd();
625 checkGLcall("glEnd and previous calls");
627 } else {
628 TRACE("Using fast vertex array code\n");
630 /* Faster version, harder to debug */
631 /* Shuffle to the beginning of the vertexes to render and index from there */
632 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
633 curPos = curVtx;
635 /* Set up the vertex pointers */
636 if (isRHW) {
637 glVertexPointer(4, GL_FLOAT, skip, curPos);
638 checkGLcall("glVertexPointer(4, ...)");
639 curPos += 4 * sizeof(float);
640 } else {
641 glVertexPointer(3, GL_FLOAT, skip, curPos);
642 checkGLcall("glVertexPointer(3, ...)");
643 curPos += 3 * sizeof(float);
645 glEnableClientState(GL_VERTEX_ARRAY);
646 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
648 if (numBlends > 0) {
649 /* no such functionality in the fixed function GL pipeline */
650 /* FIXME: Wont get here as will drop to slow method */
651 /* FIXME("Cannot handle blending data here in openGl\n");*/
652 if (checkGLSupport(ARB_VERTEX_BLEND)) {
653 FIXME("TODO\n");
654 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
655 FIXME("TODO\n");
657 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
658 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
659 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
660 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
662 curPos += numBlends * sizeof(float);
663 } else {
664 FIXME("unsupported blending in openGl\n");
666 } else {
667 if (checkGLSupport(ARB_VERTEX_BLEND)) {
668 FIXME("TODO\n");
669 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
670 FIXME("TODO\n");
672 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
673 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
679 if (normal) {
680 glNormalPointer(GL_FLOAT, skip, curPos);
681 checkGLcall("glNormalPointer");
682 glEnableClientState(GL_NORMAL_ARRAY);
683 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
684 curPos += 3 * sizeof(float);
685 } else {
686 glDisableClientState(GL_NORMAL_ARRAY);
687 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
688 glNormal3f(0, 0, 1);
689 checkGLcall("glNormal3f(0, 0, 1)");
692 if (isPtSize) {
693 /* no such functionality in the fixed function GL pipeline */
694 /* FIXME: Wont get here as will drop to slow method */
695 FIXME("Cannot change ptSize here in openGl\n");
696 curPos = curPos + sizeof(float);
699 if (isDiffuse) {
700 glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
701 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
702 glEnableClientState(GL_COLOR_ARRAY);
703 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
704 curPos += sizeof(DWORD);
706 else {
707 glDisableClientState(GL_COLOR_ARRAY);
708 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
709 glColor4f(1, 1, 1, 1);
710 checkGLcall("glColor4f(1, 1, 1, 1)");
713 /* Requires secondary color extensions to compile... */
714 if (isSpecular) {
715 #if defined(GL_VERSION_1_4)
716 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
717 checkGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos)");
718 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
719 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
720 #else
721 # if 0
722 /* FIXME: check for GL_EXT_secondary_color */
723 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos);
724 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
725 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
726 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
727 # endif
728 #endif
729 curPos += sizeof(DWORD);
730 } else {
731 #if defined(GL_VERSION_1_4)
732 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
733 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
734 glSecondaryColor3f(0, 0, 0);
735 checkGLcall("glSecondaryColor3f(0, 0, 0)");
736 #else
737 #if 0
738 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
739 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
740 glSecondaryColor3fEXT(0, 0, 0);
741 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
742 #endif
743 #endif
747 /* ToDo: Texture coords */
748 for (textureNo = 0;textureNo<numTextures; textureNo++) {
750 /* Query tex coords */
751 #if defined(GL_VERSION_1_3)
752 glClientActiveTexture(GL_TEXTURE0 + textureNo);
753 #else
754 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
755 #endif
756 if (This->StateBlock->textures[textureNo] != NULL) {
757 enableTexture = TRUE;
758 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
759 case D3DRTYPE_TEXTURE:
760 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
761 VTRACE("Skip tex coords, as being system generated\n");
762 } else {
763 glTexCoordPointer(2, GL_FLOAT, skip, curPos);
764 checkGLcall("glTexCoordPointer(2, ...)");
766 curPos += 2*sizeof(float);
767 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
768 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
769 break;
771 case D3DRTYPE_VOLUMETEXTURE:
772 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
773 VTRACE("Skip tex coords, as being system generated\n");
774 } else {
775 glTexCoordPointer(3, GL_FLOAT, skip, curPos);
776 checkGLcall("glTexCoordPointer(3, ...)");
778 curPos += 3*sizeof(float);
779 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
780 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
781 break;
783 default:
784 FIXME("Unhandled texture type\n");
785 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
786 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
789 } else {
791 /* Note I have seen a program actually do this, so just hide it and continue */
792 TRACE("Very odd - texture requested in FVF but not bound!\n");
793 #if defined(GL_VERSION_1_3)
794 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
795 checkGLcall("glMultiTexCoord4f(... , 0, 0, 0, 1)");
796 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
797 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
798 #else
799 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
800 checkGLcall("glMultiTexCoord4fARB(... , 0, 0, 0, 1)");
801 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
802 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
803 #endif
808 /* Finally do the drawing */
809 if (isIndexed) {
811 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
812 if (idxBytes==2) {
813 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
814 glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
815 (char *)idxData+(2 * StartIdx));
816 #else
817 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
818 GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
819 #endif
820 } else {
821 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
822 glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
823 (char *)idxData+(4 * StartIdx));
824 #else
825 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
826 GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
827 #endif
829 checkGLcall("glDrawRangeElements");
831 } else {
833 /* Note first is now zero as we shuffled along earlier */
834 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
835 glDrawArrays(primType, 0, NumVertexes);
836 checkGLcall("glDrawArrays");
841 /* If no normals, restore previous lighting state */
842 if (!normal) {
843 if (isLightingOn) glEnable(GL_LIGHTING);
844 else glDisable(GL_LIGHTING);
845 TRACE("Restored lighting to original state\n");
849 LEAVE_GL();
851 TRACE("glEnd\n");
855 Simple utility routines used for dx -> gl mapping of byte formats
857 SHORT bytesPerPixel(D3DFORMAT fmt) {
858 SHORT retVal;
860 switch (fmt) {
861 /* color buffer */
862 case D3DFMT_A4R4G4B4: retVal = 2; break;
863 case D3DFMT_A8R8G8B8: retVal = 4; break;
864 case D3DFMT_X8R8G8B8: retVal = 4; break;
865 case D3DFMT_R8G8B8: retVal = 3; break;
866 case D3DFMT_R5G6B5: retVal = 2; break;
867 case D3DFMT_A1R5G5B5: retVal = 2; break;
868 /* depth/stencil buffer */
869 case D3DFMT_D16_LOCKABLE: retVal = 2; break;
870 case D3DFMT_D32: retVal = 4; break;
871 case D3DFMT_D15S1: retVal = 2; break;
872 case D3DFMT_D24S8: retVal = 4; break;
873 case D3DFMT_D16: retVal = 2; break;
874 case D3DFMT_D24X8: retVal = 4; break;
875 case D3DFMT_D24X4S4: retVal = 4; break;
876 /* unknown */
877 case D3DFMT_UNKNOWN:
878 /* Guess at the highest value of the above */
879 TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %d\n", fmt);
880 retVal = 4;
881 break;
882 default:
883 FIXME("Unhandled fmt %d\n", fmt);
884 retVal = 4;
886 TRACE("bytes/Pxl for fmt %d = %d\n", fmt, retVal);
887 return retVal;
890 GLint fmt2glintFmt(D3DFORMAT fmt) {
891 GLint retVal;
893 switch (fmt) {
894 case D3DFMT_A4R4G4B4: retVal = GL_RGBA4; break;
895 case D3DFMT_A8R8G8B8: retVal = GL_RGBA8; break;
896 case D3DFMT_X8R8G8B8: retVal = GL_RGB8; break;
897 case D3DFMT_R8G8B8: retVal = GL_RGB8; break;
898 case D3DFMT_R5G6B5: retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
899 case D3DFMT_A1R5G5B5: retVal = GL_RGB5_A1; break;
900 default:
901 FIXME("Unhandled fmt %d\n", fmt);
902 retVal = 4;
904 TRACE("fmt2glintFmt for fmt %d = %x\n", fmt, retVal);
905 return retVal;
907 GLenum fmt2glFmt(D3DFORMAT fmt) {
908 GLenum retVal;
910 switch (fmt) {
911 case D3DFMT_A4R4G4B4: retVal = GL_BGRA; break;
912 case D3DFMT_A8R8G8B8: retVal = GL_BGRA; break;
913 case D3DFMT_X8R8G8B8: retVal = GL_BGRA; break;
914 case D3DFMT_R8G8B8: retVal = GL_BGR; break;
915 case D3DFMT_R5G6B5: retVal = GL_RGB; break;
916 case D3DFMT_A1R5G5B5: retVal = GL_BGRA; break;
917 default:
918 FIXME("Unhandled fmt %d\n", fmt);
919 retVal = 4;
921 TRACE("fmt2glFmt for fmt %d = %x\n", fmt, retVal);
922 return retVal;
924 DWORD fmt2glType(D3DFORMAT fmt) {
925 GLenum retVal;
927 switch (fmt) {
928 case D3DFMT_A4R4G4B4: retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
929 case D3DFMT_A8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
930 case D3DFMT_X8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
931 case D3DFMT_R5G6B5: retVal = GL_UNSIGNED_SHORT_5_6_5_REV; break;
932 case D3DFMT_R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
933 case D3DFMT_A1R5G5B5: retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
934 default:
935 FIXME("Unhandled fmt %d\n", fmt);
936 retVal = 4;
938 TRACE("fmt2glType for fmt %d = %x\n", fmt, retVal);
939 return retVal;
942 int SOURCEx_RGB_EXT(DWORD arg) {
943 switch(arg) {
944 case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
945 case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
946 case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
947 case D3DTSS_ALPHAARG0:
948 case D3DTSS_ALPHAARG1:
949 case D3DTSS_ALPHAARG2:
950 default:
951 FIXME("Invalid arg %ld\n", arg);
952 return GL_SOURCE0_RGB_EXT;
955 int OPERANDx_RGB_EXT(DWORD arg) {
956 switch(arg) {
957 case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
958 case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
959 case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
960 case D3DTSS_ALPHAARG0:
961 case D3DTSS_ALPHAARG1:
962 case D3DTSS_ALPHAARG2:
963 default:
964 FIXME("Invalid arg %ld\n", arg);
965 return GL_OPERAND0_RGB_EXT;
968 int SOURCEx_ALPHA_EXT(DWORD arg) {
969 switch(arg) {
970 case D3DTSS_ALPHAARG0: return GL_SOURCE2_ALPHA_EXT;
971 case D3DTSS_ALPHAARG1: return GL_SOURCE0_ALPHA_EXT;
972 case D3DTSS_ALPHAARG2: return GL_SOURCE1_ALPHA_EXT;
973 case D3DTSS_COLORARG0:
974 case D3DTSS_COLORARG1:
975 case D3DTSS_COLORARG2:
976 default:
977 FIXME("Invalid arg %ld\n", arg);
978 return GL_SOURCE0_ALPHA_EXT;
981 int OPERANDx_ALPHA_EXT(DWORD arg) {
982 switch(arg) {
983 case D3DTSS_ALPHAARG0: return GL_OPERAND2_ALPHA_EXT;
984 case D3DTSS_ALPHAARG1: return GL_OPERAND0_ALPHA_EXT;
985 case D3DTSS_ALPHAARG2: return GL_OPERAND1_ALPHA_EXT;
986 case D3DTSS_COLORARG0:
987 case D3DTSS_COLORARG1:
988 case D3DTSS_COLORARG2:
989 default:
990 FIXME("Invalid arg %ld\n", arg);
991 return GL_OPERAND0_ALPHA_EXT;
994 GLenum StencilOp(DWORD op) {
995 switch(op) {
996 case D3DSTENCILOP_KEEP : return GL_KEEP;
997 case D3DSTENCILOP_ZERO : return GL_ZERO;
998 case D3DSTENCILOP_REPLACE : return GL_REPLACE;
999 case D3DSTENCILOP_INCRSAT : return GL_INCR;
1000 case D3DSTENCILOP_DECRSAT : return GL_DECR;
1001 case D3DSTENCILOP_INVERT : return GL_INVERT;
1002 case D3DSTENCILOP_INCR : FIXME("Unsupported stencil op D3DSTENCILOP_INCR\n");
1003 return GL_INCR; /* Fixme - needs to support wrap */
1004 case D3DSTENCILOP_DECR : FIXME("Unsupported stencil op D3DSTENCILOP_DECR\n");
1005 return GL_DECR; /* Fixme - needs to support wrap */
1006 default:
1007 FIXME("Invalid stencil op %ld\n", op);
1008 return GL_ALWAYS;
1013 * @nodoc: todo
1015 void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand)
1017 BOOL isAlphaReplicate = FALSE;
1018 BOOL isComplement = FALSE;
1020 *operand = GL_SRC_COLOR;
1021 *source = GL_TEXTURE;
1023 /* Catch alpha replicate */
1024 if (iValue & D3DTA_ALPHAREPLICATE) {
1025 iValue = iValue & ~D3DTA_ALPHAREPLICATE;
1026 isAlphaReplicate = TRUE;
1029 /* Catch Complement */
1030 if (iValue & D3DTA_COMPLEMENT) {
1031 iValue = iValue & ~D3DTA_COMPLEMENT;
1032 isComplement = TRUE;
1035 /* Calculate the operand */
1036 if (isAlphaReplicate && !isComplement) {
1037 *operand = GL_SRC_ALPHA;
1038 } else if (isAlphaReplicate && isComplement) {
1039 *operand = GL_ONE_MINUS_SRC_ALPHA;
1040 } else if (isComplement) {
1041 if (isAlphaArg) {
1042 *operand = GL_ONE_MINUS_SRC_ALPHA;
1043 } else {
1044 *operand = GL_ONE_MINUS_SRC_COLOR;
1046 } else {
1047 if (isAlphaArg) {
1048 *operand = GL_SRC_ALPHA;
1049 } else {
1050 *operand = GL_SRC_COLOR;
1054 /* Calculate the source */
1055 switch (iValue & D3DTA_SELECTMASK) {
1056 case D3DTA_CURRENT: *source = GL_PREVIOUS_EXT;
1057 break;
1058 case D3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT;
1059 break;
1060 case D3DTA_TEXTURE: *source = GL_TEXTURE;
1061 break;
1062 case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT;
1063 break;
1064 case D3DTA_SPECULAR:
1066 * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
1067 * isnt supported until base GL supports it
1068 * There is no concept of temp registers as far as I can tell
1071 default:
1072 FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
1073 *source = GL_TEXTURE;
1078 /* Apply the current values to the specified texture stage */
1079 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
1080 ICOM_THIS(IDirect3DDevice8Impl,iface);
1081 int i=0;
1082 float col[4];
1084 /* Make appropriate texture active */
1085 if (This->isMultiTexture) {
1086 #if defined(GL_VERSION_1_3)
1087 glActiveTexture(GL_TEXTURE0 + Stage);
1088 #else
1089 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1090 #endif
1091 checkGLcall("glActiveTextureARB");
1092 } else if (Stage > 0) {
1093 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1096 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
1097 for (i=1; i<HIGHEST_TEXTURE_STATE; i++) {
1098 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1101 /* Note the D3DRS value applies to all textures, but GL has one
1102 per texture, so apply it now ready to be used! */
1103 col[0] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR]>> 16) & 0xFF) / 255.0;
1104 col[1] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 8 ) & 0xFF) / 255.0;
1105 col[2] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 0 ) & 0xFF) / 255.0;
1106 col[3] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 24 ) & 0xFF) / 255.0;
1107 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1108 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1110 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1113 /* IDirect3D IUnknown parts follow: */
1114 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1116 ICOM_THIS(IDirect3DDevice8Impl,iface);
1118 if (IsEqualGUID(riid, &IID_IUnknown)
1119 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1120 IDirect3DDevice8Impl_AddRef(iface);
1121 *ppobj = This;
1122 return D3D_OK;
1125 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1126 return E_NOINTERFACE;
1129 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1130 ICOM_THIS(IDirect3DDevice8Impl,iface);
1131 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1132 return ++(This->ref);
1135 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1136 ICOM_THIS(IDirect3DDevice8Impl,iface);
1137 ULONG ref = --This->ref;
1138 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1139 if (ref == 0) {
1140 HeapFree(GetProcessHeap(), 0, This);
1142 return ref;
1145 /* IDirect3DDevice Interface follow: */
1146 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1147 ICOM_THIS(IDirect3DDevice8Impl,iface);
1148 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
1149 return D3D_OK;
1152 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1153 ICOM_THIS(IDirect3DDevice8Impl,iface);
1154 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1156 * pretend we have 32MB of any type of memory queried.
1158 return (1024*1024*32);
1161 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1162 ICOM_THIS(IDirect3DDevice8Impl,iface);
1163 FIXME("(%p) : stub\n", This); return D3D_OK;
1165 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1166 ICOM_THIS(IDirect3DDevice8Impl,iface);
1167 TRACE("(%p) : returning %p\n", This, This->direct3d8);
1169 /* Inc ref count */
1170 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1172 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1173 return D3D_OK;
1175 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1176 ICOM_THIS(IDirect3DDevice8Impl,iface);
1177 FIXME("(%p) : stub, calling idirect3d for now\n", This);
1178 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1179 return D3D_OK;
1181 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1183 HDC hdc;
1184 int bpp = 0;
1186 ICOM_THIS(IDirect3DDevice8Impl,iface);
1187 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
1188 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
1189 pMode->RefreshRate = 85; /*FIXME: How to identify? */
1191 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1192 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1193 DeleteDC(hdc);
1195 switch (bpp) {
1196 case 8: pMode->Format = D3DFMT_R8G8B8; break;
1197 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1198 case 24: pMode->Format = D3DFMT_R8G8B8; break;
1199 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1200 default:
1201 FIXME("Unrecognized display mode format\n");
1202 pMode->Format = D3DFMT_UNKNOWN;
1205 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%d)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format);
1206 return D3D_OK;
1208 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1209 ICOM_THIS(IDirect3DDevice8Impl,iface);
1210 TRACE("(%p) copying to %p\n", This, pParameters);
1211 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1212 return D3D_OK;
1214 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1215 ICOM_THIS(IDirect3DDevice8Impl,iface);
1216 FIXME("(%p) : stub\n", This); return D3D_OK;
1218 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace,DWORD Flags) {
1219 ICOM_THIS(IDirect3DDevice8Impl,iface);
1220 FIXME("(%p) : stub\n", This); return;
1222 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1223 ICOM_THIS(IDirect3DDevice8Impl,iface);
1224 FIXME("(%p) : stub\n", This); return D3D_OK;
1226 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1227 ICOM_THIS(IDirect3DDevice8Impl,iface);
1228 FIXME("(%p) : stub\n", This);
1229 *pSwapChain = NULL;
1230 return D3D_OK;
1232 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1233 ICOM_THIS(IDirect3DDevice8Impl,iface);
1234 FIXME("(%p) : stub\n", This); return D3D_OK;
1236 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1237 ICOM_THIS(IDirect3DDevice8Impl,iface);
1238 TRACE("(%p) : complete stub!\n", This);
1240 ENTER_GL();
1242 glXSwapBuffers(This->display, This->win);
1243 checkGLcall("glXSwapBuffers");
1245 LEAVE_GL();
1247 return D3D_OK;
1249 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
1250 ICOM_THIS(IDirect3DDevice8Impl,iface);
1251 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1252 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1254 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
1255 FIXME("Only one backBuffer currently supported\n");
1256 return D3DERR_INVALIDCALL;
1259 /* Note inc ref on returned surface */
1260 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1262 return D3D_OK;
1264 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1265 ICOM_THIS(IDirect3DDevice8Impl,iface);
1266 FIXME("(%p) : stub\n", This);
1267 return D3D_OK;
1269 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags,CONST D3DGAMMARAMP* pRamp) {
1270 ICOM_THIS(IDirect3DDevice8Impl,iface);
1271 FIXME("(%p) : stub\n", This); return;
1273 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1274 ICOM_THIS(IDirect3DDevice8Impl,iface);
1275 FIXME("(%p) : stub\n", This); return;
1277 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1278 D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture8** ppTexture) {
1279 IDirect3DTexture8Impl *object;
1280 int i;
1281 UINT tmpW;
1282 UINT tmpH;
1284 ICOM_THIS(IDirect3DDevice8Impl,iface);
1286 /* Allocate the storage for the device */
1287 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool);
1288 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1289 object->lpVtbl = &Direct3DTexture8_Vtbl;
1290 object->Device = This;
1291 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->device);*/
1292 object->ResourceType = D3DRTYPE_TEXTURE;
1293 object->ref = 1;
1294 object->width = Width;
1295 object->height = Height;
1296 object->levels = Levels;
1297 object->usage = Usage;
1298 object->format = Format;
1301 /* Calculate levels for mip mapping */
1302 if (Levels == 0) {
1303 object->levels++;
1304 tmpW = Width;
1305 tmpH = Height;
1306 while (tmpW > 1 && tmpH > 1) {
1307 tmpW = max(1, tmpW / 2);
1308 tmpH = max(1, tmpH / 2);
1309 object->levels++;
1311 TRACE("Calculated levels = %d\n", object->levels);
1314 /* Generate all the surfaces */
1315 tmpW = Width;
1316 tmpH = Height;
1317 for (i = 0; i < object->levels; i++)
1319 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1320 object->surfaces[i]->Container = (IUnknown*) object;
1321 /*IUnknown_AddRef(object->surfaces[i]->Container);*/
1322 object->surfaces[i]->myDesc.Usage = Usage;
1323 object->surfaces[i]->myDesc.Pool = Pool ;
1325 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1326 tmpW = max(1, tmpW / 2);
1327 tmpH = max(1, tmpH / 2);
1330 *ppTexture = (LPDIRECT3DTEXTURE8) object;
1331 return D3D_OK;
1333 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture) {
1335 IDirect3DVolumeTexture8Impl *object;
1336 int i;
1337 UINT tmpW;
1338 UINT tmpH;
1339 UINT tmpD;
1341 ICOM_THIS(IDirect3DDevice8Impl,iface);
1343 /* Allocate the storage for it */
1344 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);
1345 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1346 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1347 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1348 object->Device = This;
1349 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1350 object->ref = 1;
1352 object->width = Width;
1353 object->height = Height;
1354 object->depth = Depth;
1355 object->levels = Levels;
1356 object->usage = Usage;
1357 object->format = Format;
1359 /* Calculate levels for mip mapping */
1360 if (Levels == 0) {
1361 object->levels++;
1362 tmpW = Width;
1363 tmpH = Height;
1364 tmpD = Depth;
1365 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1366 tmpW = max(1, tmpW / 2);
1367 tmpH = max(1, tmpH / 2);
1368 tmpD = max(1, tmpD / 2);
1369 object->levels++;
1371 TRACE("Calculated levels = %d\n", object->levels);
1374 /* Generate all the surfaces */
1375 tmpW = Width;
1376 tmpH = Height;
1377 tmpD = Depth;
1379 for (i = 0; i < object->levels; i++)
1381 IDirect3DVolume8Impl *volume;
1383 /* Create the volume - No entry point for this seperately?? */
1384 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1385 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1387 volume->lpVtbl = &Direct3DVolume8_Vtbl;
1388 volume->Device = This;
1389 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) volume->Device);*/
1390 volume->ResourceType = D3DRTYPE_VOLUME;
1391 volume->Container = (IUnknown*) object;
1392 /*IUnknown_AddRef(volume->Container);*/
1393 volume->ref = 1;
1395 volume->myDesc.Width = Width;
1396 volume->myDesc.Height = Height;
1397 volume->myDesc.Depth = Depth;
1398 volume->myDesc.Format = Format;
1399 volume->myDesc.Type = D3DRTYPE_VOLUME;
1400 volume->myDesc.Pool = Pool;
1401 volume->myDesc.Usage = Usage;
1402 volume->bytesPerPixel = bytesPerPixel(Format);
1403 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
1404 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1406 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Depth, Format,
1407 volume, volume->allocatedMemory, volume->myDesc.Size);
1409 tmpW = max(1, tmpW / 2);
1410 tmpH = max(1, tmpH / 2);
1411 tmpD = max(1, tmpD / 2);
1414 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
1415 return D3D_OK;
1417 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
1419 IDirect3DCubeTexture8Impl *object;
1420 ICOM_THIS(IDirect3DDevice8Impl,iface);
1421 int i,j;
1422 UINT tmpW;
1424 /* Allocate the storage for it */
1425 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, Pool);
1426 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1427 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1428 object->ref = 1;
1429 object->Device = This;
1430 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1431 object->ResourceType = D3DRTYPE_CUBETEXTURE;
1433 object->edgeLength = EdgeLength;
1434 object->levels = Levels;
1435 object->usage = Usage;
1436 object->format = Format;
1438 /* Calculate levels for mip mapping */
1439 if (Levels == 0) {
1440 object->levels++;
1441 tmpW = EdgeLength;
1442 while (tmpW > 1) {
1443 tmpW = max(1, tmpW / 2);
1444 object->levels++;
1446 TRACE("Calculated levels = %d\n", object->levels);
1449 /* Generate all the surfaces */
1450 tmpW = EdgeLength;
1451 for (i = 0; i < object->levels; i++)
1453 /* Create the 6 faces */
1454 for (j = 0; j < 6; j++) {
1455 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1456 object->surfaces[j][i]->Container = (IUnknown*) object;
1457 /*IUnknown_AddRef(object->surfaces[j][i]->Container);*/
1458 object->surfaces[j][i]->myDesc.Usage = Usage;
1459 object->surfaces[j][i]->myDesc.Pool = Pool;
1461 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1462 tmpW = max(1, tmpW / 2);
1466 TRACE("(%p) : Iface@%p\n", This, object);
1467 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1468 return D3D_OK;
1470 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1471 IDirect3DVertexBuffer8Impl *object;
1473 ICOM_THIS(IDirect3DDevice8Impl,iface);
1475 /* Allocate the storage for the device */
1476 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1477 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1478 object->Device = This;
1479 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1480 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1481 object->ref = 1;
1482 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1483 object->currentDesc.Usage = Usage;
1484 object->currentDesc.Pool = Pool;
1485 object->currentDesc.FVF = FVF;
1486 object->currentDesc.Size = Size;
1488 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1490 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1492 return D3D_OK;
1494 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
1495 IDirect3DIndexBuffer8Impl *object;
1497 ICOM_THIS(IDirect3DDevice8Impl,iface);
1498 TRACE("(%p) : Len=%d, Use=%lx, Format=%x, Pool=%d\n", This, Length, Usage, Format, Pool);
1500 /* Allocate the storage for the device */
1501 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1502 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1503 object->Device = This;
1504 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1505 object->ref = 1;
1506 object->ResourceType = D3DRTYPE_INDEXBUFFER;
1508 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1509 object->currentDesc.Usage = Usage;
1510 object->currentDesc.Pool = Pool;
1511 object->currentDesc.Format = Format;
1512 object->currentDesc.Size = Length;
1514 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1516 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1518 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1520 return D3D_OK;
1522 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
1523 IDirect3DSurface8Impl *object;
1525 ICOM_THIS(IDirect3DDevice8Impl,iface);
1527 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1528 if (NULL == object) {
1529 *ppSurface = NULL;
1530 return D3DERR_OUTOFVIDEOMEMORY;
1532 *ppSurface = (LPDIRECT3DSURFACE8) object;
1533 object->lpVtbl = &Direct3DSurface8_Vtbl;
1534 object->Device = This;
1535 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1536 object->ResourceType = D3DRTYPE_SURFACE;
1537 object->Container = (IUnknown*) This;
1538 /*IUnknown_AddRef(object->Container);*/
1540 object->ref = 1;
1541 object->myDesc.Width = Width;
1542 object->myDesc.Height = Height;
1543 object->myDesc.Format = Format;
1544 object->myDesc.Type = D3DRTYPE_SURFACE;
1545 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
1546 object->myDesc.Pool = D3DPOOL_DEFAULT;
1547 object->myDesc.MultiSampleType = MultiSample;
1548 object->bytesPerPixel = bytesPerPixel(Format);
1549 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1550 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1551 object->lockable = Lockable;
1552 object->locked = FALSE;
1554 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);
1555 return D3D_OK;
1557 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
1558 IDirect3DSurface8Impl *object;
1560 ICOM_THIS(IDirect3DDevice8Impl,iface);
1562 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1563 if (NULL == object) {
1564 *ppSurface = NULL;
1565 return D3DERR_OUTOFVIDEOMEMORY;
1567 *ppSurface = (LPDIRECT3DSURFACE8) object;
1568 object->lpVtbl = &Direct3DSurface8_Vtbl;
1569 object->Device = This;
1570 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1571 object->ResourceType = D3DRTYPE_SURFACE;
1572 object->Container = (IUnknown*) This;
1573 /*IUnknown_AddRef(object->Container);*/
1575 object->ref = 1;
1576 object->myDesc.Width = Width;
1577 object->myDesc.Height = Height;
1578 object->myDesc.Format = Format;
1579 object->myDesc.Type = D3DRTYPE_SURFACE;
1580 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
1581 object->myDesc.Pool = D3DPOOL_DEFAULT;
1582 object->myDesc.MultiSampleType = MultiSample;
1583 object->bytesPerPixel = bytesPerPixel(Format);
1584 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1585 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1586 object->lockable = TRUE;
1587 object->locked = FALSE;
1589 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);
1590 return D3D_OK;
1592 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
1593 IDirect3DSurface8Impl *object;
1595 ICOM_THIS(IDirect3DDevice8Impl,iface);
1597 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1598 *ppSurface = (LPDIRECT3DSURFACE8) object;
1599 object->lpVtbl = &Direct3DSurface8_Vtbl;
1600 object->Device = This;
1601 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1602 object->ResourceType = D3DRTYPE_SURFACE;
1603 object->Container = (IUnknown*) This;
1604 /*IUnknown_AddRef(object->Container);*/
1606 object->ref = 1;
1607 object->myDesc.Width = Width;
1608 object->myDesc.Height = Height;
1609 object->myDesc.Format = Format;
1610 object->myDesc.Type = D3DRTYPE_SURFACE;
1611 object->myDesc.Usage = 0;
1612 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
1613 object->bytesPerPixel = bytesPerPixel(Format);
1614 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1615 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1616 object->lockable = TRUE;
1617 object->locked = FALSE;
1619 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);
1620 return D3D_OK;
1622 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pSourceSurface,CONST RECT* pSourceRectsArray,UINT cRects,
1623 IDirect3DSurface8* pDestinationSurface,CONST POINT* pDestPointsArray) {
1625 HRESULT rc = D3D_OK;
1626 IDirect3DBaseTexture8* texture = NULL;
1629 IDirect3DSurface8Impl *src = (IDirect3DSurface8Impl*) pSourceSurface;
1630 IDirect3DSurface8Impl *dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1632 ICOM_THIS(IDirect3DDevice8Impl,iface);
1633 TRACE("(%p) srcsur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1634 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1636 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1637 a sample and doesnt seem to break anything as far as I can tell */
1638 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1639 TRACE("Formats do not match %x / %x\n", src->myDesc.Format, dst->myDesc.Format);
1640 rc = D3DERR_INVALIDCALL;
1642 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1643 TRACE("Converting dest to same format as source, since dest was unknown\n");
1644 dst->myDesc.Format = src->myDesc.Format;
1646 /* Convert container as well */
1647 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1648 if (texture != NULL) {
1650 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1651 case D3DRTYPE_TEXTURE:
1652 ((IDirect3DTexture8Impl *)texture)->format = src->myDesc.Format;
1653 break;
1654 case D3DRTYPE_VOLUMETEXTURE:
1655 ((IDirect3DVolumeTexture8Impl *)texture)->format = src->myDesc.Format;
1656 break;
1657 case D3DRTYPE_CUBETEXTURE:
1658 ((IDirect3DCubeTexture8Impl *)texture)->format = src->myDesc.Format;
1659 break;
1660 default:
1661 FIXME("Unhandled texture type\n");
1664 /** Releasing texture after GetContainer */
1665 IDirect3DBaseTexture8_Release(texture);
1669 /* Quick if complete copy ... */
1670 if (rc == D3D_OK && (cRects == 0 && pSourceRectsArray==NULL && pDestPointsArray==NULL &&
1671 src->myDesc.Width == dst->myDesc.Width &&
1672 src->myDesc.Height == dst->myDesc.Height)) {
1673 TRACE("Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1674 memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);
1676 } else {
1677 int i;
1678 int bytesPerPixel = ((IDirect3DSurface8Impl *)pSourceSurface)->bytesPerPixel;
1679 int pitchFrom = ((IDirect3DSurface8Impl *)pSourceSurface)->myDesc.Width * bytesPerPixel;
1680 int pitchTo = ((IDirect3DSurface8Impl *)pDestinationSurface)->myDesc.Width * bytesPerPixel;
1682 char *copyfrom = ((IDirect3DSurface8Impl *)pSourceSurface)->allocatedMemory;
1683 char *copyto = ((IDirect3DSurface8Impl *)pDestinationSurface)->allocatedMemory;
1685 /* Copy rect by rect */
1686 for (i=0; i<cRects; i++) {
1687 CONST RECT *r = &pSourceRectsArray[i];
1688 CONST POINT *p = &pDestPointsArray[i];
1689 char *from;
1690 char *to;
1691 int copyperline = (r->right - r->left) * bytesPerPixel;
1692 int j;
1694 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top,
1695 r->right, r->bottom, p->x, p->y);
1697 /* Find where to start */
1698 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1699 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
1701 /* Copy line by line */
1702 for (j=0; j<(r->bottom - r->top); j++) {
1703 memcpy(to + (j*pitchTo), from + (j*pitchFrom), copyperline);
1708 /* Set dirty */
1709 if (rc == D3D_OK) {
1710 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1711 if (texture != NULL) {
1713 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1714 case D3DRTYPE_TEXTURE:
1716 IDirect3DTexture8Impl *pTexture = (IDirect3DTexture8Impl *)texture;
1717 pTexture->Dirty = TRUE;
1719 break;
1720 case D3DRTYPE_VOLUMETEXTURE:
1722 IDirect3DVolumeTexture8Impl *pTexture = (IDirect3DVolumeTexture8Impl *)texture;
1723 pTexture->Dirty = TRUE;
1725 break;
1726 case D3DRTYPE_CUBETEXTURE:
1728 IDirect3DCubeTexture8Impl *pTexture = (IDirect3DCubeTexture8Impl *)texture;
1729 pTexture->Dirty = TRUE;
1731 break;
1732 default:
1733 FIXME("Unhandled texture type\n");
1736 /** Releasing texture after GetContainer */
1737 IDirect3DBaseTexture8_Release(texture);
1741 return D3D_OK;
1743 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1744 ICOM_THIS(IDirect3DDevice8Impl,iface);
1745 FIXME("(%p) : stub\n", This);
1746 return D3D_OK;
1748 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1749 HRESULT hr;
1750 D3DLOCKED_RECT lockedRect;
1751 GLint prev_store;
1752 GLenum prev_read;
1754 ICOM_THIS(IDirect3DDevice8Impl,iface);
1756 FIXME("(%p) : stub\n", This);
1758 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1759 return D3DERR_INVALIDCALL;
1762 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, NULL, 0);
1763 if (FAILED(hr)) {
1764 return D3DERR_INVALIDCALL;
1767 ENTER_GL();
1769 glFlush();
1770 vcheckGLcall("glFlush");
1771 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1772 vcheckGLcall("glIntegerv");
1773 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1774 vcheckGLcall("glIntegerv");
1776 glReadBuffer(GL_FRONT);
1777 vcheckGLcall("glReadBuffer");
1778 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1779 vcheckGLcall("glPixelStorei");
1780 glReadPixels(0, 0, This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight,
1781 GL_BGRA, GL_UNSIGNED_BYTE, lockedRect.pBits);
1782 vcheckGLcall("glReadPixels");
1783 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1784 vcheckGLcall("glPixelStorei");
1785 glReadBuffer(prev_read);
1786 vcheckGLcall("glReadBuffer");
1787 LEAVE_GL();
1789 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1790 return hr;
1792 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1793 ICOM_THIS(IDirect3DDevice8Impl,iface);
1795 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1796 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1797 return D3D_OK;
1800 FIXME("(%p) : invalid stub expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1802 return D3D_OK;
1804 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1805 ICOM_THIS(IDirect3DDevice8Impl,iface);
1807 TRACE("(%p)->(%p)\n", This, This->frontBuffer);
1809 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->frontBuffer;
1810 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1812 return D3D_OK;
1814 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1815 ICOM_THIS(IDirect3DDevice8Impl,iface);
1817 TRACE("(%p)->(%p)\n", This, ppZStencilSurface);
1819 /* Note inc ref on returned surface */
1820 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->depthStencilBuffer;
1821 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1823 return D3D_OK;
1826 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1827 ICOM_THIS(IDirect3DDevice8Impl,iface);
1828 TRACE("(%p) : stub\n", This);
1829 return D3D_OK;
1831 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1832 ICOM_THIS(IDirect3DDevice8Impl,iface);
1833 TRACE("(%p)\n", This);
1835 ENTER_GL();
1837 glFlush();
1838 checkGLcall("glFlush");
1840 /* Useful for debugging sometimes!
1841 printf("Hit Enter ...\n");
1842 getchar(); */
1844 LEAVE_GL();
1845 return D3D_OK;
1847 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) {
1848 ICOM_THIS(IDirect3DDevice8Impl,iface);
1850 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1851 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1852 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1853 GLbitfield glMask = 0;
1854 GLboolean old_ztest;
1855 GLfloat old_z_clear_value;
1856 GLint old_stencil_clear_value;
1857 GLfloat old_color_clear_value[4];
1859 int i;
1860 CONST D3DRECT *curRect;
1862 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1863 Count, pRects, Flags, Z, Stencil);
1865 ENTER_GL();
1866 if (Count > 0 && pRects) {
1867 glEnable(GL_SCISSOR_TEST);
1868 checkGLcall("glEnable GL_SCISSOR_TEST");
1869 curRect = pRects;
1870 } else {
1871 curRect = NULL;
1874 for (i = 0; i < Count || i == 0; i++) {
1876 if (curRect) {
1877 /* Note gl uses lower left, width/height */
1878 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1879 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1880 curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1881 glScissor(curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1882 checkGLcall("glScissor");
1885 /* Clear the whole screen */
1886 if (Flags & D3DCLEAR_STENCIL) {
1887 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1888 glClearStencil(Stencil);
1889 checkGLcall("glClearStencil");
1890 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1893 if (Flags & D3DCLEAR_ZBUFFER) {
1894 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1895 glDepthMask(GL_TRUE);
1896 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1897 glClearDepth(Z);
1898 checkGLcall("glClearDepth");
1899 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1902 if (Flags & D3DCLEAR_TARGET) {
1903 TRACE("Clearing screen with glClear to color %lx\n", Color);
1904 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1905 glClearColor(((Color >> 16) & 0xFF) / 255.0,
1906 ((Color >> 8) & 0xFF) / 255.0,
1907 ((Color >> 0) & 0xFF) / 255.0,
1908 ((Color >> 24) & 0xFF) / 255.0);
1909 checkGLcall("glClearColor");
1910 glMask = glMask | GL_COLOR_BUFFER_BIT;
1913 glClear(glMask);
1914 checkGLcall("glClear");
1916 if (Flags & D3DCLEAR_STENCIL) {
1917 glClearStencil(old_stencil_clear_value);
1919 if (Flags & D3DCLEAR_ZBUFFER) {
1920 glDepthMask(old_ztest);
1921 glClearDepth(old_z_clear_value);
1923 if (Flags & D3DCLEAR_TARGET) {
1924 glClearColor(old_color_clear_value[0],
1925 old_color_clear_value[1],
1926 old_color_clear_value[2],
1927 old_color_clear_value[3]);
1930 if (curRect) curRect = curRect + sizeof(D3DRECT);
1933 if (Count > 0 && pRects) {
1934 glDisable(GL_SCISSOR_TEST);
1935 checkGLcall("glDisable");
1937 LEAVE_GL();
1939 return D3D_OK;
1941 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
1942 ICOM_THIS(IDirect3DDevice8Impl,iface);
1943 D3DMATRIX m;
1944 int k;
1945 float f;
1946 BOOL viewChanged = TRUE;
1947 int Stage;
1949 /* Most of this routine, comments included copied from ddraw tree initially: */
1950 TRACE("(%p) : State=%d\n", This, d3dts);
1952 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1953 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1954 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1956 /* Handle recording of state blocks */
1957 if (This->isRecordingState) {
1958 TRACE("Recording... not performing anything\n");
1959 return D3D_OK;
1963 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1965 where ViewMat = Camera space, WorldMat = world space.
1967 In OpenGL, camera and world space is combined into GL_MODELVIEW
1968 matrix. The Projection matrix stay projection matrix. */
1970 /* After reading through both OpenGL and Direct3D documentations, I
1971 thought that D3D matrices were written in 'line major mode' transposed
1972 from OpenGL's 'column major mode'. But I found out that a simple memcpy
1973 works fine to transfer one matrix format to the other (it did not work
1974 when transposing)....
1976 So :
1977 1) are the documentations wrong
1978 2) does the matrix work even if they are not read correctly
1979 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
1980 loading using glLoadMatrix ?
1982 Anyway, I always use 'conv_mat' to transfer the matrices from one format
1983 to the other so that if I ever find out that I need to transpose them, I
1984 will able to do it quickly, only by changing the macro conv_mat. */
1986 if (d3dts <= 256) { /* WORLDMATRIX(0) == 256! */
1987 switch (d3dts) {
1988 case D3DTS_WORLDMATRIX(0):
1989 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)]);
1990 break;
1992 case D3DTS_VIEW:
1993 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
1994 break;
1996 case D3DTS_PROJECTION:
1997 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
1998 break;
2000 case D3DTS_TEXTURE0:
2001 case D3DTS_TEXTURE1:
2002 case D3DTS_TEXTURE2:
2003 case D3DTS_TEXTURE3:
2004 case D3DTS_TEXTURE4:
2005 case D3DTS_TEXTURE5:
2006 case D3DTS_TEXTURE6:
2007 case D3DTS_TEXTURE7:
2008 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2009 break;
2011 default:
2012 FIXME("Unhandled transform state!!\n");
2013 break;
2015 } else {
2016 /**
2017 * Indexed Vertex Blending Matrices 256 -> 511
2019 /** store it */
2020 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2021 if (checkGLSupport(ARB_VERTEX_BLEND)) {
2022 FIXME("TODO\n");
2023 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
2024 FIXME("TODO\n");
2029 * Move the GL operation to outside of switch to make it work
2030 * regardless of transform set order.
2032 ENTER_GL();
2033 if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
2034 glMatrixMode(GL_PROJECTION);
2035 checkGLcall("glMatrixMode");
2036 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
2037 checkGLcall("glLoadMatrixf");
2038 memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
2039 } else {
2040 TRACE("Skipping as projection already correct\n");
2043 glMatrixMode(GL_MODELVIEW);
2044 checkGLcall("glMatrixMode");
2045 viewChanged = FALSE;
2046 if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
2047 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2048 checkGLcall("glLoadMatrixf");
2049 memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
2050 viewChanged = TRUE;
2052 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
2053 if (d3dts == D3DTS_VIEW) {
2055 /* NOTE: We have to reset the positions even if the light/plane is not currently
2056 enabled, since the call to enable it will not reset the position. */
2058 /* Reset lights */
2059 for (k = 0; k < This->maxLights; k++) {
2060 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
2061 checkGLcall("glLightfv posn");
2062 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
2063 checkGLcall("glLightfv dirn");
2066 /* Reset Clipping Planes if clipping is enabled */
2067 for (k = 0; k < This->clipPlanes; k++) {
2068 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
2069 checkGLcall("glClipPlane");
2072 /* Reapply texture transforms as based off modelview when applied */
2073 for (Stage = 0; Stage < This->TextureUnits; Stage++) {
2075 /* Now apply texture transforms if not applying to the dummy textures */
2076 #if defined(GL_VERSION_1_3)
2077 glActiveTexture(GL_TEXTURE0 + Stage);
2078 #else
2079 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2080 #endif
2081 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
2083 glMatrixMode(GL_TEXTURE);
2084 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2085 glLoadIdentity();
2086 } else {
2087 D3DMATRIX fred;
2088 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2089 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2091 checkGLcall("Load matrix for texture");
2093 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2095 } else if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) {
2096 /* Now apply texture transforms if not applying to the dummy textures */
2097 Stage = d3dts-D3DTS_TEXTURE0;
2099 if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX))) {
2100 memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX));
2102 #if defined(GL_VERSION_1_3)
2103 glActiveTexture(GL_TEXTURE0 + Stage);
2104 #else
2105 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2106 #endif
2107 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
2109 glMatrixMode(GL_TEXTURE);
2110 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2111 glLoadIdentity();
2112 } else {
2113 D3DMATRIX fred;
2114 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2115 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2117 checkGLcall("Load matrix for texture");
2118 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2119 } else {
2120 TRACE("Skipping texture transform as already correct\n");
2123 } else {
2124 TRACE("Skipping view setup as view already correct\n");
2128 * Vertex Blending as described
2129 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
2131 switch (This->UpdateStateBlock->vertex_blend) {
2132 case D3DVBF_DISABLE:
2134 if (viewChanged == TRUE ||
2135 (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
2136 memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
2137 if (viewChanged==FALSE) {
2138 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2139 checkGLcall("glLoadMatrixf");
2141 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
2142 checkGLcall("glMultMatrixf");
2143 } else {
2144 TRACE("Skipping as world already correct\n");
2147 break;
2148 case D3DVBF_1WEIGHTS:
2149 case D3DVBF_2WEIGHTS:
2150 case D3DVBF_3WEIGHTS:
2152 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
2154 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
2155 * so waiting for the values before matrix work
2156 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
2157 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
2158 checkGLcall("glMultMatrixf");
2162 break;
2163 case D3DVBF_TWEENING:
2165 FIXME("valid/correct D3DVBF_TWEENING\n");
2166 f = This->UpdateStateBlock->tween_factor;
2167 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
2168 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
2169 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
2170 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
2171 if (viewChanged==FALSE) {
2172 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2173 checkGLcall("glLoadMatrixf");
2175 glMultMatrixf((float *) &m.u.m[0][0]);
2176 checkGLcall("glMultMatrixf");
2178 break;
2179 case D3DVBF_0WEIGHTS:
2181 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
2182 /* single matrix of weight 1.0f */
2183 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
2184 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
2185 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
2186 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
2187 if (viewChanged == FALSE) {
2188 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2189 checkGLcall("glLoadMatrixf");
2191 glMultMatrixf((float *) &m.u.m[0][0]);
2192 checkGLcall("glMultMatrixf");
2194 break;
2195 default:
2196 break; /* stupid compilator */
2199 LEAVE_GL();
2201 return D3D_OK;
2204 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
2205 ICOM_THIS(IDirect3DDevice8Impl,iface);
2206 TRACE("(%p) : for State %d\n", This, State);
2207 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
2208 return D3D_OK;
2211 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2212 D3DMATRIX *mat = NULL;
2213 D3DMATRIX temp;
2215 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
2216 but works regardless of recording being on.
2217 If this is found to be wrong, change to StateBlock. */
2218 ICOM_THIS(IDirect3DDevice8Impl,iface);
2219 TRACE("(%p) : For state %u\n", This, State);
2221 if (State < HIGHEST_TRANSFORMSTATE)
2223 mat = &This->UpdateStateBlock->transforms[State];
2224 } else {
2225 FIXME("Unhandled transform state!!\n");
2228 /* Copied from ddraw code: */
2229 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);
2230 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);
2231 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);
2232 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);
2234 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);
2235 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);
2236 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);
2237 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);
2239 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);
2240 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);
2241 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);
2242 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);
2244 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);
2245 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);
2246 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);
2247 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);
2249 /* Apply change via set transform - will reapply to eg. lights this way */
2250 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
2251 return D3D_OK;
2253 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
2254 ICOM_THIS(IDirect3DDevice8Impl,iface);
2256 TRACE("(%p)\n", This);
2257 This->UpdateStateBlock->Changed.viewport = TRUE;
2258 This->UpdateStateBlock->Set.viewport = TRUE;
2259 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
2261 /* Handle recording of state blocks */
2262 if (This->isRecordingState) {
2263 TRACE("Recording... not performing anything\n");
2264 return D3D_OK;
2267 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2268 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2270 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2271 checkGLcall("glDepthRange");
2272 /* Fixme? Note GL requires lower left, DirectX supplies upper left */
2273 glViewport(pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height);
2274 checkGLcall("glViewport");
2277 return D3D_OK;
2280 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
2281 ICOM_THIS(IDirect3DDevice8Impl,iface);
2282 TRACE("(%p)\n", This);
2283 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
2284 return D3D_OK;
2287 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
2288 ICOM_THIS(IDirect3DDevice8Impl,iface);
2290 This->UpdateStateBlock->Changed.material = TRUE;
2291 This->UpdateStateBlock->Set.material = TRUE;
2292 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
2294 /* Handle recording of state blocks */
2295 if (This->isRecordingState) {
2296 TRACE("Recording... not performing anything\n");
2297 return D3D_OK;
2300 ENTER_GL();
2301 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2302 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2303 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2304 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2305 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2307 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&This->UpdateStateBlock->material.Ambient);
2308 checkGLcall("glMaterialfv");
2309 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&This->UpdateStateBlock->material.Diffuse);
2310 checkGLcall("glMaterialfv");
2312 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&This->UpdateStateBlock->material.Specular);
2313 checkGLcall("glMaterialfv");
2314 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&This->UpdateStateBlock->material.Emissive);
2315 checkGLcall("glMaterialfv");
2316 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
2317 checkGLcall("glMaterialf");
2319 LEAVE_GL();
2320 return D3D_OK;
2322 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
2323 ICOM_THIS(IDirect3DDevice8Impl,iface);
2324 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
2325 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2326 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2327 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2328 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2329 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2330 return D3D_OK;
2333 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
2334 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
2335 float rho;
2336 float quad_att;
2338 ICOM_THIS(IDirect3DDevice8Impl,iface);
2339 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2341 if (Index > This->maxLights) {
2342 FIXME("Cannot handle more lights than device supports\n");
2343 return D3DERR_INVALIDCALL;
2346 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,
2347 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2348 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2349 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2350 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2351 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2352 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2354 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
2355 This->UpdateStateBlock->Set.lights[Index] = TRUE;
2356 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
2358 /* Handle recording of state blocks */
2359 if (This->isRecordingState) {
2360 TRACE("Recording... not performing anything\n");
2361 return D3D_OK;
2364 /* Diffuse: */
2365 colRGBA[0] = pLight->Diffuse.r;
2366 colRGBA[1] = pLight->Diffuse.g;
2367 colRGBA[2] = pLight->Diffuse.b;
2368 colRGBA[3] = pLight->Diffuse.a;
2369 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2370 checkGLcall("glLightfv");
2372 /* Specular */
2373 colRGBA[0] = pLight->Specular.r;
2374 colRGBA[1] = pLight->Specular.g;
2375 colRGBA[2] = pLight->Specular.b;
2376 colRGBA[3] = pLight->Specular.a;
2377 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2378 checkGLcall("glLightfv");
2380 /* Ambient */
2381 colRGBA[0] = pLight->Ambient.r;
2382 colRGBA[1] = pLight->Ambient.g;
2383 colRGBA[2] = pLight->Ambient.b;
2384 colRGBA[3] = pLight->Ambient.a;
2385 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2386 checkGLcall("glLightfv");
2388 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2389 glMatrixMode(GL_MODELVIEW);
2390 glPushMatrix();
2391 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2393 /* Attenuation - Are these right? guessing... */
2394 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
2395 checkGLcall("glLightf");
2396 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
2397 checkGLcall("glLightf");
2399 quad_att = 1.4/(pLight->Range*pLight->Range);
2400 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2401 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2402 checkGLcall("glLightf");
2404 switch (pLight->Type) {
2405 case D3DLIGHT_POINT:
2406 /* Position */
2407 This->lightPosn[Index][0] = pLight->Position.x;
2408 This->lightPosn[Index][1] = pLight->Position.y;
2409 This->lightPosn[Index][2] = pLight->Position.z;
2410 This->lightPosn[Index][3] = 1.0;
2411 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2412 checkGLcall("glLightfv");
2414 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2415 checkGLcall("glLightf");
2417 /* FIXME: Range */
2418 break;
2420 case D3DLIGHT_SPOT:
2421 /* Position */
2422 This->lightPosn[Index][0] = pLight->Position.x;
2423 This->lightPosn[Index][1] = pLight->Position.y;
2424 This->lightPosn[Index][2] = pLight->Position.z;
2425 This->lightPosn[Index][3] = 1.0;
2426 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2427 checkGLcall("glLightfv");
2429 /* Direction */
2430 This->lightDirn[Index][0] = pLight->Direction.x;
2431 This->lightDirn[Index][1] = pLight->Direction.y;
2432 This->lightDirn[Index][2] = pLight->Direction.z;
2433 This->lightDirn[Index][3] = 1.0;
2434 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2435 checkGLcall("glLightfv");
2438 * opengl-ish and d3d-ish spot lights use too different models for the
2439 * light "intensity" as a function of the angle towards the main light direction,
2440 * so we only can approximate very roughly.
2441 * however spot lights are rather rarely used in games (if ever used at all).
2442 * furthermore if still used, probably nobody pays attention to such details.
2444 if (pLight->Falloff == 0) {
2445 rho = 6.28f;
2446 } else {
2447 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2449 if (rho < 0.0001) rho = 0.0001f;
2450 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2451 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2453 /* FIXME: Range */
2454 break;
2455 case D3DLIGHT_DIRECTIONAL:
2456 /* Direction */
2457 This->lightPosn[Index][0] = -pLight->Direction.x;
2458 This->lightPosn[Index][1] = -pLight->Direction.y;
2459 This->lightPosn[Index][2] = -pLight->Direction.z;
2460 This->lightPosn[Index][3] = 0.0;
2461 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2462 checkGLcall("glLightfv");
2464 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2465 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2468 break;
2469 default:
2470 FIXME("Unrecognized light type %d\n", pLight->Type);
2473 /* Restore the modelview matrix */
2474 glPopMatrix();
2476 return D3D_OK;
2478 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2479 ICOM_THIS(IDirect3DDevice8Impl,iface);
2480 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2482 if (Index > This->maxLights) {
2483 FIXME("Cannot handle more lights than device supports\n");
2484 return D3DERR_INVALIDCALL;
2487 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2488 return D3D_OK;
2490 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2491 ICOM_THIS(IDirect3DDevice8Impl,iface);
2492 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2494 if (Index > This->maxLights) {
2495 FIXME("Cannot handle more lights than device supports\n");
2496 return D3DERR_INVALIDCALL;
2499 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2500 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2501 This->UpdateStateBlock->lightEnable[Index] = Enable;
2503 /* Handle recording of state blocks */
2504 if (This->isRecordingState) {
2505 TRACE("Recording... not performing anything\n");
2506 return D3D_OK;
2509 if (Enable) {
2510 glEnable(GL_LIGHT0+Index);
2511 checkGLcall("glEnable GL_LIGHT0+Index");
2512 } else {
2513 glDisable(GL_LIGHT0+Index);
2514 checkGLcall("glDisable GL_LIGHT0+Index");
2516 return D3D_OK;
2518 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2519 ICOM_THIS(IDirect3DDevice8Impl,iface);
2520 TRACE("(%p) : for idx(%ld)\n", This, Index);
2522 if (Index > This->maxLights) {
2523 FIXME("Cannot handle more lights than device supports\n");
2524 return D3DERR_INVALIDCALL;
2527 *pEnable = This->StateBlock->lightEnable[Index];
2528 return D3D_OK;
2530 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2531 ICOM_THIS(IDirect3DDevice8Impl,iface);
2532 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2534 /* Validate Index */
2535 if (Index >= This->clipPlanes ) {
2536 TRACE("Application has requested clipplane this device doesnt support\n");
2537 return D3DERR_INVALIDCALL;
2540 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2541 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2542 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2543 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2544 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2545 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2547 /* Handle recording of state blocks */
2548 if (This->isRecordingState) {
2549 TRACE("Recording... not performing anything\n");
2550 return D3D_OK;
2553 /* Apply it */
2555 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2556 glMatrixMode(GL_MODELVIEW);
2557 glPushMatrix();
2558 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2560 TRACE("Clipplane [%f,%f,%f,%f]\n", This->UpdateStateBlock->clipplane[Index][0], This->UpdateStateBlock->clipplane[Index][1],
2561 This->UpdateStateBlock->clipplane[Index][2], This->UpdateStateBlock->clipplane[Index][3]);
2562 glClipPlane(GL_CLIP_PLANE0+Index, This->UpdateStateBlock->clipplane[Index]);
2564 glPopMatrix();
2565 checkGLcall("glClipPlane");
2567 return D3D_OK;
2569 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2570 ICOM_THIS(IDirect3DDevice8Impl,iface);
2571 TRACE("(%p) : for idx %ld\n", This, Index);
2573 /* Validate Index */
2574 if (Index >= This->clipPlanes ) {
2575 TRACE("Application has requested clipplane this device doesnt support\n");
2576 return D3DERR_INVALIDCALL;
2579 pPlane[0] = This->StateBlock->clipplane[Index][0];
2580 pPlane[1] = This->StateBlock->clipplane[Index][0];
2581 pPlane[2] = This->StateBlock->clipplane[Index][0];
2582 pPlane[3] = This->StateBlock->clipplane[Index][0];
2583 return D3D_OK;
2585 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2586 ICOM_THIS(IDirect3DDevice8Impl,iface);
2587 DWORD OldValue = This->StateBlock->renderstate[State];
2589 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2590 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2591 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2592 This->UpdateStateBlock->renderstate[State] = Value;
2594 /* Handle recording of state blocks */
2595 if (This->isRecordingState) {
2596 TRACE("Recording... not performing anything\n");
2597 return D3D_OK;
2600 switch (State) {
2601 case D3DRS_FILLMODE :
2602 switch ((D3DFILLMODE) Value) {
2603 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2604 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2605 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2606 default:
2607 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2609 checkGLcall("glPolygonMode (fillmode)");
2610 break;
2612 case D3DRS_LIGHTING :
2613 if (Value) {
2614 glEnable(GL_LIGHTING);
2615 checkGLcall("glEnable GL_LIGHTING");
2616 } else {
2617 glDisable(GL_LIGHTING);
2618 checkGLcall("glDisable GL_LIGHTING");
2620 break;
2622 case D3DRS_ZENABLE :
2623 switch ((D3DZBUFFERTYPE) Value) {
2624 case D3DZB_FALSE:
2625 glDisable(GL_DEPTH_TEST);
2626 checkGLcall("glDisable GL_DEPTH_TEST");
2627 break;
2628 case D3DZB_TRUE:
2629 glEnable(GL_DEPTH_TEST);
2630 checkGLcall("glEnable GL_DEPTH_TEST");
2631 break;
2633 case D3DZB_USEW:
2634 default:
2635 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2637 break;
2639 case D3DRS_CULLMODE :
2641 /* If we are culling "back faces with clockwise vertices" then
2642 set front faces to be counter clockwise and enable culling
2643 of back faces */
2644 switch ((D3DCULL) Value) {
2645 case D3DCULL_NONE:
2646 glDisable(GL_CULL_FACE);
2647 checkGLcall("glDisable GL_CULL_FACE");
2648 break;
2649 case D3DCULL_CW:
2650 glEnable(GL_CULL_FACE);
2651 checkGLcall("glEnable GL_CULL_FACE");
2652 glFrontFace(GL_CCW);
2653 checkGLcall("glFrontFace GL_CCW");
2654 glCullFace(GL_BACK);
2655 break;
2656 case D3DCULL_CCW:
2657 glEnable(GL_CULL_FACE);
2658 checkGLcall("glEnable GL_CULL_FACE");
2659 glFrontFace(GL_CW);
2660 checkGLcall("glFrontFace GL_CW");
2661 glCullFace(GL_BACK);
2662 break;
2663 default:
2664 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2666 break;
2668 case D3DRS_SHADEMODE :
2669 switch ((D3DSHADEMODE) Value) {
2670 case D3DSHADE_FLAT:
2671 glShadeModel(GL_FLAT);
2672 checkGLcall("glShadeModel");
2673 break;
2674 case D3DSHADE_GOURAUD:
2675 glShadeModel(GL_SMOOTH);
2676 checkGLcall("glShadeModel");
2677 break;
2678 case D3DSHADE_PHONG:
2679 FIXME("D3DSHADE_PHONG isnt supported?\n");
2680 return D3DERR_INVALIDCALL;
2681 default:
2682 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2684 break;
2686 case D3DRS_DITHERENABLE :
2687 if (Value) {
2688 glEnable(GL_DITHER);
2689 checkGLcall("glEnable GL_DITHER");
2690 } else {
2691 glDisable(GL_DITHER);
2692 checkGLcall("glDisable GL_DITHER");
2694 break;
2696 case D3DRS_ZWRITEENABLE :
2697 if (Value) {
2698 glDepthMask(1);
2699 checkGLcall("glDepthMask");
2700 } else {
2701 glDepthMask(0);
2702 checkGLcall("glDepthMask");
2704 break;
2706 case D3DRS_ZFUNC :
2708 int glParm = GL_LESS;
2710 switch ((D3DCMPFUNC) Value) {
2711 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2712 case D3DCMP_LESS: glParm=GL_LESS; break;
2713 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2714 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2715 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2716 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2717 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2718 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2719 default:
2720 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2722 glDepthFunc(glParm);
2723 checkGLcall("glDepthFunc");
2725 break;
2727 case D3DRS_AMBIENT :
2730 float col[4];
2731 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2732 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2733 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2734 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2735 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0],col[1],col[2],col[3]);
2736 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2737 checkGLcall("glLightModel for MODEL_AMBIENT");
2740 break;
2742 case D3DRS_ALPHABLENDENABLE :
2743 if (Value) {
2744 glEnable(GL_BLEND);
2745 checkGLcall("glEnable GL_BLEND");
2746 } else {
2747 glDisable(GL_BLEND);
2748 checkGLcall("glDisable GL_BLEND");
2750 break;
2752 case D3DRS_SRCBLEND :
2753 case D3DRS_DESTBLEND :
2755 int newVal = GL_ZERO;
2756 switch (Value) {
2757 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2758 case D3DBLEND_ONE : newVal = GL_ONE; break;
2759 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2760 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2761 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2762 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2763 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2764 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2765 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2766 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2767 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2769 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2770 This->srcBlend = newVal;
2771 This->dstBlend = newVal;
2772 break;
2774 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2775 This->srcBlend = newVal;
2776 This->dstBlend = newVal;
2777 break;
2778 default:
2779 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2782 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2783 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2784 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2785 glBlendFunc(This->srcBlend, This->dstBlend);
2787 checkGLcall("glBlendFunc");
2789 break;
2791 case D3DRS_ALPHATESTENABLE :
2792 if (Value) {
2793 glEnable(GL_ALPHA_TEST);
2794 checkGLcall("glEnable GL_ALPHA_TEST");
2795 } else {
2796 glDisable(GL_ALPHA_TEST);
2797 checkGLcall("glDisable GL_ALPHA_TEST");
2799 break;
2801 case D3DRS_ALPHAFUNC :
2803 int glParm = GL_LESS;
2804 float ref = 1.0;
2806 glGetFloatv(GL_ALPHA_TEST_REF, &ref);
2807 checkGLcall("glGetFloatv(GL_ALPHA_TEST_REF, &ref);");
2809 switch ((D3DCMPFUNC) Value) {
2810 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2811 case D3DCMP_LESS: glParm=GL_LESS; break;
2812 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2813 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2814 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2815 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2816 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2817 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2818 default:
2819 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2821 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2822 glAlphaFunc(glParm, ref);
2823 checkGLcall("glAlphaFunc");
2825 break;
2827 case D3DRS_ALPHAREF :
2829 int glParm = GL_LESS;
2830 float ref = 1.0;
2832 glGetIntegerv(GL_ALPHA_TEST_FUNC, &glParm);
2833 checkGLcall("glGetFloatv(GL_ALPHA_TEST_FUNC, &glParm);");
2835 ref = ((float) Value) / 255.0;
2836 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2837 glAlphaFunc(glParm, ref);
2838 checkGLcall("glAlphaFunc");
2840 break;
2842 case D3DRS_CLIPPLANEENABLE :
2843 case D3DRS_CLIPPING :
2845 /* Ensure we only do the changed clip planes */
2846 DWORD enable = 0xFFFFFFFF;
2847 DWORD disable = 0x00000000;
2849 /* If enabling / disabling all */
2850 if (State == D3DRS_CLIPPING) {
2851 if (Value) {
2852 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2853 disable = 0x00;
2854 } else {
2855 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2856 enable = 0x00;
2858 } else {
2859 enable = Value & ~OldValue;
2860 disable = ~Value & OldValue;
2863 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2864 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2865 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2866 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2867 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2868 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2870 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2871 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2872 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2873 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2874 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2875 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2877 break;
2879 case D3DRS_BLENDOP :
2881 int glParm = GL_FUNC_ADD;
2883 switch ((D3DBLENDOP) Value) {
2884 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2885 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2886 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2887 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2888 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2889 default:
2890 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2892 TRACE("glBlendEquation(%x)\n", glParm);
2893 glBlendEquation(glParm);
2894 checkGLcall("glBlendEquation");
2896 break;
2898 case D3DRS_TEXTUREFACTOR :
2900 int i;
2902 /* Note the texture color applies to all textures whereas
2903 GL_TEXTURE_ENV_COLOR applies to active only */
2904 float col[4];
2905 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2906 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2907 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2908 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2910 /* Set the default alpha blend color */
2911 glBlendColor(col[0], col[1], col[2], col[3]);
2912 checkGLcall("glBlendColor");
2914 /* And now the default texture color as well */
2915 for (i = 0; i < This->TextureUnits; i++) {
2917 /* Note the D3DRS value applies to all textures, but GL has one
2918 per texture, so apply it now ready to be used! */
2919 if (This->isMultiTexture) {
2920 #if defined(GL_VERSION_1_3)
2921 glActiveTexture(GL_TEXTURE0 + i);
2922 #else
2923 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2924 #endif
2925 checkGLcall("Activate texture.. to update const color");
2926 } else if (i>0) {
2927 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2930 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2931 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2934 break;
2936 case D3DRS_SPECULARENABLE :
2938 if (Value) {
2939 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
2940 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);");
2941 } else {
2942 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
2943 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);");
2946 break;
2948 case D3DRS_STENCILENABLE :
2949 if (Value) {
2950 glEnable(GL_STENCIL_TEST);
2951 checkGLcall("glEnable GL_STENCIL_TEST");
2952 } else {
2953 glDisable(GL_STENCIL_TEST);
2954 checkGLcall("glDisable GL_STENCIL_TEST");
2956 break;
2958 case D3DRS_STENCILFUNC :
2960 int glParm = GL_ALWAYS;
2961 int ref = 0;
2962 GLuint mask = 0xFFFFFFFF;
2964 glGetIntegerv(GL_STENCIL_REF, &ref);
2965 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
2966 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
2967 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
2969 switch ((D3DCMPFUNC) Value) {
2970 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2971 case D3DCMP_LESS: glParm=GL_LESS; break;
2972 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2973 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2974 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2975 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2976 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2977 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2978 default:
2979 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2981 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2982 glStencilFunc(glParm, ref, mask);
2983 checkGLcall("glStencilFunc");
2985 break;
2987 case D3DRS_STENCILREF :
2989 int glParm = GL_ALWAYS;
2990 int ref = 0;
2991 GLuint mask = 0xFFFFFFFF;
2993 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
2994 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
2995 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
2996 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
2998 ref = Value;
2999 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3000 glStencilFunc(glParm, ref, mask);
3001 checkGLcall("glStencilFunc");
3003 break;
3005 case D3DRS_STENCILMASK :
3007 int glParm = GL_ALWAYS;
3008 int ref = 0.0;
3009 GLuint mask = Value;
3011 glGetIntegerv(GL_STENCIL_REF, &ref);
3012 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
3013 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
3014 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
3016 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3017 glStencilFunc(glParm, ref, mask);
3018 checkGLcall("glStencilFunc");
3020 break;
3022 case D3DRS_STENCILFAIL :
3024 GLenum fail ;
3025 GLenum zpass ;
3026 GLenum zfail ;
3028 fail = StencilOp(Value);
3029 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3030 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3031 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3032 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3034 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3035 glStencilOp(fail, zfail, zpass);
3036 checkGLcall("glStencilOp(fail, zfail, zpass);");
3038 break;
3039 case D3DRS_STENCILZFAIL :
3041 GLenum fail ;
3042 GLenum zpass ;
3043 GLenum zfail ;
3045 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3046 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3047 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3048 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3049 zfail = StencilOp(Value);
3051 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3052 glStencilOp(fail, zfail, zpass);
3053 checkGLcall("glStencilOp(fail, zfail, zpass);");
3055 break;
3056 case D3DRS_STENCILPASS :
3058 GLenum fail ;
3059 GLenum zpass ;
3060 GLenum zfail ;
3062 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3063 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3064 zpass = StencilOp(Value);
3065 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3066 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3068 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3069 glStencilOp(fail, zfail, zpass);
3070 checkGLcall("glStencilOp(fail, zfail, zpass);");
3072 break;
3074 case D3DRS_STENCILWRITEMASK :
3076 glStencilMask(Value);
3077 TRACE("glStencilMask(%lu)\n", Value);
3078 checkGLcall("glStencilMask");
3080 break;
3082 case D3DRS_FOGENABLE :
3084 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
3085 glEnable(GL_FOG);
3086 checkGLcall("glEnable GL_FOG\n");
3087 } else {
3088 glDisable(GL_FOG);
3089 checkGLcall("glDisable GL_FOG\n");
3092 break;
3094 case D3DRS_FOGCOLOR :
3096 float col[4];
3097 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3098 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
3099 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
3100 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
3102 /* Set the default alpha blend color */
3103 glFogfv(GL_FOG_COLOR, &col[0]);
3104 checkGLcall("glFog GL_FOG_COLOR");
3106 break;
3108 case D3DRS_FOGSTART :
3110 float *f = (float *)&Value;
3111 glFogfv(GL_FOG_START, f);
3112 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3113 TRACE("Fog Start == %f\n", *f);
3115 break;
3117 case D3DRS_FOGEND :
3119 float *f = (float *)&Value;
3120 glFogfv(GL_FOG_END, f);
3121 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3122 TRACE("Fog End == %f\n", *f);
3124 break;
3126 case D3DRS_FOGDENSITY :
3128 glFogf(GL_FOG_DENSITY, (float) Value);
3129 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3131 break;
3133 case D3DRS_VERTEXBLEND :
3135 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3136 TRACE("Vertex Blending state to %ld\n", Value);
3138 break;
3140 case D3DRS_TWEENFACTOR :
3142 This->UpdateStateBlock->tween_factor = *((float*) &Value);
3143 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
3145 break;
3147 case D3DRS_INDEXEDVERTEXBLENDENABLE :
3149 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3151 break;
3154 case D3DRS_COLORVERTEX :
3155 case D3DRS_DIFFUSEMATERIALSOURCE :
3156 case D3DRS_SPECULARMATERIALSOURCE :
3157 case D3DRS_AMBIENTMATERIALSOURCE :
3158 case D3DRS_EMISSIVEMATERIALSOURCE :
3160 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3162 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
3163 glEnable(GL_COLOR_MATERIAL);
3164 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
3166 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3167 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
3168 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
3169 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
3170 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
3172 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3173 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3174 Parm = GL_AMBIENT_AND_DIFFUSE;
3175 } else {
3176 Parm = GL_DIFFUSE;
3178 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3179 Parm = GL_AMBIENT;
3180 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3181 Parm = GL_EMISSION;
3182 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3183 Parm = GL_SPECULAR;
3184 } else {
3185 Parm = -1;
3188 if (Parm == -1) {
3189 glDisable(GL_COLOR_MATERIAL);
3190 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3191 } else {
3192 TRACE("glColorMaterial Parm=%d\n", Parm);
3193 glColorMaterial(GL_FRONT_AND_BACK, Parm);
3194 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
3197 } else {
3198 glDisable(GL_COLOR_MATERIAL);
3199 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3202 break;
3204 /* Unhandled yet...! */
3205 case D3DRS_LINEPATTERN :
3206 case D3DRS_LASTPIXEL :
3207 case D3DRS_ZVISIBLE :
3208 case D3DRS_FOGTABLEMODE :
3209 case D3DRS_EDGEANTIALIAS :
3210 case D3DRS_ZBIAS :
3211 case D3DRS_RANGEFOGENABLE :
3212 case D3DRS_WRAP0 :
3213 case D3DRS_WRAP1 :
3214 case D3DRS_WRAP2 :
3215 case D3DRS_WRAP3 :
3216 case D3DRS_WRAP4 :
3217 case D3DRS_WRAP5 :
3218 case D3DRS_WRAP6 :
3219 case D3DRS_WRAP7 :
3220 case D3DRS_FOGVERTEXMODE :
3221 case D3DRS_LOCALVIEWER :
3222 case D3DRS_NORMALIZENORMALS :
3223 case D3DRS_SOFTWAREVERTEXPROCESSING :
3224 case D3DRS_POINTSIZE :
3225 case D3DRS_POINTSIZE_MIN :
3226 case D3DRS_POINTSPRITEENABLE :
3227 case D3DRS_POINTSCALEENABLE :
3228 case D3DRS_POINTSCALE_A :
3229 case D3DRS_POINTSCALE_B :
3230 case D3DRS_POINTSCALE_C :
3231 case D3DRS_MULTISAMPLEANTIALIAS :
3232 case D3DRS_MULTISAMPLEMASK :
3233 case D3DRS_PATCHEDGESTYLE :
3234 case D3DRS_PATCHSEGMENTS :
3235 case D3DRS_DEBUGMONITORTOKEN :
3236 case D3DRS_POINTSIZE_MAX :
3237 case D3DRS_COLORWRITEENABLE :
3238 case D3DRS_POSITIONORDER :
3239 case D3DRS_NORMALORDER :
3240 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3241 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3242 break;
3243 default:
3244 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3247 return D3D_OK;
3249 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3250 ICOM_THIS(IDirect3DDevice8Impl,iface);
3251 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3252 *pValue = This->StateBlock->renderstate[State];
3253 return D3D_OK;
3255 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3256 ICOM_THIS(IDirect3DDevice8Impl,iface);
3258 TRACE("(%p)\n", This);
3260 return IDirect3DDeviceImpl_BeginStateBlock(This);
3262 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3263 IDirect3DStateBlockImpl* pSB;
3264 ICOM_THIS(IDirect3DDevice8Impl,iface);
3265 HRESULT res;
3267 TRACE("(%p)\n", This);
3269 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3270 *pToken = (DWORD) pSB;
3271 return res;
3274 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3275 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3276 ICOM_THIS(IDirect3DDevice8Impl,iface);
3278 TRACE("(%p)\n", This);
3280 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3283 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3284 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3285 ICOM_THIS(IDirect3DDevice8Impl,iface);
3287 TRACE("(%p)\n", This);
3289 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3291 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3292 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3293 ICOM_THIS(IDirect3DDevice8Impl,iface);
3295 TRACE("(%p)\n", This);
3297 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3300 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3301 IDirect3DStateBlockImpl* pSB;
3302 ICOM_THIS(IDirect3DDevice8Impl,iface);
3303 HRESULT res;
3305 TRACE("(%p) : for type %d\n", This, Type);
3307 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3308 *pToken = (DWORD) pSB;
3309 return res;
3312 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3313 ICOM_THIS(IDirect3DDevice8Impl,iface);
3314 FIXME("(%p) : stub\n", This); return D3D_OK;
3316 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3317 ICOM_THIS(IDirect3DDevice8Impl,iface);
3318 FIXME("(%p) : stub\n", This); return D3D_OK;
3320 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3321 ICOM_THIS(IDirect3DDevice8Impl,iface);
3322 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3323 *ppTexture = (LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage];
3324 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3325 return D3D_OK;
3327 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8* pTexture) {
3329 IDirect3DBaseTexture8 *oldTxt;
3330 BOOL reapplyStates = TRUE;
3332 ICOM_THIS(IDirect3DDevice8Impl,iface);
3333 D3DRESOURCETYPE textureType;
3335 oldTxt = This->UpdateStateBlock->textures[Stage];
3336 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3338 /* Reject invalid texture units */
3339 if (Stage >= This->TextureUnits) {
3340 TRACE("Attempt to access invalid texture rejected\n");
3341 return D3DERR_INVALIDCALL;
3344 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3345 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3346 This->UpdateStateBlock->textures[Stage] = pTexture;
3348 /* Handle recording of state blocks */
3349 if (This->isRecordingState) {
3350 TRACE("Recording... not performing anything\n");
3351 return D3D_OK;
3354 /* Make appropriate texture active */
3355 if (This->isMultiTexture) {
3356 #if defined(GL_VERSION_1_3)
3357 glActiveTexture(GL_TEXTURE0 + Stage);
3358 #else
3359 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3360 #endif
3361 checkGLcall("glActiveTextureARB");
3362 } else if (Stage>0) {
3363 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3366 /* Decrement the count of the previous texture */
3367 if (oldTxt != NULL) {
3368 IDirect3DBaseTexture8Impl_Release(oldTxt);
3371 if (pTexture) {
3372 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage]);
3374 /* Now setup the texture appropraitly */
3375 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3377 if (textureType == D3DRTYPE_TEXTURE) {
3378 IDirect3DTexture8Impl *pTexture2 = (IDirect3DTexture8Impl *) pTexture;
3380 if ((void *)oldTxt == (void *)pTexture2 && pTexture2->Dirty == FALSE) {
3381 TRACE("Skipping setting texture as old == new\n");
3382 reapplyStates = FALSE;
3383 } else {
3385 /* Standard 2D texture */
3386 TRACE("Standard 2d texture\n");
3387 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3389 /* Load up the texture now */
3390 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8)pTexture);
3392 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3393 IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture;
3394 int i;
3396 /* Standard 3D (volume) texture */
3397 TRACE("Standard 3d texture\n");
3398 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3400 for (i=0; i<pTexture2->levels; i++)
3403 if (i==0 && pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3404 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3405 checkGLcall("glBindTexture");
3406 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3408 /* No need to walk through all mip-map levels, since already all assigned */
3409 i = pTexture2->levels;
3410 } else {
3411 if (i==0) {
3413 if (pTexture2->volumes[i]->textureName == 0) {
3414 glGenTextures(1, &pTexture2->volumes[i]->textureName);
3415 checkGLcall("glGenTextures");
3416 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3419 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3420 checkGLcall("glBindTexture");
3422 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1);
3423 checkGLcall("glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1)");
3426 TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3427 GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width,
3428 pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth,
3429 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3430 pTexture2->volumes[i]->allocatedMemory);
3431 glTexImage3D(GL_TEXTURE_3D, i,
3432 fmt2glintFmt(pTexture2->format),
3433 pTexture2->volumes[i]->myDesc.Width,
3434 pTexture2->volumes[i]->myDesc.Height,
3435 pTexture2->volumes[i]->myDesc.Depth,
3437 fmt2glFmt(pTexture2->format),
3438 fmt2glType(pTexture2->format),
3439 pTexture2->volumes[i]->allocatedMemory
3441 checkGLcall("glTexImage3D");
3443 /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3444 pTexture2->Dirty = FALSE;
3448 } else {
3449 FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType);
3451 } else {
3452 TRACE("Setting to no texture (ie default texture)\n");
3453 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3454 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3455 checkGLcall("glBindTexture");
3456 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3459 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3460 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3461 if (reapplyStates) {
3462 setupTextureStates (iface, Stage);
3465 return D3D_OK;
3468 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3469 ICOM_THIS(IDirect3DDevice8Impl,iface);
3470 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3471 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3472 return D3D_OK;
3475 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) {
3476 ICOM_THIS(IDirect3DDevice8Impl,iface);
3478 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3480 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value);
3482 /* Reject invalid texture units */
3483 if (Stage >= This->TextureUnits) {
3484 TRACE("Attempt to access invalid texture rejected\n");
3485 return D3DERR_INVALIDCALL;
3488 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3489 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3490 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3492 /* Handle recording of state blocks */
3493 if (This->isRecordingState) {
3494 TRACE("Recording... not performing anything\n");
3495 return D3D_OK;
3498 /* Make appropriate texture active */
3499 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3500 if (This->isMultiTexture) {
3501 #if defined(GL_VERSION_1_3)
3502 glActiveTexture(GL_TEXTURE0 + Stage);
3503 vcheckGLcall("glActiveTexture");
3504 #else
3505 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3506 vcheckGLcall("glActiveTextureARB");
3507 #endif
3508 } else if (Stage > 0) {
3509 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3512 switch (Type) {
3514 case D3DTSS_MINFILTER :
3515 case D3DTSS_MIPFILTER :
3517 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3518 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3519 GLint realVal = GL_LINEAR;
3521 if (ValueMIN == D3DTEXF_POINT) {
3522 /* GL_NEAREST_* */
3523 if (ValueMIP == D3DTEXF_POINT) {
3524 realVal = GL_NEAREST_MIPMAP_NEAREST;
3525 } else if (ValueMIP == D3DTEXF_LINEAR) {
3526 realVal = GL_NEAREST_MIPMAP_LINEAR;
3527 } else if (ValueMIP == D3DTEXF_NONE) {
3528 realVal = GL_NEAREST;
3529 } else {
3530 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3531 realVal = GL_NEAREST_MIPMAP_LINEAR;
3533 } else if (ValueMIN == D3DTEXF_LINEAR) {
3534 /* GL_LINEAR_* */
3535 if (ValueMIP == D3DTEXF_POINT) {
3536 realVal = GL_LINEAR_MIPMAP_NEAREST;
3537 } else if (ValueMIP == D3DTEXF_LINEAR) {
3538 realVal = GL_LINEAR_MIPMAP_LINEAR;
3539 } else if (ValueMIP == D3DTEXF_NONE) {
3540 realVal = GL_LINEAR;
3541 } else {
3542 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3543 realVal = GL_LINEAR_MIPMAP_LINEAR;
3545 } else if (ValueMIN == D3DTEXF_NONE) {
3546 /* Doesnt really make sense - Windows just seems to disable
3547 mipmapping when this occurs */
3548 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3549 realVal = GL_LINEAR;
3551 } else {
3552 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3553 realVal = GL_LINEAR_MIPMAP_LINEAR;
3556 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3557 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3558 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3560 break;
3563 case D3DTSS_MAGFILTER :
3564 if (Value == D3DTEXF_POINT) {
3565 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3566 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3567 } else if (Value == D3DTEXF_LINEAR) {
3568 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3569 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3570 } else {
3571 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3573 break;
3575 case D3DTSS_COLORARG0 :
3576 case D3DTSS_ALPHAARG0 :
3577 /* FIXME: Mesa seems to struggle setting these at the moment */
3578 /*FIXME("COLORARG0/ALPHAARG0 support still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);*/
3579 /*break;*/
3581 case D3DTSS_COLORARG1 :
3582 case D3DTSS_COLORARG2 :
3583 case D3DTSS_ALPHAARG1 :
3584 case D3DTSS_ALPHAARG2 :
3586 BOOL isAlphaArg = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3587 int operand = GL_SRC_COLOR;
3588 int source = GL_TEXTURE;
3590 GetSrcAndOpFromValue(Value, isAlphaArg, &source, &operand);
3591 if (isAlphaArg) {
3592 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
3593 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
3594 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
3595 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
3596 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
3597 } else {
3598 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
3599 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
3600 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
3601 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
3602 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
3605 break;
3607 case D3DTSS_ALPHAOP :
3608 case D3DTSS_COLOROP :
3611 int Scale = 1;
3612 int Parm = (Type == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
3614 if (Type == D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
3615 /* TODO: Disable by making this and all later levels disabled */
3616 glDisable(GL_TEXTURE_1D);
3617 checkGLcall("Disable GL_TEXTURE_1D");
3618 glDisable(GL_TEXTURE_2D);
3619 checkGLcall("Disable GL_TEXTURE_2D");
3620 glDisable(GL_TEXTURE_3D);
3621 checkGLcall("Disable GL_TEXTURE_3D");
3622 } else {
3624 /* Enable only the appropriate texture dimension */
3625 if (Type == D3DTSS_COLOROP) {
3626 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3627 glEnable(GL_TEXTURE_1D);
3628 checkGLcall("Enable GL_TEXTURE_1D");
3629 } else {
3630 glDisable(GL_TEXTURE_1D);
3631 checkGLcall("Disable GL_TEXTURE_1D");
3633 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3634 glEnable(GL_TEXTURE_2D);
3635 checkGLcall("Enable GL_TEXTURE_2D");
3636 } else {
3637 glDisable(GL_TEXTURE_2D);
3638 checkGLcall("Disable GL_TEXTURE_2D");
3640 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3641 glEnable(GL_TEXTURE_3D);
3642 checkGLcall("Enable GL_TEXTURE_3D");
3643 } else {
3644 glDisable(GL_TEXTURE_3D);
3645 checkGLcall("Disable GL_TEXTURE_3D");
3649 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
3650 if (Value != D3DTOP_DISABLE) {
3651 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3654 /* Now set up the operand correctly */
3655 switch (Value) {
3656 case D3DTOP_DISABLE :
3657 /* Contrary to the docs, alpha can be disabled when colorop is enabled
3658 and it works, so ignore this op */
3659 TRACE("Disable ALPHAOP but COLOROP enabled!\n");
3660 break;
3662 case D3DTOP_SELECTARG1 :
3664 FIXME("see if D3DTOP_SELECTARG1 behavior is correct now!\n");
3665 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3666 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3667 #if 0 /* don't seem to do anything */
3668 BOOL isAlphaOp = (Type == D3DTSS_ALPHAOP);
3669 DWORD dwValue = 0;
3670 GLenum source;
3671 GLenum operand;
3672 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3673 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3674 if (isAlphaOp) {
3675 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3676 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3677 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3678 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3679 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3680 } else {
3681 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3682 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3683 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3684 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3685 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3687 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3688 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3689 if (isAlphaOp) {
3690 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3691 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3692 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3693 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3694 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3695 } else {
3696 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3697 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3698 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3699 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3700 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3702 #endif
3704 break;
3706 case D3DTOP_SELECTARG2 :
3708 BOOL isAlphaOp = (Type == D3DTSS_ALPHAOP);
3709 DWORD dwValue = 0;
3710 GLenum source;
3711 GLenum operand;
3712 FIXME("see if D3DTOP_SELECTARG2 behavior is correct now!\n");
3713 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3714 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3715 /* GL_REPLACE, swap args 0 and 1? */
3716 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3717 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3718 if (isAlphaOp) {
3719 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3720 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3721 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3722 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3723 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3724 } else {
3725 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3726 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3727 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3728 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3729 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3731 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3732 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3733 if (isAlphaOp) {
3734 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3735 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3736 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3737 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3738 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3739 } else {
3740 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3741 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3742 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3743 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3744 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3747 break;
3749 case D3DTOP_MODULATE4X : Scale = Scale * 2; /* Drop through */
3750 case D3DTOP_MODULATE2X : Scale = Scale * 2; /* Drop through */
3751 case D3DTOP_MODULATE :
3753 /* Correct scale */
3754 if (Type == D3DTSS_ALPHAOP) {
3755 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
3756 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
3757 } else {
3758 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
3759 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
3761 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
3762 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
3763 break;
3765 case D3DTOP_ADD :
3766 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
3767 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
3768 break;
3770 case D3DTOP_ADDSIGNED2X : Scale = Scale * 2; /* Drop through */
3771 case D3DTOP_ADDSIGNED :
3772 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
3773 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
3774 break;
3776 case D3DTOP_DOTPRODUCT3 :
3777 #if defined(GL_VERSION_1_3)
3778 if (This->isDot3) {
3779 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
3780 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
3781 break;
3783 #endif
3784 FIXME("DotProduct3 extension requested but not supported via this version of opengl\n");
3785 break;
3787 case D3DTOP_SUBTRACT :
3788 #if defined(GL_VERSION_1_3)
3789 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT);
3790 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT)");
3791 break;
3792 #else
3794 * @TODO: to check:
3795 * if ARB_texture_env_combine is supported
3796 * we can use GL_SUBTRACT_ARB here
3798 #endif
3799 case D3DTOP_ADDSMOOTH :
3800 case D3DTOP_BLENDDIFFUSEALPHA :
3801 case D3DTOP_BLENDTEXTUREALPHA :
3802 case D3DTOP_BLENDFACTORALPHA :
3803 case D3DTOP_BLENDTEXTUREALPHAPM :
3804 case D3DTOP_BLENDCURRENTALPHA :
3805 case D3DTOP_PREMODULATE :
3806 case D3DTOP_MODULATEALPHA_ADDCOLOR :
3807 case D3DTOP_MODULATECOLOR_ADDALPHA :
3808 case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
3809 case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
3810 case D3DTOP_BUMPENVMAP :
3811 case D3DTOP_BUMPENVMAPLUMINANCE :
3812 case D3DTOP_MULTIPLYADD :
3813 case D3DTOP_LERP :
3814 default:
3815 FIXME("Unhandled texture operation %ld\n", Value);
3818 break;
3821 case D3DTSS_ADDRESSU :
3822 case D3DTSS_ADDRESSV :
3823 case D3DTSS_ADDRESSW :
3825 GLint wrapParm = GL_REPEAT;
3826 switch (Value) {
3827 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3828 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3829 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3830 #if defined(GL_VERSION_1_4)
3831 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3832 #elif defined(GL_ARB_texture_mirrored_repeat)
3833 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3834 #else
3835 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3836 #endif
3837 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3838 default:
3839 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3840 wrapParm = GL_REPEAT;
3843 switch (Type) {
3844 case D3DTSS_ADDRESSU:
3845 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3846 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3847 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3848 break;
3849 case D3DTSS_ADDRESSV:
3850 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3851 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3852 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3853 break;
3854 case D3DTSS_ADDRESSW:
3855 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3856 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3857 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3858 break;
3859 default: /* nop */
3860 break; /** stupic compilator */
3863 break;
3865 case D3DTSS_BORDERCOLOR :
3867 float col[4];
3868 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3869 col[1] = ((Value >> 8) & 0xFF) / 255.0;
3870 col[2] = ((Value >> 0) & 0xFF) / 255.0;
3871 col[3] = ((Value >> 24) & 0xFF) / 255.0;
3873 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3874 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3875 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3877 break;
3879 case D3DTSS_TEXCOORDINDEX :
3881 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3882 as the input texture coordinates for this stage's texture transformation. This
3883 equates roughly to EYE_LINEAR */
3886 * To Jason: i don't understand what to do with the (Value & 0x00FF) index
3887 * it seems a texture coordinate index (0 <= x <= 7) seeing msdn and logs
3888 * have you any idea ?
3891 /**
3892 * Be carefull the value of the mask 0xF0000 come from d3d8types.h infos
3894 switch (Value & 0xFFFFFF00) {
3895 case D3DTSS_TCI_PASSTHRU:
3896 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3897 break;
3899 case D3DTSS_TCI_CAMERASPACEPOSITION:
3901 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3902 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3903 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3904 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3905 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3907 glMatrixMode(GL_MODELVIEW);
3908 glPushMatrix();
3909 glLoadIdentity();
3910 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3911 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3912 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3913 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3914 glPopMatrix();
3916 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3917 glEnable(GL_TEXTURE_GEN_S);
3918 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3919 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3920 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3921 glEnable(GL_TEXTURE_GEN_T);
3922 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3923 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3924 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3925 glEnable(GL_TEXTURE_GEN_R);
3926 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3927 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3928 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3930 break;
3932 default:
3933 /* Todo: */
3934 /* ? disable GL_TEXTURE_GEN_n ? */
3935 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3936 break;
3939 break;
3941 /* Unhandled */
3942 case D3DTSS_BUMPENVMAT00 :
3943 case D3DTSS_BUMPENVMAT01 :
3944 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3945 break;
3946 case D3DTSS_BUMPENVMAT10 :
3947 case D3DTSS_BUMPENVMAT11 :
3948 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3949 break;
3951 case D3DTSS_MIPMAPLODBIAS :
3952 case D3DTSS_MAXMIPLEVEL :
3953 case D3DTSS_MAXANISOTROPY :
3954 case D3DTSS_BUMPENVLSCALE :
3955 case D3DTSS_BUMPENVLOFFSET :
3956 case D3DTSS_TEXTURETRANSFORMFLAGS :
3957 case D3DTSS_RESULTARG :
3958 default:
3959 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3960 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3962 return D3D_OK;
3964 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3965 ICOM_THIS(IDirect3DDevice8Impl,iface);
3966 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3967 return D3D_OK;
3969 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize) {
3970 ICOM_THIS(IDirect3DDevice8Impl,iface);
3971 FIXME("(%p) : stub\n", This); return D3D_OK;
3973 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,CONST PALETTEENTRY* pEntries) {
3974 ICOM_THIS(IDirect3DDevice8Impl,iface);
3975 FIXME("(%p) : stub\n", This); return D3D_OK;
3977 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,PALETTEENTRY* pEntries) {
3978 ICOM_THIS(IDirect3DDevice8Impl,iface);
3979 FIXME("(%p) : stub\n", This); return D3D_OK;
3981 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3982 ICOM_THIS(IDirect3DDevice8Impl,iface);
3983 FIXME("(%p) : stub\n", This); return D3D_OK;
3985 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3986 ICOM_THIS(IDirect3DDevice8Impl,iface);
3987 FIXME("(%p) : stub\n", This); return D3D_OK;
3989 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) {
3991 IDirect3DVertexBuffer8 *pVB;
3993 ICOM_THIS(IDirect3DDevice8Impl,iface);
3994 pVB = This->StateBlock->stream_source[0];
3996 TRACE("(%p) : Type=%d, Start=%d, Count=%d\n", This, PrimitiveType, StartVertex, PrimitiveCount);
3998 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
3999 This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
4001 return D3D_OK;
4003 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
4004 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
4005 UINT idxStride = 2;
4006 IDirect3DIndexBuffer8 *pIB;
4007 IDirect3DVertexBuffer8 *pVB;
4008 D3DINDEXBUFFER_DESC IdxBufDsc;
4010 ICOM_THIS(IDirect3DDevice8Impl,iface);
4011 pIB = This->StateBlock->pIndexData;
4012 pVB = This->StateBlock->stream_source[0];
4014 TRACE("(%p) : Type=%d, min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, PrimitiveType,
4015 minIndex, NumVertices, startIndex, primCount);
4017 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
4018 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
4019 idxStride = 2;
4020 } else {
4021 idxStride = 4;
4024 DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
4025 This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
4026 minIndex);
4028 return D3D_OK;
4030 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
4031 ICOM_THIS(IDirect3DDevice8Impl,iface);
4033 TRACE("(%p) : Type=%d, pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4035 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4037 This->StateBlock->stream_source[0] = NULL;
4038 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4039 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4040 0, 0, 0, NULL, 0);
4041 This->StateBlock->stream_stride[0] = 0;
4043 /*stream zero settings set to null at end */
4044 return D3D_OK;
4046 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4047 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4048 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4049 UINT VertexStreamZeroStride) {
4050 int idxStride;
4051 ICOM_THIS(IDirect3DDevice8Impl,iface);
4052 TRACE("(%p) : Type=%d, MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType,
4053 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4055 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4056 if (IndexDataFormat == D3DFMT_INDEX16) {
4057 idxStride = 2;
4058 } else {
4059 idxStride = 4;
4062 This->StateBlock->stream_source[0] = NULL;
4063 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4064 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4065 This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4067 /*stream zero settings set to null at end */
4068 This->StateBlock->stream_stride[0] = 0;
4069 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4071 return D3D_OK;
4073 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4074 ICOM_THIS(IDirect3DDevice8Impl,iface);
4075 FIXME("(%p) : stub\n", This); return D3D_OK;
4077 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4078 ICOM_THIS(IDirect3DDevice8Impl,iface);
4079 IDirect3DVertexShaderImpl* object;
4080 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4081 HRESULT res;
4082 UINT i;
4084 TRACE("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
4085 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4086 return D3DERR_INVALIDCALL;
4088 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4089 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4090 return D3DERR_OUTOFVIDEOMEMORY;
4093 /** Create the Vertex Shader */
4094 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4095 /** TODO: check FAILED(res) */
4097 /** Create and Bind the Vertex Shader Declaration */
4098 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4099 /** TODO: check FAILED(res) */
4101 VertexShaders[i] = object;
4102 VertexShaderDeclarations[i] = attached_decl;
4103 *pHandle = VS_HIGHESTFIXEDFXF + i;
4105 return D3D_OK;
4107 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4108 ICOM_THIS(IDirect3DDevice8Impl,iface);
4110 This->UpdateStateBlock->VertexShader = Handle;
4111 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4112 This->UpdateStateBlock->Set.vertexShader = TRUE;
4114 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4115 FIXME("(%p) : Created shader, Handle=%lx\n", This, Handle);
4116 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4117 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4118 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4119 } else { /* use a fvf, so desactivate the vshader decl */
4120 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4121 This->UpdateStateBlock->vertexShaderDecl = NULL;
4122 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4123 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4125 /* Handle recording of state blocks */
4126 if (This->isRecordingState) {
4127 TRACE("Recording... not performing anything\n");
4128 return D3D_OK;
4131 * TODO: merge HAL shaders context switching from prototype
4133 return D3D_OK;
4135 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4136 ICOM_THIS(IDirect3DDevice8Impl,iface);
4137 TRACE("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4138 *pHandle = This->StateBlock->VertexShader;
4139 return D3D_OK;
4142 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4143 ICOM_THIS(IDirect3DDevice8Impl,iface);
4144 IDirect3DVertexShaderImpl* object;
4145 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4147 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4148 return D3DERR_INVALIDCALL;
4152 * Delete Vertex Shader
4154 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4155 if (NULL == object) {
4156 return D3DERR_INVALIDCALL;
4158 FIXME("(%p) : freing VertexShader %p\n", This, object);
4159 /* TODO: check validity of object */
4160 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4161 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4162 HeapFree(GetProcessHeap(), 0, (void *)object);
4163 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4166 * Delete Vertex Shader Declaration
4168 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4169 if (NULL == attached_decl) {
4170 return D3DERR_INVALIDCALL;
4172 FIXME("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4173 /* TODO: check validity of object */
4174 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4175 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4176 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4178 return D3D_OK;
4181 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4182 ICOM_THIS(IDirect3DDevice8Impl,iface);
4184 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4185 ERR("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4186 return D3DERR_INVALIDCALL;
4188 if (NULL == pConstantData) {
4189 return D3DERR_INVALIDCALL;
4191 if (ConstantCount > 1) {
4192 FLOAT* f = (FLOAT*)pConstantData;
4193 UINT i;
4194 TRACE("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4195 for (i = 0; i < ConstantCount; ++i) {
4196 TRACE("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4197 f += 4;
4199 } else {
4200 FLOAT* f = (FLOAT*)pConstantData;
4201 TRACE("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4203 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4204 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4205 return D3D_OK;
4207 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4208 ICOM_THIS(IDirect3DDevice8Impl,iface);
4210 TRACE("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4211 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4212 return D3DERR_INVALIDCALL;
4214 if (NULL == pConstantData) {
4215 return D3DERR_INVALIDCALL;
4217 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4218 return D3D_OK;
4220 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4221 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4222 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4224 attached_decl = VERTEX_SHADER_DECL(Handle);
4225 if (NULL == attached_decl) {
4226 return D3DERR_INVALIDCALL;
4228 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4230 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4231 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4232 IDirect3DVertexShaderImpl* object;
4234 object = VERTEX_SHADER(Handle);
4235 if (NULL == object) {
4236 return D3DERR_INVALIDCALL;
4238 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4241 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4242 ICOM_THIS(IDirect3DDevice8Impl,iface);
4243 IDirect3DIndexBuffer8 *oldIdxs;
4245 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4246 oldIdxs = This->StateBlock->pIndexData;
4248 This->UpdateStateBlock->Changed.Indices = TRUE;
4249 This->UpdateStateBlock->Set.Indices = TRUE;
4250 This->UpdateStateBlock->pIndexData = pIndexData;
4251 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4253 /* Handle recording of state blocks */
4254 if (This->isRecordingState) {
4255 TRACE("Recording... not performing anything\n");
4256 return D3D_OK;
4259 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4260 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4261 return D3D_OK;
4263 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4264 ICOM_THIS(IDirect3DDevice8Impl,iface);
4265 FIXME("(%p) : stub\n", This);
4267 *ppIndexData = This->StateBlock->pIndexData;
4268 /* up ref count on ppindexdata */
4269 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4270 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4272 return D3D_OK;
4274 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4275 ICOM_THIS(IDirect3DDevice8Impl,iface);
4276 IDirect3DPixelShaderImpl* object;
4277 UINT i;
4279 FIXME("(%p) : PixelShader not fully supported yet\n", This);
4280 if (NULL == pFunction || NULL == pHandle) {
4281 return D3DERR_INVALIDCALL;
4283 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4284 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4285 return D3DERR_OUTOFVIDEOMEMORY;
4287 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DPixelShaderImpl));
4288 if (NULL == object) {
4289 return D3DERR_OUTOFVIDEOMEMORY;
4292 object->data = NULL; /* TODO */
4294 PixelShaders[i] = object;
4295 *pHandle = VS_HIGHESTFIXEDFXF + i;
4297 object->function = pFunction;
4298 for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
4299 object->functionLength = i + 1;
4301 return D3D_OK;
4303 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4304 ICOM_THIS(IDirect3DDevice8Impl,iface);
4306 This->UpdateStateBlock->PixelShader = Handle;
4307 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4308 This->UpdateStateBlock->Set.pixelShader = TRUE;
4310 /* Handle recording of state blocks */
4311 if (This->isRecordingState) {
4312 TRACE("Recording... not performing anything\n");
4313 return D3D_OK;
4316 /* FIXME: Quieten when not being used */
4317 if (Handle != 0) {
4318 FIXME("(%p) : stub %ld\n", This, Handle);
4319 } else {
4320 TRACE("(%p) : stub %ld\n", This, Handle);
4323 return D3D_OK;
4325 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4326 ICOM_THIS(IDirect3DDevice8Impl,iface);
4327 TRACE("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4328 *pHandle = This->StateBlock->PixelShader;
4329 return D3D_OK;
4332 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4333 ICOM_THIS(IDirect3DDevice8Impl,iface);
4334 IDirect3DPixelShaderImpl* object;
4336 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4337 return D3DERR_INVALIDCALL;
4339 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4340 TRACE("(%p) : freeing PixelShader %p\n", This, object);
4341 /* TODO: check validity of object before free */
4342 HeapFree(GetProcessHeap(), 0, (void *)object);
4343 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
4344 return D3D_OK;
4347 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,CONST void* pConstantData, DWORD ConstantCount) {
4348 ICOM_THIS(IDirect3DDevice8Impl,iface);
4349 FIXME("(%p) : stub\n", This);
4350 return D3D_OK;
4352 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,void* pConstantData, DWORD ConstantCount) {
4353 ICOM_THIS(IDirect3DDevice8Impl,iface);
4354 FIXME("(%p) : stub\n", This);
4355 return D3D_OK;
4357 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4358 ICOM_THIS(IDirect3DDevice8Impl,iface);
4359 IDirect3DPixelShaderImpl* object;
4361 object = PIXEL_SHADER(Handle);
4362 if (NULL == object) {
4363 return D3DERR_INVALIDCALL;
4365 if (NULL == pData) {
4366 *pSizeOfData = object->functionLength;
4367 return D3D_OK;
4369 if (*pSizeOfData < object->functionLength) {
4370 *pSizeOfData = object->functionLength;
4371 return D3DERR_MOREDATA;
4373 TRACE("(%p) : GetPixelShaderFunction copying to %p\n", This, pData);
4374 memcpy(pData, object->function, object->functionLength);
4375 return D3D_OK;
4377 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4378 ICOM_THIS(IDirect3DDevice8Impl,iface);
4379 FIXME("(%p) : stub\n", This); return D3D_OK;
4381 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4382 ICOM_THIS(IDirect3DDevice8Impl,iface);
4383 FIXME("(%p) : stub\n", This); return D3D_OK;
4385 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4386 ICOM_THIS(IDirect3DDevice8Impl,iface);
4387 FIXME("(%p) : stub\n", This); return D3D_OK;
4390 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4391 IDirect3DVertexBuffer8 *oldSrc;
4392 ICOM_THIS(IDirect3DDevice8Impl,iface);
4394 oldSrc = This->StateBlock->stream_source[StreamNumber];
4395 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4397 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4398 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4399 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4400 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4402 /* Handle recording of state blocks */
4403 if (This->isRecordingState) {
4404 TRACE("Recording... not performing anything\n");
4405 return D3D_OK;
4408 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4409 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4410 return D3D_OK;
4412 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4413 ICOM_THIS(IDirect3DDevice8Impl,iface);
4414 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4415 *pStream = This->StateBlock->stream_source[StreamNumber];
4416 *pStride = This->StateBlock->stream_stride[StreamNumber];
4417 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4418 return D3D_OK;
4422 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4424 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4425 IDirect3DDevice8Impl_QueryInterface,
4426 IDirect3DDevice8Impl_AddRef,
4427 IDirect3DDevice8Impl_Release,
4428 IDirect3DDevice8Impl_TestCooperativeLevel,
4429 IDirect3DDevice8Impl_GetAvailableTextureMem,
4430 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4431 IDirect3DDevice8Impl_GetDirect3D,
4432 IDirect3DDevice8Impl_GetDeviceCaps,
4433 IDirect3DDevice8Impl_GetDisplayMode,
4434 IDirect3DDevice8Impl_GetCreationParameters,
4435 IDirect3DDevice8Impl_SetCursorProperties,
4436 IDirect3DDevice8Impl_SetCursorPosition,
4437 IDirect3DDevice8Impl_ShowCursor,
4438 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4439 IDirect3DDevice8Impl_Reset,
4440 IDirect3DDevice8Impl_Present,
4441 IDirect3DDevice8Impl_GetBackBuffer,
4442 IDirect3DDevice8Impl_GetRasterStatus,
4443 IDirect3DDevice8Impl_SetGammaRamp,
4444 IDirect3DDevice8Impl_GetGammaRamp,
4445 IDirect3DDevice8Impl_CreateTexture,
4446 IDirect3DDevice8Impl_CreateVolumeTexture,
4447 IDirect3DDevice8Impl_CreateCubeTexture,
4448 IDirect3DDevice8Impl_CreateVertexBuffer,
4449 IDirect3DDevice8Impl_CreateIndexBuffer,
4450 IDirect3DDevice8Impl_CreateRenderTarget,
4451 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4452 IDirect3DDevice8Impl_CreateImageSurface,
4453 IDirect3DDevice8Impl_CopyRects,
4454 IDirect3DDevice8Impl_UpdateTexture,
4455 IDirect3DDevice8Impl_GetFrontBuffer,
4456 IDirect3DDevice8Impl_SetRenderTarget,
4457 IDirect3DDevice8Impl_GetRenderTarget,
4458 IDirect3DDevice8Impl_GetDepthStencilSurface,
4459 IDirect3DDevice8Impl_BeginScene,
4460 IDirect3DDevice8Impl_EndScene,
4461 IDirect3DDevice8Impl_Clear,
4462 IDirect3DDevice8Impl_SetTransform,
4463 IDirect3DDevice8Impl_GetTransform,
4464 IDirect3DDevice8Impl_MultiplyTransform,
4465 IDirect3DDevice8Impl_SetViewport,
4466 IDirect3DDevice8Impl_GetViewport,
4467 IDirect3DDevice8Impl_SetMaterial,
4468 IDirect3DDevice8Impl_GetMaterial,
4469 IDirect3DDevice8Impl_SetLight,
4470 IDirect3DDevice8Impl_GetLight,
4471 IDirect3DDevice8Impl_LightEnable,
4472 IDirect3DDevice8Impl_GetLightEnable,
4473 IDirect3DDevice8Impl_SetClipPlane,
4474 IDirect3DDevice8Impl_GetClipPlane,
4475 IDirect3DDevice8Impl_SetRenderState,
4476 IDirect3DDevice8Impl_GetRenderState,
4477 IDirect3DDevice8Impl_BeginStateBlock,
4478 IDirect3DDevice8Impl_EndStateBlock,
4479 IDirect3DDevice8Impl_ApplyStateBlock,
4480 IDirect3DDevice8Impl_CaptureStateBlock,
4481 IDirect3DDevice8Impl_DeleteStateBlock,
4482 IDirect3DDevice8Impl_CreateStateBlock,
4483 IDirect3DDevice8Impl_SetClipStatus,
4484 IDirect3DDevice8Impl_GetClipStatus,
4485 IDirect3DDevice8Impl_GetTexture,
4486 IDirect3DDevice8Impl_SetTexture,
4487 IDirect3DDevice8Impl_GetTextureStageState,
4488 IDirect3DDevice8Impl_SetTextureStageState,
4489 IDirect3DDevice8Impl_ValidateDevice,
4490 IDirect3DDevice8Impl_GetInfo,
4491 IDirect3DDevice8Impl_SetPaletteEntries,
4492 IDirect3DDevice8Impl_GetPaletteEntries,
4493 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4494 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4495 IDirect3DDevice8Impl_DrawPrimitive,
4496 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4497 IDirect3DDevice8Impl_DrawPrimitiveUP,
4498 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4499 IDirect3DDevice8Impl_ProcessVertices,
4500 IDirect3DDevice8Impl_CreateVertexShader,
4501 IDirect3DDevice8Impl_SetVertexShader,
4502 IDirect3DDevice8Impl_GetVertexShader,
4503 IDirect3DDevice8Impl_DeleteVertexShader,
4504 IDirect3DDevice8Impl_SetVertexShaderConstant,
4505 IDirect3DDevice8Impl_GetVertexShaderConstant,
4506 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4507 IDirect3DDevice8Impl_GetVertexShaderFunction,
4508 IDirect3DDevice8Impl_SetStreamSource,
4509 IDirect3DDevice8Impl_GetStreamSource,
4510 IDirect3DDevice8Impl_SetIndices,
4511 IDirect3DDevice8Impl_GetIndices,
4512 IDirect3DDevice8Impl_CreatePixelShader,
4513 IDirect3DDevice8Impl_SetPixelShader,
4514 IDirect3DDevice8Impl_GetPixelShader,
4515 IDirect3DDevice8Impl_DeletePixelShader,
4516 IDirect3DDevice8Impl_SetPixelShaderConstant,
4517 IDirect3DDevice8Impl_GetPixelShaderConstant,
4518 IDirect3DDevice8Impl_GetPixelShaderFunction,
4519 IDirect3DDevice8Impl_DrawRectPatch,
4520 IDirect3DDevice8Impl_DrawTriPatch,
4521 IDirect3DDevice8Impl_DeletePatch