Properly support texture coordinate indexes.
[wine/wine64.git] / dlls / d3d8 / device.c
blobf9b46a49f1530ccfdd22209532ba12cc7235f05a
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 int vx_index;
149 int coordIdxInfo = 0x00; /* Information on number of coords supplied */
150 float s[8], t[8], r[8], q[8]; /* Holding place for tex coords */
151 const char *coordPtr[8]; /* Holding place for the ptr to tex coords */
152 int numCoords[8]; /* Holding place for D3DFVF_TEXTUREFORMATx */
155 float x = 0.0f,
156 y = 0.0f,
157 z = 0.0f; /* x,y,z coordinates */
158 float nx = 0.0f,
159 ny =0.0,
160 nz = 0.0f; /* normal x,y,z coordinates */
161 float rhw = 0.0f; /* rhw */
162 float ptSize = 0.0f; /* Point size */
163 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
164 DWORD specularColor = 0; /* Specular Color */
166 ENTER_GL();
168 if (isIndexed) {
169 if (idxBytes == 2) pIdxBufS = (short *) idxData;
170 else pIdxBufL = (long *) idxData;
173 /* Check vertex formats expected ? */
174 /**
175 * FVF parser as seen it
176 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp
178 normal = fvf & D3DFVF_NORMAL;
179 isRHW = fvf & D3DFVF_XYZRHW;
180 isLastUByte4 = fvf & D3DFVF_LASTBETA_UBYTE4;
181 numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */
182 isPtSize = fvf & D3DFVF_PSIZE;
183 isDiffuse = fvf & D3DFVF_DIFFUSE;
184 isSpecular = fvf & D3DFVF_SPECULAR;
185 numTextures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
186 coordIdxInfo = (fvf & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
188 TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d, coordIdxInfo=%x)\n",
189 fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends, coordIdxInfo);
191 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
192 set by the appropriate render state */
193 if (!normal) {
194 isLightingOn = glIsEnabled(GL_LIGHTING);
195 glDisable(GL_LIGHTING);
196 TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
199 if (isRHW) {
200 double height, width, minZ, maxZ;
202 * Already transformed vertex do not need transform
203 * matrices. Reset all matrices to identity.
204 * Leave the default matrix in world mode.
206 glMatrixMode(GL_PROJECTION);
207 checkGLcall("glMatrixMode");
208 glLoadIdentity();
209 checkGLcall("glLoadIdentity");
210 glMatrixMode(GL_MODELVIEW);
211 checkGLcall("glMatrixMode");
212 glLoadIdentity();
213 checkGLcall("glLoadIdentity");
214 height = This->StateBlock->viewport.Height;
215 width = This->StateBlock->viewport.Width;
216 minZ = This->StateBlock->viewport.MinZ;
217 maxZ = This->StateBlock->viewport.MaxZ;
218 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
219 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
220 checkGLcall("glOrtho");
221 } else {
222 glMatrixMode(GL_PROJECTION);
223 checkGLcall("glMatrixMode");
224 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
225 checkGLcall("glLoadMatrixf");
226 glMatrixMode(GL_MODELVIEW);
227 checkGLcall("glMatrixMode");
228 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
229 checkGLcall("glLoadMatrixf");
230 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
231 checkGLcall("glMultMatrixf");
234 /* Set OpenGL to the appropriate Primitive Type */
235 switch (PrimitiveType) {
236 case D3DPT_POINTLIST:
237 TRACE("POINTS\n");
238 primType = GL_POINTS;
239 NumVertexes = NumPrimitives;
240 break;
242 case D3DPT_LINELIST:
243 TRACE("LINES\n");
244 primType = GL_LINES;
245 NumVertexes = NumPrimitives * 2;
246 break;
248 case D3DPT_LINESTRIP:
249 TRACE("LINE_STRIP\n");
250 primType = GL_LINE_STRIP;
251 NumVertexes = NumPrimitives + 1;
252 break;
254 case D3DPT_TRIANGLELIST:
255 TRACE("TRIANGLES\n");
256 primType = GL_TRIANGLES;
257 NumVertexes = NumPrimitives * 3;
258 break;
260 case D3DPT_TRIANGLESTRIP:
261 TRACE("TRIANGLE_STRIP\n");
262 primType = GL_TRIANGLE_STRIP;
263 NumVertexes = NumPrimitives + 2;
264 break;
266 case D3DPT_TRIANGLEFAN:
267 TRACE("TRIANGLE_FAN\n");
268 primType = GL_TRIANGLE_FAN;
269 NumVertexes = NumPrimitives + 2;
270 break;
272 default:
273 FIXME("Unhandled primitive\n");
274 break;
277 /* Fixme, Ideally, only use this per-vertex code for software HAL
278 but until opengl supports all the functions returned to setup
279 vertex arrays, we need to drop down to the slow mechanism for
280 certain functions */
282 if (isPtSize || isDiffuse || useVertexShaderFunction==TRUE || (numBlends > 0)) {
283 TRACE("Using slow per-vertex code\n");
285 /* Enable this one to be able to debug what is going on, but it is slower
286 than the pointer/array version */
287 VTRACE(("glBegin(%x)\n", primType));
288 glBegin(primType);
290 /* Draw the primitives */
291 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
293 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
295 if (!isIndexed) {
296 curPos = curVtx;
297 } else {
298 if (idxBytes == 2) {
299 VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
300 curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
301 } else {
302 VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
303 curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
307 /* Work through the vertex buffer */
308 x = *(float *)curPos;
309 curPos = curPos + sizeof(float);
310 y = *(float *)curPos;
311 curPos = curPos + sizeof(float);
312 z = *(float *)curPos;
313 curPos = curPos + sizeof(float);
314 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
316 /* RHW follows, only if transformed */
317 if (isRHW) {
318 rhw = *(float *)curPos;
319 curPos = curPos + sizeof(float);
320 VTRACE(("rhw=%f\n", rhw));
323 /* Blending data */
324 if (numBlends > 0) {
325 UINT i;
326 D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
327 DWORD skippedBlendLastUByte4 = 0;
329 for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
330 ((float*)&skippedBlend)[i] = *(float *)curPos;
331 curPos = curPos + sizeof(float);
334 if (isLastUByte4) {
335 skippedBlendLastUByte4 = *(DWORD*)curPos;
336 curPos = curPos + sizeof(DWORD);
340 /* Vertex Normal Data (untransformed only) */
341 if (normal) {
342 nx = *(float *)curPos;
343 curPos = curPos + sizeof(float);
344 ny = *(float *)curPos;
345 curPos = curPos + sizeof(float);
346 nz = *(float *)curPos;
347 curPos = curPos + sizeof(float);
348 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
351 if (isPtSize) {
352 ptSize = *(float *)curPos;
353 VTRACE(("ptSize=%f\n", ptSize));
354 curPos = curPos + sizeof(float);
357 if (isDiffuse) {
358 diffuseColor = *(DWORD *)curPos;
359 VTRACE(("diffuseColor=%lx\n", diffuseColor));
360 curPos = curPos + sizeof(DWORD);
363 if (isSpecular) {
364 specularColor = *(DWORD *)curPos;
365 VTRACE(("specularColor=%lx\n", specularColor));
366 curPos = curPos + sizeof(DWORD);
369 /* Texture coords */
370 /* numTextures indicates the number of texture coordinates supplied */
371 /* However, the first set may not be for stage 0 texture - it all */
372 /* depends on D3DTSS_TEXCOORDINDEX. */
373 /* The number of bytes for each coordinate set is based off */
374 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
376 /* Initialize unused coords to unsupplied so we can check later */
377 for (textureNo = numTextures; textureNo < 7; textureNo++) numCoords[textureNo] = -1;
379 /* So, for each supplied texture extract the coords */
380 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
382 numCoords[textureNo] = coordIdxInfo & 0x03;
384 /* Always one set */
385 s[textureNo] = *(float *)curPos;
386 curPos = curPos + sizeof(float);
387 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
388 t[textureNo] = *(float *)curPos;
389 curPos = curPos + sizeof(float);
390 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
391 r[textureNo] = *(float *)curPos;
392 curPos = curPos + sizeof(float);
393 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
394 q[textureNo] = *(float *)curPos;
395 curPos = curPos + sizeof(float);
400 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
403 /* Now use the appropriate set of texture indexes */
404 for (textureNo = 0; textureNo < This->TextureUnits; ++textureNo) {
406 if (!(This->isMultiTexture) && textureNo > 0) {
407 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
408 continue ;
411 /* Query tex coords */
412 if ((This->StateBlock->textures[textureNo] != NULL) &&
413 (useVertexShaderFunction == FALSE)) {
415 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
417 if (coordIdx > 7) {
418 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
419 } else if (coordIdx >= numTextures) {
420 VTRACE(("tex: %d - Skip tex coords, as requested higher than supplied\n", textureNo));
421 } else {
422 switch (numCoords[coordIdx]) { /* Supply the provided texture coords */
423 case D3DFVF_TEXTUREFORMAT1:
424 VTRACE(("tex:%d, s=%f\n", textureNo, s[coordIdx]));
425 if (This->isMultiTexture) {
426 #if defined(GL_VERSION_1_3)
427 glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s[coordIdx]);
428 #else
429 glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx]);
430 #endif
431 } else {
432 glTexCoord1f(s[coordIdx]);
434 break;
435 case D3DFVF_TEXTUREFORMAT2:
436 VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s[coordIdx], t[coordIdx]));
437 if (This->isMultiTexture) {
438 #if defined(GL_VERSION_1_3)
439 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx]);
440 #else
441 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx]);
442 #endif
443 } else {
444 glTexCoord2f(s[coordIdx], t[coordIdx]);
446 break;
447 case D3DFVF_TEXTUREFORMAT3:
448 VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx]));
449 if (This->isMultiTexture) {
450 #if defined(GL_VERSION_1_3)
451 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
452 #else
453 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx]);
454 #endif
455 } else {
456 glTexCoord3f(s[coordIdx], t[coordIdx], r[coordIdx]);
458 break;
459 case D3DFVF_TEXTUREFORMAT4:
460 VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]));
461 if (This->isMultiTexture) {
462 #if defined(GL_VERSION_1_3)
463 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
464 #else
465 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
466 #endif
467 } else {
468 glTexCoord4f(s[coordIdx], t[coordIdx], r[coordIdx], q[coordIdx]);
470 break;
471 default:
472 FIXME("Should not get here as numCoords is two bits only (%x)!\n", numCoords[coordIdx]);
479 /** if vertex shader program specified ... using it */
480 if (TRUE == useVertexShaderFunction) {
483 * this code must become the really
484 * vs input params init
486 * because its possible to use input registers for anything
487 * and some samples use registers for other things than they are
488 * declared
491 /**
492 * no really valid declaration, user defined input register use
493 * so fill input registers as described in vertex shader declaration
495 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
496 (!isIndexed) ? (vx_index * skip) :
497 (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) :
498 ((pIdxBufL[StartIdx + vx_index]) * skip));
500 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
501 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
503 TRACE_VECTOR(vertex_shader->output.oPos);
504 TRACE_VECTOR(vertex_shader->output.oD[0]);
505 TRACE_VECTOR(vertex_shader->output.oD[1]);
506 TRACE_VECTOR(vertex_shader->output.oT[0]);
507 TRACE_VECTOR(vertex_shader->output.oT[1]);
508 TRACE_VECTOR(vertex_shader->input.V[0]);
509 TRACE_VECTOR(vertex_shader->data->C[0]);
510 TRACE_VECTOR(vertex_shader->data->C[1]);
511 TRACE_VECTOR(vertex_shader->data->C[2]);
512 TRACE_VECTOR(vertex_shader->data->C[3]);
513 TRACE_VECTOR(vertex_shader->data->C[4]);
514 TRACE_VECTOR(vertex_shader->data->C[5]);
515 TRACE_VECTOR(vertex_shader->data->C[6]);
516 TRACE_VECTOR(vertex_shader->data->C[7]);
518 x = vertex_shader->output.oPos.x;
519 y = vertex_shader->output.oPos.y;
520 z = vertex_shader->output.oPos.z;
522 if (1.0f != vertex_shader->output.oPos.w || isRHW) {
523 rhw = vertex_shader->output.oPos.w;
525 /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
526 glColor4fv((float*) &vertex_shader->output.oD[0]);
528 /* Requires secondary color extensions to compile... */
529 #if defined(GL_VERSION_1_4)
530 glSecondaryColor3fv((float*) &vertex_shader->output.oD[1]);
531 checkGLcall("glSecondaryColor3fv");
532 #else
533 if (checkGLSupport(EXT_SECONDARY_COLOR)) {
534 /*specularColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[1]);*/
535 /*GLExtCall(glSecondaryColor3fvEXT)((float*) &vertex_shader->output.oD[1]);*/
536 /*checkGLcall("glSecondaryColor3fvEXT");*/
538 #endif
539 /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
540 for (textureNo = 0; textureNo < 4; ++textureNo) {
541 float s, t, r, q;
543 if (!(This->isMultiTexture) && textureNo > 0) {
544 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
545 continue ;
547 /* Query tex coords */
548 if (This->StateBlock->textures[textureNo] != NULL) {
549 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
550 case D3DRTYPE_TEXTURE:
551 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
552 s = vertex_shader->output.oT[textureNo].x;
553 t = vertex_shader->output.oT[textureNo].y;
554 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
555 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
556 VTRACE(("Skip tex coords, as being system generated\n"));
557 } else {
558 if (This->isMultiTexture) {
559 #if defined(GL_VERSION_1_3)
560 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
561 #else
562 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
563 #endif
564 /*checkGLcall("glMultiTexCoord2fARB");*/
565 } else {
566 glTexCoord2f(s, t);
567 /*checkGLcall("gTexCoord2f");*/
570 break;
572 case D3DRTYPE_VOLUMETEXTURE:
573 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
574 s = vertex_shader->output.oT[textureNo].x;
575 t = vertex_shader->output.oT[textureNo].y;
576 r = vertex_shader->output.oT[textureNo].z;
577 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
578 if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX] > 7) {
579 VTRACE(("Skip tex coords, as being system generated\n"));
580 } else {
581 if (This->isMultiTexture) {
582 #if defined(GL_VERSION_1_3)
583 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
584 #else
585 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
586 #endif
587 /*checkGLcall("glMultiTexCoord2fARB");*/
588 } else {
589 glTexCoord3f(s, t, r);
590 /*checkGLcall("gTexCoord3f");*/
593 break;
595 default:
596 /* Avoid compiler warnings, need these vars later for other textures */
597 r = 0.0f; q = 0.0f;
598 FIXME("Unhandled texture type\n");
603 if (1.0f == rhw || rhw < 0.01f) {
604 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
605 glVertex3f(x, y, z);
606 /*checkGLcall("glVertex3f");*/
607 } else {
608 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
609 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
610 /*checkGLcall("glVertex4f");*/
612 } else {
613 /**
614 * FALSE == useVertexShaderFunction
615 * using std FVF code
618 /* Handle these vertexes */
619 if (isDiffuse) {
620 glColor4ub((diffuseColor >> 16) & 0xFF,
621 (diffuseColor >> 8) & 0xFF,
622 (diffuseColor >> 0) & 0xFF,
623 (diffuseColor >> 24) & 0xFF);
624 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
625 ((diffuseColor >> 16) & 0xFF) / 255.0f,
626 ((diffuseColor >> 8) & 0xFF) / 255.0f,
627 ((diffuseColor >> 0) & 0xFF) / 255.0f,
628 ((diffuseColor >> 24) & 0xFF) / 255.0f));
631 if (normal) {
632 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
633 glNormal3f(nx, ny, nz);
634 glVertex3f(x, y, z);
635 } else {
636 if (1.0f == rhw || rhw < 0.01f) {
637 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
638 glVertex3f(x, y, z);
639 } else {
640 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
641 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
646 if (!isIndexed) {
647 curVtx = curVtx + skip;
651 glEnd();
652 checkGLcall("glEnd and previous calls");
654 } else {
655 TRACE("Using fast vertex array code\n");
657 /* Faster version, harder to debug */
658 /* Shuffle to the beginning of the vertexes to render and index from there */
659 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
660 curPos = curVtx;
662 /* Set up the vertex pointers */
663 if (isRHW) {
664 glVertexPointer(4, GL_FLOAT, skip, curPos);
665 checkGLcall("glVertexPointer(4, ...)");
666 curPos += 4 * sizeof(float);
667 } else {
668 glVertexPointer(3, GL_FLOAT, skip, curPos);
669 checkGLcall("glVertexPointer(3, ...)");
670 curPos += 3 * sizeof(float);
672 glEnableClientState(GL_VERTEX_ARRAY);
673 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
675 if (numBlends > 0) {
676 /* no such functionality in the fixed function GL pipeline */
677 /* FIXME: Wont get here as will drop to slow method */
678 /* FIXME("Cannot handle blending data here in openGl\n");*/
679 if (checkGLSupport(ARB_VERTEX_BLEND)) {
680 FIXME("TODO\n");
681 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
682 FIXME("TODO\n");
684 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
685 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
686 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
687 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
689 curPos += numBlends * sizeof(float);
690 } else {
691 FIXME("unsupported blending in openGl\n");
693 } else {
694 if (checkGLSupport(ARB_VERTEX_BLEND)) {
695 FIXME("TODO\n");
696 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
697 FIXME("TODO\n");
699 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
700 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
706 if (normal) {
707 glNormalPointer(GL_FLOAT, skip, curPos);
708 checkGLcall("glNormalPointer");
709 glEnableClientState(GL_NORMAL_ARRAY);
710 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
711 curPos += 3 * sizeof(float);
712 } else {
713 glDisableClientState(GL_NORMAL_ARRAY);
714 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
715 glNormal3f(0, 0, 1);
716 checkGLcall("glNormal3f(0, 0, 1)");
719 if (isPtSize) {
720 /* no such functionality in the fixed function GL pipeline */
721 /* FIXME: Wont get here as will drop to slow method */
722 FIXME("Cannot change ptSize here in openGl\n");
723 curPos = curPos + sizeof(float);
726 if (isDiffuse) {
727 glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
728 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
729 glEnableClientState(GL_COLOR_ARRAY);
730 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
731 curPos += sizeof(DWORD);
733 else {
734 glDisableClientState(GL_COLOR_ARRAY);
735 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
736 glColor4f(1, 1, 1, 1);
737 checkGLcall("glColor4f(1, 1, 1, 1)");
740 /* Requires secondary color extensions to compile... */
741 if (isSpecular) {
742 #if defined(GL_VERSION_1_4)
743 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
744 checkGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos)");
745 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
746 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
747 #else
748 # if 0
749 /* FIXME: check for GL_EXT_secondary_color */
750 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos);
751 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
752 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
753 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
754 # endif
755 #endif
756 curPos += sizeof(DWORD);
757 } else {
758 #if defined(GL_VERSION_1_4)
759 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
760 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
761 glSecondaryColor3f(0, 0, 0);
762 checkGLcall("glSecondaryColor3f(0, 0, 0)");
763 #else
764 #if 0
765 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
766 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
767 glSecondaryColor3fEXT(0, 0, 0);
768 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
769 #endif
770 #endif
773 /* Texture coords */
774 /* numTextures indicates the number of texture coordinates supplied */
775 /* However, the first set may not be for stage 0 texture - it all */
776 /* depends on D3DTSS_TEXCOORDINDEX. */
777 /* The number of bytes for each coordinate set is based off */
778 /* D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits */
780 /* Initialize unused coords to unsupplied so we can check later */
781 for (textureNo = numTextures; textureNo < 7; textureNo++) coordPtr[textureNo] = NULL;
783 /* So, for each supplied texture extract the coords */
784 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
786 numCoords[textureNo] = coordIdxInfo & 0x03;
787 coordPtr[textureNo] = curPos;
789 /* Always one set */
790 curPos = curPos + sizeof(float);
791 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
792 curPos = curPos + sizeof(float);
793 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
794 curPos = curPos + sizeof(float);
795 if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
796 curPos = curPos + sizeof(float);
800 coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
803 /* Now use the appropriate set of texture indexes */
804 for (textureNo = 0; textureNo < This->TextureUnits; ++textureNo) {
806 if (!(This->isMultiTexture) && textureNo > 0) {
807 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
808 continue ;
811 /* Query tex coords */
812 if ((This->StateBlock->textures[textureNo] != NULL) && (useVertexShaderFunction == FALSE)) {
813 int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
815 if (coordIdx > 7) {
816 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
817 } else {
818 int numFloats = 0;
819 #if defined(GL_VERSION_1_3)
820 glClientActiveTexture(GL_TEXTURE0 + textureNo);
821 #else
822 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
823 #endif
824 switch (numCoords[coordIdx]) { /* Supply the provided texture coords */
825 case D3DFVF_TEXTUREFORMAT1: numFloats = 1; break;
826 case D3DFVF_TEXTUREFORMAT2: numFloats = 2; break;
827 case D3DFVF_TEXTUREFORMAT3: numFloats = 3; break;
828 case D3DFVF_TEXTUREFORMAT4: numFloats = 4; break;
829 default: numFloats = 0; break;
832 if (numFloats == 0 || coordIdx >= numTextures) {
833 VTRACE(("Skipping as invalid request - numfloats=%d, coordIdx=%d, numTextures=%d\n", numFloats, coordIdx, numTextures));
834 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
835 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
836 } else {
837 VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, coordPtr[coordIdx], numFloats));
838 glTexCoordPointer(numFloats, GL_FLOAT, skip, coordPtr[coordIdx]);
839 checkGLcall("glTexCoordPointer(x, ...)");
840 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
841 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
847 /* Finally do the drawing */
848 if (isIndexed) {
850 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
851 if (idxBytes==2) {
852 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
853 glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
854 (char *)idxData+(2 * StartIdx));
855 #else
856 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
857 GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
858 #endif
859 } else {
860 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
861 glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
862 (char *)idxData+(4 * StartIdx));
863 #else
864 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
865 GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
866 #endif
868 checkGLcall("glDrawRangeElements");
870 } else {
872 /* Note first is now zero as we shuffled along earlier */
873 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
874 glDrawArrays(primType, 0, NumVertexes);
875 checkGLcall("glDrawArrays");
880 /* If no normals, restore previous lighting state */
881 if (!normal) {
882 if (isLightingOn) glEnable(GL_LIGHTING);
883 else glDisable(GL_LIGHTING);
884 TRACE("Restored lighting to original state\n");
888 LEAVE_GL();
890 TRACE("glEnd\n");
894 Simple utility routines used for dx -> gl mapping of byte formats
896 SHORT bytesPerPixel(D3DFORMAT fmt) {
897 SHORT retVal;
899 switch (fmt) {
900 /* color buffer */
901 case D3DFMT_A4R4G4B4: retVal = 2; break;
902 case D3DFMT_A8R8G8B8: retVal = 4; break;
903 case D3DFMT_X8R8G8B8: retVal = 4; break;
904 case D3DFMT_R8G8B8: retVal = 3; break;
905 case D3DFMT_R5G6B5: retVal = 2; break;
906 case D3DFMT_A1R5G5B5: retVal = 2; break;
907 /* depth/stencil buffer */
908 case D3DFMT_D16_LOCKABLE: retVal = 2; break;
909 case D3DFMT_D32: retVal = 4; break;
910 case D3DFMT_D15S1: retVal = 2; break;
911 case D3DFMT_D24S8: retVal = 4; break;
912 case D3DFMT_D16: retVal = 2; break;
913 case D3DFMT_D24X8: retVal = 4; break;
914 case D3DFMT_D24X4S4: retVal = 4; break;
915 /* unknown */
916 case D3DFMT_UNKNOWN:
917 /* Guess at the highest value of the above */
918 TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %d\n", fmt);
919 retVal = 4;
920 break;
921 default:
922 FIXME("Unhandled fmt %d\n", fmt);
923 retVal = 4;
925 TRACE("bytes/Pxl for fmt %d = %d\n", fmt, retVal);
926 return retVal;
929 GLint fmt2glintFmt(D3DFORMAT fmt) {
930 GLint retVal;
932 switch (fmt) {
933 case D3DFMT_A4R4G4B4: retVal = GL_RGBA4; break;
934 case D3DFMT_A8R8G8B8: retVal = GL_RGBA8; break;
935 case D3DFMT_X8R8G8B8: retVal = GL_RGB8; break;
936 case D3DFMT_R8G8B8: retVal = GL_RGB8; break;
937 case D3DFMT_R5G6B5: retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
938 case D3DFMT_A1R5G5B5: retVal = GL_RGB5_A1; break;
939 default:
940 FIXME("Unhandled fmt %d\n", fmt);
941 retVal = 4;
943 TRACE("fmt2glintFmt for fmt %d = %x\n", fmt, retVal);
944 return retVal;
946 GLenum fmt2glFmt(D3DFORMAT fmt) {
947 GLenum retVal;
949 switch (fmt) {
950 case D3DFMT_A4R4G4B4: retVal = GL_BGRA; break;
951 case D3DFMT_A8R8G8B8: retVal = GL_BGRA; break;
952 case D3DFMT_X8R8G8B8: retVal = GL_BGRA; break;
953 case D3DFMT_R8G8B8: retVal = GL_BGR; break;
954 case D3DFMT_R5G6B5: retVal = GL_RGB; break;
955 case D3DFMT_A1R5G5B5: retVal = GL_BGRA; break;
956 default:
957 FIXME("Unhandled fmt %d\n", fmt);
958 retVal = 4;
960 TRACE("fmt2glFmt for fmt %d = %x\n", fmt, retVal);
961 return retVal;
963 DWORD fmt2glType(D3DFORMAT fmt) {
964 GLenum retVal;
966 switch (fmt) {
967 case D3DFMT_A4R4G4B4: retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
968 case D3DFMT_A8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
969 case D3DFMT_X8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
970 case D3DFMT_R5G6B5: retVal = GL_UNSIGNED_SHORT_5_6_5_REV; break;
971 case D3DFMT_R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
972 case D3DFMT_A1R5G5B5: retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
973 default:
974 FIXME("Unhandled fmt %d\n", fmt);
975 retVal = 4;
977 TRACE("fmt2glType for fmt %d = %x\n", fmt, retVal);
978 return retVal;
981 int SOURCEx_RGB_EXT(DWORD arg) {
982 switch(arg) {
983 case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
984 case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
985 case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
986 case D3DTSS_ALPHAARG0:
987 case D3DTSS_ALPHAARG1:
988 case D3DTSS_ALPHAARG2:
989 default:
990 FIXME("Invalid arg %ld\n", arg);
991 return GL_SOURCE0_RGB_EXT;
994 int OPERANDx_RGB_EXT(DWORD arg) {
995 switch(arg) {
996 case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
997 case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
998 case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
999 case D3DTSS_ALPHAARG0:
1000 case D3DTSS_ALPHAARG1:
1001 case D3DTSS_ALPHAARG2:
1002 default:
1003 FIXME("Invalid arg %ld\n", arg);
1004 return GL_OPERAND0_RGB_EXT;
1007 int SOURCEx_ALPHA_EXT(DWORD arg) {
1008 switch(arg) {
1009 case D3DTSS_ALPHAARG0: return GL_SOURCE2_ALPHA_EXT;
1010 case D3DTSS_ALPHAARG1: return GL_SOURCE0_ALPHA_EXT;
1011 case D3DTSS_ALPHAARG2: return GL_SOURCE1_ALPHA_EXT;
1012 case D3DTSS_COLORARG0:
1013 case D3DTSS_COLORARG1:
1014 case D3DTSS_COLORARG2:
1015 default:
1016 FIXME("Invalid arg %ld\n", arg);
1017 return GL_SOURCE0_ALPHA_EXT;
1020 int OPERANDx_ALPHA_EXT(DWORD arg) {
1021 switch(arg) {
1022 case D3DTSS_ALPHAARG0: return GL_OPERAND2_ALPHA_EXT;
1023 case D3DTSS_ALPHAARG1: return GL_OPERAND0_ALPHA_EXT;
1024 case D3DTSS_ALPHAARG2: return GL_OPERAND1_ALPHA_EXT;
1025 case D3DTSS_COLORARG0:
1026 case D3DTSS_COLORARG1:
1027 case D3DTSS_COLORARG2:
1028 default:
1029 FIXME("Invalid arg %ld\n", arg);
1030 return GL_OPERAND0_ALPHA_EXT;
1033 GLenum StencilOp(DWORD op) {
1034 switch(op) {
1035 case D3DSTENCILOP_KEEP : return GL_KEEP;
1036 case D3DSTENCILOP_ZERO : return GL_ZERO;
1037 case D3DSTENCILOP_REPLACE : return GL_REPLACE;
1038 case D3DSTENCILOP_INCRSAT : return GL_INCR;
1039 case D3DSTENCILOP_DECRSAT : return GL_DECR;
1040 case D3DSTENCILOP_INVERT : return GL_INVERT;
1041 case D3DSTENCILOP_INCR : FIXME("Unsupported stencil op D3DSTENCILOP_INCR\n");
1042 return GL_INCR; /* Fixme - needs to support wrap */
1043 case D3DSTENCILOP_DECR : FIXME("Unsupported stencil op D3DSTENCILOP_DECR\n");
1044 return GL_DECR; /* Fixme - needs to support wrap */
1045 default:
1046 FIXME("Invalid stencil op %ld\n", op);
1047 return GL_ALWAYS;
1052 * @nodoc: todo
1054 void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand)
1056 BOOL isAlphaReplicate = FALSE;
1057 BOOL isComplement = FALSE;
1059 *operand = GL_SRC_COLOR;
1060 *source = GL_TEXTURE;
1062 /* Catch alpha replicate */
1063 if (iValue & D3DTA_ALPHAREPLICATE) {
1064 iValue = iValue & ~D3DTA_ALPHAREPLICATE;
1065 isAlphaReplicate = TRUE;
1068 /* Catch Complement */
1069 if (iValue & D3DTA_COMPLEMENT) {
1070 iValue = iValue & ~D3DTA_COMPLEMENT;
1071 isComplement = TRUE;
1074 /* Calculate the operand */
1075 if (isAlphaReplicate && !isComplement) {
1076 *operand = GL_SRC_ALPHA;
1077 } else if (isAlphaReplicate && isComplement) {
1078 *operand = GL_ONE_MINUS_SRC_ALPHA;
1079 } else if (isComplement) {
1080 if (isAlphaArg) {
1081 *operand = GL_ONE_MINUS_SRC_ALPHA;
1082 } else {
1083 *operand = GL_ONE_MINUS_SRC_COLOR;
1085 } else {
1086 if (isAlphaArg) {
1087 *operand = GL_SRC_ALPHA;
1088 } else {
1089 *operand = GL_SRC_COLOR;
1093 /* Calculate the source */
1094 switch (iValue & D3DTA_SELECTMASK) {
1095 case D3DTA_CURRENT: *source = GL_PREVIOUS_EXT;
1096 break;
1097 case D3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT;
1098 break;
1099 case D3DTA_TEXTURE: *source = GL_TEXTURE;
1100 break;
1101 case D3DTA_TFACTOR: *source = GL_CONSTANT_EXT;
1102 break;
1103 case D3DTA_SPECULAR:
1105 * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
1106 * isnt supported until base GL supports it
1107 * There is no concept of temp registers as far as I can tell
1110 default:
1111 FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
1112 *source = GL_TEXTURE;
1117 /* Apply the current values to the specified texture stage */
1118 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
1119 ICOM_THIS(IDirect3DDevice8Impl,iface);
1120 int i=0;
1121 float col[4];
1123 /* Make appropriate texture active */
1124 if (This->isMultiTexture) {
1125 #if defined(GL_VERSION_1_3)
1126 glActiveTexture(GL_TEXTURE0 + Stage);
1127 #else
1128 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1129 #endif
1130 checkGLcall("glActiveTextureARB");
1131 } else if (Stage > 0) {
1132 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1135 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
1136 for (i=1; i<HIGHEST_TEXTURE_STATE; i++) {
1137 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1140 /* Note the D3DRS value applies to all textures, but GL has one
1141 per texture, so apply it now ready to be used! */
1142 col[0] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR]>> 16) & 0xFF) / 255.0;
1143 col[1] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 8 ) & 0xFF) / 255.0;
1144 col[2] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 0 ) & 0xFF) / 255.0;
1145 col[3] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 24 ) & 0xFF) / 255.0;
1146 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1147 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1149 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1152 /* IDirect3D IUnknown parts follow: */
1153 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1155 ICOM_THIS(IDirect3DDevice8Impl,iface);
1157 if (IsEqualGUID(riid, &IID_IUnknown)
1158 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1159 IDirect3DDevice8Impl_AddRef(iface);
1160 *ppobj = This;
1161 return D3D_OK;
1164 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1165 return E_NOINTERFACE;
1168 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1169 ICOM_THIS(IDirect3DDevice8Impl,iface);
1170 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1171 return ++(This->ref);
1174 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1175 ICOM_THIS(IDirect3DDevice8Impl,iface);
1176 ULONG ref = --This->ref;
1177 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1178 if (ref == 0) {
1179 HeapFree(GetProcessHeap(), 0, This);
1181 return ref;
1184 /* IDirect3DDevice Interface follow: */
1185 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1186 ICOM_THIS(IDirect3DDevice8Impl,iface);
1187 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
1188 return D3D_OK;
1191 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1192 ICOM_THIS(IDirect3DDevice8Impl,iface);
1193 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1195 * pretend we have 32MB of any type of memory queried.
1197 return (1024*1024*32);
1200 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1201 ICOM_THIS(IDirect3DDevice8Impl,iface);
1202 FIXME("(%p) : stub\n", This); return D3D_OK;
1204 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1205 ICOM_THIS(IDirect3DDevice8Impl,iface);
1206 TRACE("(%p) : returning %p\n", This, This->direct3d8);
1208 /* Inc ref count */
1209 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1211 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1212 return D3D_OK;
1214 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1215 ICOM_THIS(IDirect3DDevice8Impl,iface);
1216 FIXME("(%p) : stub, calling idirect3d for now\n", This);
1217 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1218 return D3D_OK;
1220 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1222 HDC hdc;
1223 int bpp = 0;
1225 ICOM_THIS(IDirect3DDevice8Impl,iface);
1226 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
1227 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
1228 pMode->RefreshRate = 85; /*FIXME: How to identify? */
1230 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1231 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1232 DeleteDC(hdc);
1234 switch (bpp) {
1235 case 8: pMode->Format = D3DFMT_R8G8B8; break;
1236 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1237 case 24: pMode->Format = D3DFMT_R8G8B8; break;
1238 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1239 default:
1240 FIXME("Unrecognized display mode format\n");
1241 pMode->Format = D3DFMT_UNKNOWN;
1244 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%d)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format);
1245 return D3D_OK;
1247 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1248 ICOM_THIS(IDirect3DDevice8Impl,iface);
1249 TRACE("(%p) copying to %p\n", This, pParameters);
1250 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1251 return D3D_OK;
1253 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1254 ICOM_THIS(IDirect3DDevice8Impl,iface);
1255 FIXME("(%p) : stub\n", This); return D3D_OK;
1257 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace,DWORD Flags) {
1258 ICOM_THIS(IDirect3DDevice8Impl,iface);
1259 FIXME("(%p) : stub\n", This); return;
1261 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1262 ICOM_THIS(IDirect3DDevice8Impl,iface);
1263 FIXME("(%p) : stub\n", This); return D3D_OK;
1265 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1266 ICOM_THIS(IDirect3DDevice8Impl,iface);
1267 FIXME("(%p) : stub\n", This);
1268 *pSwapChain = NULL;
1269 return D3D_OK;
1271 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1272 ICOM_THIS(IDirect3DDevice8Impl,iface);
1273 FIXME("(%p) : stub\n", This); return D3D_OK;
1275 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1276 ICOM_THIS(IDirect3DDevice8Impl,iface);
1277 TRACE("(%p) : complete stub!\n", This);
1279 ENTER_GL();
1281 glXSwapBuffers(This->display, This->win);
1282 checkGLcall("glXSwapBuffers");
1284 LEAVE_GL();
1286 return D3D_OK;
1288 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
1289 ICOM_THIS(IDirect3DDevice8Impl,iface);
1290 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1291 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1293 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
1294 FIXME("Only one backBuffer currently supported\n");
1295 return D3DERR_INVALIDCALL;
1298 /* Note inc ref on returned surface */
1299 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1301 return D3D_OK;
1303 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1304 ICOM_THIS(IDirect3DDevice8Impl,iface);
1305 FIXME("(%p) : stub\n", This);
1306 return D3D_OK;
1308 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags,CONST D3DGAMMARAMP* pRamp) {
1309 ICOM_THIS(IDirect3DDevice8Impl,iface);
1310 FIXME("(%p) : stub\n", This); return;
1312 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1313 ICOM_THIS(IDirect3DDevice8Impl,iface);
1314 FIXME("(%p) : stub\n", This); return;
1316 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1317 D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture8** ppTexture) {
1318 IDirect3DTexture8Impl *object;
1319 int i;
1320 UINT tmpW;
1321 UINT tmpH;
1323 ICOM_THIS(IDirect3DDevice8Impl,iface);
1325 /* Allocate the storage for the device */
1326 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool);
1327 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1328 object->lpVtbl = &Direct3DTexture8_Vtbl;
1329 object->Device = This;
1330 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->device);*/
1331 object->ResourceType = D3DRTYPE_TEXTURE;
1332 object->ref = 1;
1333 object->width = Width;
1334 object->height = Height;
1335 object->levels = Levels;
1336 object->usage = Usage;
1337 object->format = Format;
1340 /* Calculate levels for mip mapping */
1341 if (Levels == 0) {
1342 object->levels++;
1343 tmpW = Width;
1344 tmpH = Height;
1345 while (tmpW > 1 && tmpH > 1) {
1346 tmpW = max(1, tmpW / 2);
1347 tmpH = max(1, tmpH / 2);
1348 object->levels++;
1350 TRACE("Calculated levels = %d\n", object->levels);
1353 /* Generate all the surfaces */
1354 tmpW = Width;
1355 tmpH = Height;
1356 for (i = 0; i < object->levels; i++)
1358 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1359 object->surfaces[i]->Container = (IUnknown*) object;
1360 /*IUnknown_AddRef(object->surfaces[i]->Container);*/
1361 object->surfaces[i]->myDesc.Usage = Usage;
1362 object->surfaces[i]->myDesc.Pool = Pool ;
1364 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1365 tmpW = max(1, tmpW / 2);
1366 tmpH = max(1, tmpH / 2);
1369 *ppTexture = (LPDIRECT3DTEXTURE8) object;
1370 return D3D_OK;
1372 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture) {
1374 IDirect3DVolumeTexture8Impl *object;
1375 int i;
1376 UINT tmpW;
1377 UINT tmpH;
1378 UINT tmpD;
1380 ICOM_THIS(IDirect3DDevice8Impl,iface);
1382 /* Allocate the storage for it */
1383 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);
1384 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1385 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1386 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1387 object->Device = This;
1388 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1389 object->ref = 1;
1391 object->width = Width;
1392 object->height = Height;
1393 object->depth = Depth;
1394 object->levels = Levels;
1395 object->usage = Usage;
1396 object->format = Format;
1398 /* Calculate levels for mip mapping */
1399 if (Levels == 0) {
1400 object->levels++;
1401 tmpW = Width;
1402 tmpH = Height;
1403 tmpD = Depth;
1404 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1405 tmpW = max(1, tmpW / 2);
1406 tmpH = max(1, tmpH / 2);
1407 tmpD = max(1, tmpD / 2);
1408 object->levels++;
1410 TRACE("Calculated levels = %d\n", object->levels);
1413 /* Generate all the surfaces */
1414 tmpW = Width;
1415 tmpH = Height;
1416 tmpD = Depth;
1418 for (i = 0; i < object->levels; i++)
1420 IDirect3DVolume8Impl *volume;
1422 /* Create the volume - No entry point for this seperately?? */
1423 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1424 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1426 volume->lpVtbl = &Direct3DVolume8_Vtbl;
1427 volume->Device = This;
1428 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) volume->Device);*/
1429 volume->ResourceType = D3DRTYPE_VOLUME;
1430 volume->Container = (IUnknown*) object;
1431 /*IUnknown_AddRef(volume->Container);*/
1432 volume->ref = 1;
1434 volume->myDesc.Width = Width;
1435 volume->myDesc.Height = Height;
1436 volume->myDesc.Depth = Depth;
1437 volume->myDesc.Format = Format;
1438 volume->myDesc.Type = D3DRTYPE_VOLUME;
1439 volume->myDesc.Pool = Pool;
1440 volume->myDesc.Usage = Usage;
1441 volume->bytesPerPixel = bytesPerPixel(Format);
1442 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
1443 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1445 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Depth, Format,
1446 volume, volume->allocatedMemory, volume->myDesc.Size);
1448 tmpW = max(1, tmpW / 2);
1449 tmpH = max(1, tmpH / 2);
1450 tmpD = max(1, tmpD / 2);
1453 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
1454 return D3D_OK;
1456 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
1458 IDirect3DCubeTexture8Impl *object;
1459 ICOM_THIS(IDirect3DDevice8Impl,iface);
1460 int i,j;
1461 UINT tmpW;
1463 /* Allocate the storage for it */
1464 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, Pool);
1465 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1466 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1467 object->ref = 1;
1468 object->Device = This;
1469 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1470 object->ResourceType = D3DRTYPE_CUBETEXTURE;
1472 object->edgeLength = EdgeLength;
1473 object->levels = Levels;
1474 object->usage = Usage;
1475 object->format = Format;
1477 /* Calculate levels for mip mapping */
1478 if (Levels == 0) {
1479 object->levels++;
1480 tmpW = EdgeLength;
1481 while (tmpW > 1) {
1482 tmpW = max(1, tmpW / 2);
1483 object->levels++;
1485 TRACE("Calculated levels = %d\n", object->levels);
1488 /* Generate all the surfaces */
1489 tmpW = EdgeLength;
1490 for (i = 0; i < object->levels; i++)
1492 /* Create the 6 faces */
1493 for (j = 0; j < 6; j++) {
1494 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1495 object->surfaces[j][i]->Container = (IUnknown*) object;
1496 /*IUnknown_AddRef(object->surfaces[j][i]->Container);*/
1497 object->surfaces[j][i]->myDesc.Usage = Usage;
1498 object->surfaces[j][i]->myDesc.Pool = Pool;
1500 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1501 tmpW = max(1, tmpW / 2);
1505 TRACE("(%p) : Iface@%p\n", This, object);
1506 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1507 return D3D_OK;
1509 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1510 IDirect3DVertexBuffer8Impl *object;
1512 ICOM_THIS(IDirect3DDevice8Impl,iface);
1514 /* Allocate the storage for the device */
1515 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1516 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1517 object->Device = This;
1518 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1519 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1520 object->ref = 1;
1521 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1522 object->currentDesc.Usage = Usage;
1523 object->currentDesc.Pool = Pool;
1524 object->currentDesc.FVF = FVF;
1525 object->currentDesc.Size = Size;
1527 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1529 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1531 return D3D_OK;
1533 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
1534 IDirect3DIndexBuffer8Impl *object;
1536 ICOM_THIS(IDirect3DDevice8Impl,iface);
1537 TRACE("(%p) : Len=%d, Use=%lx, Format=%x, Pool=%d\n", This, Length, Usage, Format, Pool);
1539 /* Allocate the storage for the device */
1540 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1541 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1542 object->Device = This;
1543 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1544 object->ref = 1;
1545 object->ResourceType = D3DRTYPE_INDEXBUFFER;
1547 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1548 object->currentDesc.Usage = Usage;
1549 object->currentDesc.Pool = Pool;
1550 object->currentDesc.Format = Format;
1551 object->currentDesc.Size = Length;
1553 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1555 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1557 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1559 return D3D_OK;
1561 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
1562 IDirect3DSurface8Impl *object;
1564 ICOM_THIS(IDirect3DDevice8Impl,iface);
1566 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1567 if (NULL == object) {
1568 *ppSurface = NULL;
1569 return D3DERR_OUTOFVIDEOMEMORY;
1571 *ppSurface = (LPDIRECT3DSURFACE8) object;
1572 object->lpVtbl = &Direct3DSurface8_Vtbl;
1573 object->Device = This;
1574 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1575 object->ResourceType = D3DRTYPE_SURFACE;
1576 object->Container = (IUnknown*) This;
1577 /*IUnknown_AddRef(object->Container);*/
1579 object->ref = 1;
1580 object->myDesc.Width = Width;
1581 object->myDesc.Height = Height;
1582 object->myDesc.Format = Format;
1583 object->myDesc.Type = D3DRTYPE_SURFACE;
1584 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
1585 object->myDesc.Pool = D3DPOOL_DEFAULT;
1586 object->myDesc.MultiSampleType = MultiSample;
1587 object->bytesPerPixel = bytesPerPixel(Format);
1588 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1589 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1590 object->lockable = Lockable;
1591 object->locked = FALSE;
1593 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);
1594 return D3D_OK;
1596 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
1597 IDirect3DSurface8Impl *object;
1599 ICOM_THIS(IDirect3DDevice8Impl,iface);
1601 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1602 if (NULL == object) {
1603 *ppSurface = NULL;
1604 return D3DERR_OUTOFVIDEOMEMORY;
1606 *ppSurface = (LPDIRECT3DSURFACE8) object;
1607 object->lpVtbl = &Direct3DSurface8_Vtbl;
1608 object->Device = This;
1609 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1610 object->ResourceType = D3DRTYPE_SURFACE;
1611 object->Container = (IUnknown*) This;
1612 /*IUnknown_AddRef(object->Container);*/
1614 object->ref = 1;
1615 object->myDesc.Width = Width;
1616 object->myDesc.Height = Height;
1617 object->myDesc.Format = Format;
1618 object->myDesc.Type = D3DRTYPE_SURFACE;
1619 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
1620 object->myDesc.Pool = D3DPOOL_DEFAULT;
1621 object->myDesc.MultiSampleType = MultiSample;
1622 object->bytesPerPixel = bytesPerPixel(Format);
1623 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1624 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1625 object->lockable = TRUE;
1626 object->locked = FALSE;
1628 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);
1629 return D3D_OK;
1631 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
1632 IDirect3DSurface8Impl *object;
1634 ICOM_THIS(IDirect3DDevice8Impl,iface);
1636 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1637 *ppSurface = (LPDIRECT3DSURFACE8) object;
1638 object->lpVtbl = &Direct3DSurface8_Vtbl;
1639 object->Device = This;
1640 /*IDirect3DDevice8Impl_AddRef((LPDIRECT3DDEVICE8) object->Device);*/
1641 object->ResourceType = D3DRTYPE_SURFACE;
1642 object->Container = (IUnknown*) This;
1643 /*IUnknown_AddRef(object->Container);*/
1645 object->ref = 1;
1646 object->myDesc.Width = Width;
1647 object->myDesc.Height = Height;
1648 object->myDesc.Format = Format;
1649 object->myDesc.Type = D3DRTYPE_SURFACE;
1650 object->myDesc.Usage = 0;
1651 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
1652 object->bytesPerPixel = bytesPerPixel(Format);
1653 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1654 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1655 object->lockable = TRUE;
1656 object->locked = FALSE;
1658 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);
1659 return D3D_OK;
1661 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pSourceSurface,CONST RECT* pSourceRectsArray,UINT cRects,
1662 IDirect3DSurface8* pDestinationSurface,CONST POINT* pDestPointsArray) {
1664 HRESULT rc = D3D_OK;
1665 IDirect3DBaseTexture8* texture = NULL;
1668 IDirect3DSurface8Impl *src = (IDirect3DSurface8Impl*) pSourceSurface;
1669 IDirect3DSurface8Impl *dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1671 ICOM_THIS(IDirect3DDevice8Impl,iface);
1672 TRACE("(%p) srcsur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1673 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1675 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1676 a sample and doesnt seem to break anything as far as I can tell */
1677 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1678 TRACE("Formats do not match %x / %x\n", src->myDesc.Format, dst->myDesc.Format);
1679 rc = D3DERR_INVALIDCALL;
1681 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1682 TRACE("Converting dest to same format as source, since dest was unknown\n");
1683 dst->myDesc.Format = src->myDesc.Format;
1685 /* Convert container as well */
1686 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1687 if (texture != NULL) {
1689 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1690 case D3DRTYPE_TEXTURE:
1691 ((IDirect3DTexture8Impl *)texture)->format = src->myDesc.Format;
1692 break;
1693 case D3DRTYPE_VOLUMETEXTURE:
1694 ((IDirect3DVolumeTexture8Impl *)texture)->format = src->myDesc.Format;
1695 break;
1696 case D3DRTYPE_CUBETEXTURE:
1697 ((IDirect3DCubeTexture8Impl *)texture)->format = src->myDesc.Format;
1698 break;
1699 default:
1700 FIXME("Unhandled texture type\n");
1703 /** Releasing texture after GetContainer */
1704 IDirect3DBaseTexture8_Release(texture);
1708 /* Quick if complete copy ... */
1709 if (rc == D3D_OK && (cRects == 0 && pSourceRectsArray==NULL && pDestPointsArray==NULL &&
1710 src->myDesc.Width == dst->myDesc.Width &&
1711 src->myDesc.Height == dst->myDesc.Height)) {
1712 D3DLOCKED_RECT lr;
1714 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)src, &lr, NULL, D3DLOCK_READONLY);
1715 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)dst, &lr, NULL, D3DLOCK_DISCARD);
1716 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1718 memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);
1720 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)src);
1721 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)dst);
1722 TRACE("Unlocked src and dst\n");
1724 } else {
1725 int i;
1726 int bytesPerPixel = ((IDirect3DSurface8Impl *)pSourceSurface)->bytesPerPixel;
1727 int pitchFrom = ((IDirect3DSurface8Impl *)pSourceSurface)->myDesc.Width * bytesPerPixel;
1728 int pitchTo = ((IDirect3DSurface8Impl *)pDestinationSurface)->myDesc.Width * bytesPerPixel;
1730 char *copyfrom = ((IDirect3DSurface8Impl *)pSourceSurface)->allocatedMemory;
1731 char *copyto = ((IDirect3DSurface8Impl *)pDestinationSurface)->allocatedMemory;
1733 /* Copy rect by rect */
1734 for (i=0; i<cRects; i++) {
1735 CONST RECT *r = &pSourceRectsArray[i];
1736 CONST POINT *p = &pDestPointsArray[i];
1737 char *from;
1738 char *to;
1739 int copyperline = (r->right - r->left) * bytesPerPixel;
1740 int j;
1741 D3DLOCKED_RECT lr;
1742 RECT dest_rect;
1744 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top,
1745 r->right, r->bottom, p->x, p->y);
1747 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)src, &lr, r, D3DLOCK_READONLY);
1748 dest_rect.left = p->x;
1749 dest_rect.top = p->y;
1750 dest_rect.right = p->x + (r->right - r->left);
1751 dest_rect.left = p->y + (r->bottom - r->top);
1752 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8)dst, &lr, &dest_rect, 0L);
1753 TRACE("Locked src and dst\n");
1755 /* Find where to start */
1756 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1757 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
1759 /* Copy line by line */
1760 for (j=0; j<(r->bottom - r->top); j++) {
1761 memcpy(to + (j*pitchTo), from + (j*pitchFrom), copyperline);
1764 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)src);
1765 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8)dst);
1766 TRACE("Unlocked src and dst\n");
1770 /* Set dirty */
1771 if (rc == D3D_OK) {
1772 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1773 if (texture != NULL) {
1775 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1776 case D3DRTYPE_TEXTURE:
1778 IDirect3DTexture8Impl *pTexture = (IDirect3DTexture8Impl *)texture;
1779 pTexture->Dirty = TRUE;
1781 break;
1782 case D3DRTYPE_VOLUMETEXTURE:
1784 IDirect3DVolumeTexture8Impl *pTexture = (IDirect3DVolumeTexture8Impl *)texture;
1785 pTexture->Dirty = TRUE;
1787 break;
1788 case D3DRTYPE_CUBETEXTURE:
1790 IDirect3DCubeTexture8Impl *pTexture = (IDirect3DCubeTexture8Impl *)texture;
1791 pTexture->Dirty = TRUE;
1793 break;
1794 default:
1795 FIXME("Unhandled texture type\n");
1798 /** Releasing texture after GetContainer */
1799 IDirect3DBaseTexture8_Release(texture);
1803 return D3D_OK;
1805 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1806 ICOM_THIS(IDirect3DDevice8Impl,iface);
1807 FIXME("(%p) : stub\n", This);
1808 return D3D_OK;
1810 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1811 HRESULT hr;
1812 D3DLOCKED_RECT lockedRect;
1813 GLint prev_store;
1814 GLenum prev_read;
1816 ICOM_THIS(IDirect3DDevice8Impl,iface);
1818 FIXME("(%p) : stub\n", This);
1820 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1821 return D3DERR_INVALIDCALL;
1824 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, NULL, 0);
1825 if (FAILED(hr)) {
1826 return D3DERR_INVALIDCALL;
1829 ENTER_GL();
1831 glFlush();
1832 vcheckGLcall("glFlush");
1833 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1834 vcheckGLcall("glIntegerv");
1835 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1836 vcheckGLcall("glIntegerv");
1838 glReadBuffer(GL_FRONT);
1839 vcheckGLcall("glReadBuffer");
1840 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1841 vcheckGLcall("glPixelStorei");
1842 glReadPixels(0, 0, This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight,
1843 GL_BGRA, GL_UNSIGNED_BYTE, lockedRect.pBits);
1844 vcheckGLcall("glReadPixels");
1845 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1846 vcheckGLcall("glPixelStorei");
1847 glReadBuffer(prev_read);
1848 vcheckGLcall("glReadBuffer");
1849 LEAVE_GL();
1851 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1852 return hr;
1854 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1855 ICOM_THIS(IDirect3DDevice8Impl,iface);
1857 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1858 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1859 return D3D_OK;
1862 FIXME("(%p) : invalid stub expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1864 return D3D_OK;
1866 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1867 ICOM_THIS(IDirect3DDevice8Impl,iface);
1869 TRACE("(%p)->(%p)\n", This, This->frontBuffer);
1871 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->frontBuffer;
1872 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1874 return D3D_OK;
1876 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1877 ICOM_THIS(IDirect3DDevice8Impl,iface);
1879 TRACE("(%p)->(%p)\n", This, ppZStencilSurface);
1881 /* Note inc ref on returned surface */
1882 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->depthStencilBuffer;
1883 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1885 return D3D_OK;
1888 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1889 ICOM_THIS(IDirect3DDevice8Impl,iface);
1890 TRACE("(%p) : stub\n", This);
1891 return D3D_OK;
1893 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1894 ICOM_THIS(IDirect3DDevice8Impl,iface);
1895 TRACE("(%p)\n", This);
1897 ENTER_GL();
1899 glFlush();
1900 checkGLcall("glFlush");
1902 /* Useful for debugging sometimes!
1903 printf("Hit Enter ...\n");
1904 getchar(); */
1906 LEAVE_GL();
1907 return D3D_OK;
1909 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) {
1910 ICOM_THIS(IDirect3DDevice8Impl,iface);
1912 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1913 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1914 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1915 GLbitfield glMask = 0;
1916 GLboolean old_ztest;
1917 GLfloat old_z_clear_value;
1918 GLint old_stencil_clear_value;
1919 GLfloat old_color_clear_value[4];
1921 int i;
1922 CONST D3DRECT *curRect;
1924 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1925 Count, pRects, Flags, Z, Stencil);
1927 ENTER_GL();
1928 if (Count > 0 && pRects) {
1929 glEnable(GL_SCISSOR_TEST);
1930 checkGLcall("glEnable GL_SCISSOR_TEST");
1931 curRect = pRects;
1932 } else {
1933 curRect = NULL;
1936 for (i = 0; i < Count || i == 0; i++) {
1938 if (curRect) {
1939 /* Note gl uses lower left, width/height */
1940 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1941 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1942 curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1943 glScissor(curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1944 checkGLcall("glScissor");
1947 /* Clear the whole screen */
1948 if (Flags & D3DCLEAR_STENCIL) {
1949 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1950 glClearStencil(Stencil);
1951 checkGLcall("glClearStencil");
1952 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1955 if (Flags & D3DCLEAR_ZBUFFER) {
1956 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1957 glDepthMask(GL_TRUE);
1958 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1959 glClearDepth(Z);
1960 checkGLcall("glClearDepth");
1961 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1964 if (Flags & D3DCLEAR_TARGET) {
1965 TRACE("Clearing screen with glClear to color %lx\n", Color);
1966 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1967 glClearColor(((Color >> 16) & 0xFF) / 255.0,
1968 ((Color >> 8) & 0xFF) / 255.0,
1969 ((Color >> 0) & 0xFF) / 255.0,
1970 ((Color >> 24) & 0xFF) / 255.0);
1971 checkGLcall("glClearColor");
1972 glMask = glMask | GL_COLOR_BUFFER_BIT;
1975 glClear(glMask);
1976 checkGLcall("glClear");
1978 if (Flags & D3DCLEAR_STENCIL) {
1979 glClearStencil(old_stencil_clear_value);
1981 if (Flags & D3DCLEAR_ZBUFFER) {
1982 glDepthMask(old_ztest);
1983 glClearDepth(old_z_clear_value);
1985 if (Flags & D3DCLEAR_TARGET) {
1986 glClearColor(old_color_clear_value[0],
1987 old_color_clear_value[1],
1988 old_color_clear_value[2],
1989 old_color_clear_value[3]);
1992 if (curRect) curRect = curRect + sizeof(D3DRECT);
1995 if (Count > 0 && pRects) {
1996 glDisable(GL_SCISSOR_TEST);
1997 checkGLcall("glDisable");
1999 LEAVE_GL();
2001 return D3D_OK;
2003 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
2004 ICOM_THIS(IDirect3DDevice8Impl,iface);
2005 D3DMATRIX m;
2006 int k;
2007 float f;
2008 BOOL viewChanged = TRUE;
2009 int Stage;
2011 /* Most of this routine, comments included copied from ddraw tree initially: */
2012 TRACE("(%p) : State=%d\n", This, d3dts);
2014 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
2015 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
2016 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
2018 /* Handle recording of state blocks */
2019 if (This->isRecordingState) {
2020 TRACE("Recording... not performing anything\n");
2021 return D3D_OK;
2025 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2027 where ViewMat = Camera space, WorldMat = world space.
2029 In OpenGL, camera and world space is combined into GL_MODELVIEW
2030 matrix. The Projection matrix stay projection matrix. */
2032 /* After reading through both OpenGL and Direct3D documentations, I
2033 thought that D3D matrices were written in 'line major mode' transposed
2034 from OpenGL's 'column major mode'. But I found out that a simple memcpy
2035 works fine to transfer one matrix format to the other (it did not work
2036 when transposing)....
2038 So :
2039 1) are the documentations wrong
2040 2) does the matrix work even if they are not read correctly
2041 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
2042 loading using glLoadMatrix ?
2044 Anyway, I always use 'conv_mat' to transfer the matrices from one format
2045 to the other so that if I ever find out that I need to transpose them, I
2046 will able to do it quickly, only by changing the macro conv_mat. */
2048 if (d3dts <= 256) { /* WORLDMATRIX(0) == 256! */
2049 switch (d3dts) {
2050 case D3DTS_WORLDMATRIX(0):
2051 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)]);
2052 break;
2054 case D3DTS_VIEW:
2055 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
2056 break;
2058 case D3DTS_PROJECTION:
2059 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
2060 break;
2062 case D3DTS_TEXTURE0:
2063 case D3DTS_TEXTURE1:
2064 case D3DTS_TEXTURE2:
2065 case D3DTS_TEXTURE3:
2066 case D3DTS_TEXTURE4:
2067 case D3DTS_TEXTURE5:
2068 case D3DTS_TEXTURE6:
2069 case D3DTS_TEXTURE7:
2070 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2071 break;
2073 default:
2074 FIXME("Unhandled transform state!!\n");
2075 break;
2077 } else {
2078 /**
2079 * Indexed Vertex Blending Matrices 256 -> 511
2081 /** store it */
2082 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
2083 if (checkGLSupport(ARB_VERTEX_BLEND)) {
2084 FIXME("TODO\n");
2085 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
2086 FIXME("TODO\n");
2091 * Move the GL operation to outside of switch to make it work
2092 * regardless of transform set order.
2094 ENTER_GL();
2095 if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
2096 glMatrixMode(GL_PROJECTION);
2097 checkGLcall("glMatrixMode");
2098 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
2099 checkGLcall("glLoadMatrixf");
2100 memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
2101 } else {
2102 TRACE("Skipping as projection already correct\n");
2105 glMatrixMode(GL_MODELVIEW);
2106 checkGLcall("glMatrixMode");
2107 viewChanged = FALSE;
2108 if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
2109 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2110 checkGLcall("glLoadMatrixf");
2111 memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
2112 viewChanged = TRUE;
2114 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
2115 if (d3dts == D3DTS_VIEW) {
2117 /* NOTE: We have to reset the positions even if the light/plane is not currently
2118 enabled, since the call to enable it will not reset the position. */
2120 /* Reset lights */
2121 for (k = 0; k < This->maxLights; k++) {
2122 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
2123 checkGLcall("glLightfv posn");
2124 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
2125 checkGLcall("glLightfv dirn");
2128 /* Reset Clipping Planes if clipping is enabled */
2129 for (k = 0; k < This->clipPlanes; k++) {
2130 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
2131 checkGLcall("glClipPlane");
2134 /* Reapply texture transforms as based off modelview when applied */
2135 for (Stage = 0; Stage < This->TextureUnits; Stage++) {
2137 /* Now apply texture transforms if not applying to the dummy textures */
2138 #if defined(GL_VERSION_1_3)
2139 glActiveTexture(GL_TEXTURE0 + Stage);
2140 #else
2141 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2142 #endif
2143 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
2145 glMatrixMode(GL_TEXTURE);
2146 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2147 glLoadIdentity();
2148 } else {
2149 D3DMATRIX fred;
2150 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2151 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2153 checkGLcall("Load matrix for texture");
2155 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2157 } else if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) {
2158 /* Now apply texture transforms if not applying to the dummy textures */
2159 Stage = d3dts-D3DTS_TEXTURE0;
2161 if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX))) {
2162 memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0], sizeof(D3DMATRIX));
2164 #if defined(GL_VERSION_1_3)
2165 glActiveTexture(GL_TEXTURE0 + Stage);
2166 #else
2167 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2168 #endif
2169 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
2171 glMatrixMode(GL_TEXTURE);
2172 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2173 glLoadIdentity();
2174 } else {
2175 D3DMATRIX fred;
2176 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
2177 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
2179 checkGLcall("Load matrix for texture");
2180 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
2181 } else {
2182 TRACE("Skipping texture transform as already correct\n");
2185 } else {
2186 TRACE("Skipping view setup as view already correct\n");
2190 * Vertex Blending as described
2191 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
2193 switch (This->UpdateStateBlock->vertex_blend) {
2194 case D3DVBF_DISABLE:
2196 if (viewChanged == TRUE ||
2197 (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
2198 memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
2199 if (viewChanged==FALSE) {
2200 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2201 checkGLcall("glLoadMatrixf");
2203 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
2204 checkGLcall("glMultMatrixf");
2205 } else {
2206 TRACE("Skipping as world already correct\n");
2209 break;
2210 case D3DVBF_1WEIGHTS:
2211 case D3DVBF_2WEIGHTS:
2212 case D3DVBF_3WEIGHTS:
2214 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
2216 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
2217 * so waiting for the values before matrix work
2218 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
2219 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
2220 checkGLcall("glMultMatrixf");
2224 break;
2225 case D3DVBF_TWEENING:
2227 FIXME("valid/correct D3DVBF_TWEENING\n");
2228 f = This->UpdateStateBlock->tween_factor;
2229 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
2230 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
2231 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
2232 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
2233 if (viewChanged==FALSE) {
2234 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2235 checkGLcall("glLoadMatrixf");
2237 glMultMatrixf((float *) &m.u.m[0][0]);
2238 checkGLcall("glMultMatrixf");
2240 break;
2241 case D3DVBF_0WEIGHTS:
2243 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
2244 /* single matrix of weight 1.0f */
2245 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
2246 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
2247 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
2248 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
2249 if (viewChanged == FALSE) {
2250 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2251 checkGLcall("glLoadMatrixf");
2253 glMultMatrixf((float *) &m.u.m[0][0]);
2254 checkGLcall("glMultMatrixf");
2256 break;
2257 default:
2258 break; /* stupid compilator */
2261 LEAVE_GL();
2263 return D3D_OK;
2266 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
2267 ICOM_THIS(IDirect3DDevice8Impl,iface);
2268 TRACE("(%p) : for State %d\n", This, State);
2269 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
2270 return D3D_OK;
2273 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
2274 D3DMATRIX *mat = NULL;
2275 D3DMATRIX temp;
2277 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
2278 but works regardless of recording being on.
2279 If this is found to be wrong, change to StateBlock. */
2280 ICOM_THIS(IDirect3DDevice8Impl,iface);
2281 TRACE("(%p) : For state %u\n", This, State);
2283 if (State < HIGHEST_TRANSFORMSTATE)
2285 mat = &This->UpdateStateBlock->transforms[State];
2286 } else {
2287 FIXME("Unhandled transform state!!\n");
2290 /* Copied from ddraw code: */
2291 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);
2292 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);
2293 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);
2294 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);
2296 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);
2297 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);
2298 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);
2299 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);
2301 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);
2302 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);
2303 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);
2304 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);
2306 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);
2307 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);
2308 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);
2309 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);
2311 /* Apply change via set transform - will reapply to eg. lights this way */
2312 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
2313 return D3D_OK;
2315 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
2316 ICOM_THIS(IDirect3DDevice8Impl,iface);
2318 TRACE("(%p)\n", This);
2319 This->UpdateStateBlock->Changed.viewport = TRUE;
2320 This->UpdateStateBlock->Set.viewport = TRUE;
2321 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
2323 /* Handle recording of state blocks */
2324 if (This->isRecordingState) {
2325 TRACE("Recording... not performing anything\n");
2326 return D3D_OK;
2329 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2330 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2332 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2333 checkGLcall("glDepthRange");
2334 /* Fixme? Note GL requires lower left, DirectX supplies upper left */
2335 glViewport(pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height);
2336 checkGLcall("glViewport");
2339 return D3D_OK;
2342 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
2343 ICOM_THIS(IDirect3DDevice8Impl,iface);
2344 TRACE("(%p)\n", This);
2345 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
2346 return D3D_OK;
2349 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
2350 ICOM_THIS(IDirect3DDevice8Impl,iface);
2352 This->UpdateStateBlock->Changed.material = TRUE;
2353 This->UpdateStateBlock->Set.material = TRUE;
2354 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
2356 /* Handle recording of state blocks */
2357 if (This->isRecordingState) {
2358 TRACE("Recording... not performing anything\n");
2359 return D3D_OK;
2362 ENTER_GL();
2363 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2364 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2365 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2366 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2367 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2369 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&This->UpdateStateBlock->material.Ambient);
2370 checkGLcall("glMaterialfv");
2371 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&This->UpdateStateBlock->material.Diffuse);
2372 checkGLcall("glMaterialfv");
2374 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&This->UpdateStateBlock->material.Specular);
2375 checkGLcall("glMaterialfv");
2376 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&This->UpdateStateBlock->material.Emissive);
2377 checkGLcall("glMaterialfv");
2378 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
2379 checkGLcall("glMaterialf");
2381 LEAVE_GL();
2382 return D3D_OK;
2384 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
2385 ICOM_THIS(IDirect3DDevice8Impl,iface);
2386 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
2387 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2388 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2389 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2390 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2391 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2392 return D3D_OK;
2395 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
2396 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
2397 float rho;
2398 float quad_att;
2400 ICOM_THIS(IDirect3DDevice8Impl,iface);
2401 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2403 if (Index > This->maxLights) {
2404 FIXME("Cannot handle more lights than device supports\n");
2405 return D3DERR_INVALIDCALL;
2408 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,
2409 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2410 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2411 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2412 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2413 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2414 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2416 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
2417 This->UpdateStateBlock->Set.lights[Index] = TRUE;
2418 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
2420 /* Handle recording of state blocks */
2421 if (This->isRecordingState) {
2422 TRACE("Recording... not performing anything\n");
2423 return D3D_OK;
2426 /* Diffuse: */
2427 colRGBA[0] = pLight->Diffuse.r;
2428 colRGBA[1] = pLight->Diffuse.g;
2429 colRGBA[2] = pLight->Diffuse.b;
2430 colRGBA[3] = pLight->Diffuse.a;
2431 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2432 checkGLcall("glLightfv");
2434 /* Specular */
2435 colRGBA[0] = pLight->Specular.r;
2436 colRGBA[1] = pLight->Specular.g;
2437 colRGBA[2] = pLight->Specular.b;
2438 colRGBA[3] = pLight->Specular.a;
2439 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2440 checkGLcall("glLightfv");
2442 /* Ambient */
2443 colRGBA[0] = pLight->Ambient.r;
2444 colRGBA[1] = pLight->Ambient.g;
2445 colRGBA[2] = pLight->Ambient.b;
2446 colRGBA[3] = pLight->Ambient.a;
2447 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2448 checkGLcall("glLightfv");
2450 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2451 glMatrixMode(GL_MODELVIEW);
2452 glPushMatrix();
2453 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2455 /* Attenuation - Are these right? guessing... */
2456 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
2457 checkGLcall("glLightf");
2458 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
2459 checkGLcall("glLightf");
2461 quad_att = 1.4/(pLight->Range*pLight->Range);
2462 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2463 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2464 checkGLcall("glLightf");
2466 switch (pLight->Type) {
2467 case D3DLIGHT_POINT:
2468 /* Position */
2469 This->lightPosn[Index][0] = pLight->Position.x;
2470 This->lightPosn[Index][1] = pLight->Position.y;
2471 This->lightPosn[Index][2] = pLight->Position.z;
2472 This->lightPosn[Index][3] = 1.0;
2473 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2474 checkGLcall("glLightfv");
2476 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2477 checkGLcall("glLightf");
2479 /* FIXME: Range */
2480 break;
2482 case D3DLIGHT_SPOT:
2483 /* Position */
2484 This->lightPosn[Index][0] = pLight->Position.x;
2485 This->lightPosn[Index][1] = pLight->Position.y;
2486 This->lightPosn[Index][2] = pLight->Position.z;
2487 This->lightPosn[Index][3] = 1.0;
2488 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2489 checkGLcall("glLightfv");
2491 /* Direction */
2492 This->lightDirn[Index][0] = pLight->Direction.x;
2493 This->lightDirn[Index][1] = pLight->Direction.y;
2494 This->lightDirn[Index][2] = pLight->Direction.z;
2495 This->lightDirn[Index][3] = 1.0;
2496 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2497 checkGLcall("glLightfv");
2500 * opengl-ish and d3d-ish spot lights use too different models for the
2501 * light "intensity" as a function of the angle towards the main light direction,
2502 * so we only can approximate very roughly.
2503 * however spot lights are rather rarely used in games (if ever used at all).
2504 * furthermore if still used, probably nobody pays attention to such details.
2506 if (pLight->Falloff == 0) {
2507 rho = 6.28f;
2508 } else {
2509 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2511 if (rho < 0.0001) rho = 0.0001f;
2512 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2513 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2515 /* FIXME: Range */
2516 break;
2517 case D3DLIGHT_DIRECTIONAL:
2518 /* Direction */
2519 This->lightPosn[Index][0] = -pLight->Direction.x;
2520 This->lightPosn[Index][1] = -pLight->Direction.y;
2521 This->lightPosn[Index][2] = -pLight->Direction.z;
2522 This->lightPosn[Index][3] = 0.0;
2523 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2524 checkGLcall("glLightfv");
2526 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2527 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2530 break;
2531 default:
2532 FIXME("Unrecognized light type %d\n", pLight->Type);
2535 /* Restore the modelview matrix */
2536 glPopMatrix();
2538 return D3D_OK;
2540 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2541 ICOM_THIS(IDirect3DDevice8Impl,iface);
2542 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2544 if (Index > This->maxLights) {
2545 FIXME("Cannot handle more lights than device supports\n");
2546 return D3DERR_INVALIDCALL;
2549 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2550 return D3D_OK;
2552 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2553 ICOM_THIS(IDirect3DDevice8Impl,iface);
2554 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2556 if (Index > This->maxLights) {
2557 FIXME("Cannot handle more lights than device supports\n");
2558 return D3DERR_INVALIDCALL;
2561 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2562 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2563 This->UpdateStateBlock->lightEnable[Index] = Enable;
2565 /* Handle recording of state blocks */
2566 if (This->isRecordingState) {
2567 TRACE("Recording... not performing anything\n");
2568 return D3D_OK;
2571 if (Enable) {
2572 glEnable(GL_LIGHT0+Index);
2573 checkGLcall("glEnable GL_LIGHT0+Index");
2574 } else {
2575 glDisable(GL_LIGHT0+Index);
2576 checkGLcall("glDisable GL_LIGHT0+Index");
2578 return D3D_OK;
2580 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2581 ICOM_THIS(IDirect3DDevice8Impl,iface);
2582 TRACE("(%p) : for idx(%ld)\n", This, Index);
2584 if (Index > This->maxLights) {
2585 FIXME("Cannot handle more lights than device supports\n");
2586 return D3DERR_INVALIDCALL;
2589 *pEnable = This->StateBlock->lightEnable[Index];
2590 return D3D_OK;
2592 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2593 ICOM_THIS(IDirect3DDevice8Impl,iface);
2594 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2596 /* Validate Index */
2597 if (Index >= This->clipPlanes ) {
2598 TRACE("Application has requested clipplane this device doesnt support\n");
2599 return D3DERR_INVALIDCALL;
2602 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2603 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2604 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2605 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2606 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2607 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2609 /* Handle recording of state blocks */
2610 if (This->isRecordingState) {
2611 TRACE("Recording... not performing anything\n");
2612 return D3D_OK;
2615 /* Apply it */
2617 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2618 glMatrixMode(GL_MODELVIEW);
2619 glPushMatrix();
2620 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2622 TRACE("Clipplane [%f,%f,%f,%f]\n", This->UpdateStateBlock->clipplane[Index][0], This->UpdateStateBlock->clipplane[Index][1],
2623 This->UpdateStateBlock->clipplane[Index][2], This->UpdateStateBlock->clipplane[Index][3]);
2624 glClipPlane(GL_CLIP_PLANE0+Index, This->UpdateStateBlock->clipplane[Index]);
2626 glPopMatrix();
2627 checkGLcall("glClipPlane");
2629 return D3D_OK;
2631 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2632 ICOM_THIS(IDirect3DDevice8Impl,iface);
2633 TRACE("(%p) : for idx %ld\n", This, Index);
2635 /* Validate Index */
2636 if (Index >= This->clipPlanes ) {
2637 TRACE("Application has requested clipplane this device doesnt support\n");
2638 return D3DERR_INVALIDCALL;
2641 pPlane[0] = This->StateBlock->clipplane[Index][0];
2642 pPlane[1] = This->StateBlock->clipplane[Index][0];
2643 pPlane[2] = This->StateBlock->clipplane[Index][0];
2644 pPlane[3] = This->StateBlock->clipplane[Index][0];
2645 return D3D_OK;
2647 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2648 ICOM_THIS(IDirect3DDevice8Impl,iface);
2649 DWORD OldValue = This->StateBlock->renderstate[State];
2651 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2652 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2653 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2654 This->UpdateStateBlock->renderstate[State] = Value;
2656 /* Handle recording of state blocks */
2657 if (This->isRecordingState) {
2658 TRACE("Recording... not performing anything\n");
2659 return D3D_OK;
2662 switch (State) {
2663 case D3DRS_FILLMODE :
2664 switch ((D3DFILLMODE) Value) {
2665 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2666 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2667 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2668 default:
2669 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2671 checkGLcall("glPolygonMode (fillmode)");
2672 break;
2674 case D3DRS_LIGHTING :
2675 if (Value) {
2676 glEnable(GL_LIGHTING);
2677 checkGLcall("glEnable GL_LIGHTING");
2678 } else {
2679 glDisable(GL_LIGHTING);
2680 checkGLcall("glDisable GL_LIGHTING");
2682 break;
2684 case D3DRS_ZENABLE :
2685 switch ((D3DZBUFFERTYPE) Value) {
2686 case D3DZB_FALSE:
2687 glDisable(GL_DEPTH_TEST);
2688 checkGLcall("glDisable GL_DEPTH_TEST");
2689 break;
2690 case D3DZB_TRUE:
2691 glEnable(GL_DEPTH_TEST);
2692 checkGLcall("glEnable GL_DEPTH_TEST");
2693 break;
2695 case D3DZB_USEW:
2696 default:
2697 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2699 break;
2701 case D3DRS_CULLMODE :
2703 /* If we are culling "back faces with clockwise vertices" then
2704 set front faces to be counter clockwise and enable culling
2705 of back faces */
2706 switch ((D3DCULL) Value) {
2707 case D3DCULL_NONE:
2708 glDisable(GL_CULL_FACE);
2709 checkGLcall("glDisable GL_CULL_FACE");
2710 break;
2711 case D3DCULL_CW:
2712 glEnable(GL_CULL_FACE);
2713 checkGLcall("glEnable GL_CULL_FACE");
2714 glFrontFace(GL_CCW);
2715 checkGLcall("glFrontFace GL_CCW");
2716 glCullFace(GL_BACK);
2717 break;
2718 case D3DCULL_CCW:
2719 glEnable(GL_CULL_FACE);
2720 checkGLcall("glEnable GL_CULL_FACE");
2721 glFrontFace(GL_CW);
2722 checkGLcall("glFrontFace GL_CW");
2723 glCullFace(GL_BACK);
2724 break;
2725 default:
2726 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2728 break;
2730 case D3DRS_SHADEMODE :
2731 switch ((D3DSHADEMODE) Value) {
2732 case D3DSHADE_FLAT:
2733 glShadeModel(GL_FLAT);
2734 checkGLcall("glShadeModel");
2735 break;
2736 case D3DSHADE_GOURAUD:
2737 glShadeModel(GL_SMOOTH);
2738 checkGLcall("glShadeModel");
2739 break;
2740 case D3DSHADE_PHONG:
2741 FIXME("D3DSHADE_PHONG isnt supported?\n");
2742 return D3DERR_INVALIDCALL;
2743 default:
2744 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2746 break;
2748 case D3DRS_DITHERENABLE :
2749 if (Value) {
2750 glEnable(GL_DITHER);
2751 checkGLcall("glEnable GL_DITHER");
2752 } else {
2753 glDisable(GL_DITHER);
2754 checkGLcall("glDisable GL_DITHER");
2756 break;
2758 case D3DRS_ZWRITEENABLE :
2759 if (Value) {
2760 glDepthMask(1);
2761 checkGLcall("glDepthMask");
2762 } else {
2763 glDepthMask(0);
2764 checkGLcall("glDepthMask");
2766 break;
2768 case D3DRS_ZFUNC :
2770 int glParm = GL_LESS;
2772 switch ((D3DCMPFUNC) Value) {
2773 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2774 case D3DCMP_LESS: glParm=GL_LESS; break;
2775 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2776 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2777 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2778 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2779 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2780 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2781 default:
2782 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2784 glDepthFunc(glParm);
2785 checkGLcall("glDepthFunc");
2787 break;
2789 case D3DRS_AMBIENT :
2792 float col[4];
2793 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2794 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2795 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2796 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2797 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0],col[1],col[2],col[3]);
2798 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2799 checkGLcall("glLightModel for MODEL_AMBIENT");
2802 break;
2804 case D3DRS_ALPHABLENDENABLE :
2805 if (Value) {
2806 glEnable(GL_BLEND);
2807 checkGLcall("glEnable GL_BLEND");
2808 } else {
2809 glDisable(GL_BLEND);
2810 checkGLcall("glDisable GL_BLEND");
2812 break;
2814 case D3DRS_SRCBLEND :
2815 case D3DRS_DESTBLEND :
2817 int newVal = GL_ZERO;
2818 switch (Value) {
2819 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2820 case D3DBLEND_ONE : newVal = GL_ONE; break;
2821 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2822 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2823 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2824 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2825 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2826 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2827 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2828 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2829 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2831 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2832 This->srcBlend = newVal;
2833 This->dstBlend = newVal;
2834 break;
2836 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2837 This->srcBlend = newVal;
2838 This->dstBlend = newVal;
2839 break;
2840 default:
2841 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2844 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2845 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2846 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2847 glBlendFunc(This->srcBlend, This->dstBlend);
2849 checkGLcall("glBlendFunc");
2851 break;
2853 case D3DRS_ALPHATESTENABLE :
2854 if (Value) {
2855 glEnable(GL_ALPHA_TEST);
2856 checkGLcall("glEnable GL_ALPHA_TEST");
2857 } else {
2858 glDisable(GL_ALPHA_TEST);
2859 checkGLcall("glDisable GL_ALPHA_TEST");
2861 break;
2863 case D3DRS_ALPHAFUNC :
2865 int glParm = GL_LESS;
2866 float ref = 1.0;
2868 glGetFloatv(GL_ALPHA_TEST_REF, &ref);
2869 checkGLcall("glGetFloatv(GL_ALPHA_TEST_REF, &ref);");
2871 switch ((D3DCMPFUNC) Value) {
2872 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2873 case D3DCMP_LESS: glParm=GL_LESS; break;
2874 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2875 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2876 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2877 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2878 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2879 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2880 default:
2881 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2883 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2884 glAlphaFunc(glParm, ref);
2885 checkGLcall("glAlphaFunc");
2887 break;
2889 case D3DRS_ALPHAREF :
2891 int glParm = GL_LESS;
2892 float ref = 1.0;
2894 glGetIntegerv(GL_ALPHA_TEST_FUNC, &glParm);
2895 checkGLcall("glGetFloatv(GL_ALPHA_TEST_FUNC, &glParm);");
2897 ref = ((float) Value) / 255.0;
2898 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2899 glAlphaFunc(glParm, ref);
2900 checkGLcall("glAlphaFunc");
2902 break;
2904 case D3DRS_CLIPPLANEENABLE :
2905 case D3DRS_CLIPPING :
2907 /* Ensure we only do the changed clip planes */
2908 DWORD enable = 0xFFFFFFFF;
2909 DWORD disable = 0x00000000;
2911 /* If enabling / disabling all */
2912 if (State == D3DRS_CLIPPING) {
2913 if (Value) {
2914 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2915 disable = 0x00;
2916 } else {
2917 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2918 enable = 0x00;
2920 } else {
2921 enable = Value & ~OldValue;
2922 disable = ~Value & OldValue;
2925 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2926 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2927 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2928 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2929 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2930 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2932 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2933 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2934 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2935 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2936 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2937 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2939 break;
2941 case D3DRS_BLENDOP :
2943 int glParm = GL_FUNC_ADD;
2945 switch ((D3DBLENDOP) Value) {
2946 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2947 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2948 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2949 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2950 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2951 default:
2952 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2954 TRACE("glBlendEquation(%x)\n", glParm);
2955 glBlendEquation(glParm);
2956 checkGLcall("glBlendEquation");
2958 break;
2960 case D3DRS_TEXTUREFACTOR :
2962 int i;
2964 /* Note the texture color applies to all textures whereas
2965 GL_TEXTURE_ENV_COLOR applies to active only */
2966 float col[4];
2967 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2968 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2969 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2970 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2972 /* Set the default alpha blend color */
2973 glBlendColor(col[0], col[1], col[2], col[3]);
2974 checkGLcall("glBlendColor");
2976 /* And now the default texture color as well */
2977 for (i = 0; i < This->TextureUnits; i++) {
2979 /* Note the D3DRS value applies to all textures, but GL has one
2980 per texture, so apply it now ready to be used! */
2981 if (This->isMultiTexture) {
2982 #if defined(GL_VERSION_1_3)
2983 glActiveTexture(GL_TEXTURE0 + i);
2984 #else
2985 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2986 #endif
2987 checkGLcall("Activate texture.. to update const color");
2988 } else if (i>0) {
2989 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2992 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2993 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2996 break;
2998 case D3DRS_SPECULARENABLE :
3000 if (Value) {
3001 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
3002 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);");
3003 } else {
3004 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
3005 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);");
3008 break;
3010 case D3DRS_STENCILENABLE :
3011 if (Value) {
3012 glEnable(GL_STENCIL_TEST);
3013 checkGLcall("glEnable GL_STENCIL_TEST");
3014 } else {
3015 glDisable(GL_STENCIL_TEST);
3016 checkGLcall("glDisable GL_STENCIL_TEST");
3018 break;
3020 case D3DRS_STENCILFUNC :
3022 int glParm = GL_ALWAYS;
3023 int ref = 0;
3024 GLuint mask = 0xFFFFFFFF;
3026 glGetIntegerv(GL_STENCIL_REF, &ref);
3027 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
3028 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
3029 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
3031 switch ((D3DCMPFUNC) Value) {
3032 case D3DCMP_NEVER: glParm=GL_NEVER; break;
3033 case D3DCMP_LESS: glParm=GL_LESS; break;
3034 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
3035 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
3036 case D3DCMP_GREATER: glParm=GL_GREATER; break;
3037 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
3038 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
3039 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
3040 default:
3041 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
3043 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3044 glStencilFunc(glParm, ref, mask);
3045 checkGLcall("glStencilFunc");
3047 break;
3049 case D3DRS_STENCILREF :
3051 int glParm = GL_ALWAYS;
3052 int ref = 0;
3053 GLuint mask = 0xFFFFFFFF;
3055 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
3056 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
3057 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
3058 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
3060 ref = Value;
3061 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3062 glStencilFunc(glParm, ref, mask);
3063 checkGLcall("glStencilFunc");
3065 break;
3067 case D3DRS_STENCILMASK :
3069 int glParm = GL_ALWAYS;
3070 int ref = 0.0;
3071 GLuint mask = Value;
3073 glGetIntegerv(GL_STENCIL_REF, &ref);
3074 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
3075 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
3076 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
3078 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
3079 glStencilFunc(glParm, ref, mask);
3080 checkGLcall("glStencilFunc");
3082 break;
3084 case D3DRS_STENCILFAIL :
3086 GLenum fail ;
3087 GLenum zpass ;
3088 GLenum zfail ;
3090 fail = StencilOp(Value);
3091 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3092 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3093 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3094 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3096 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3097 glStencilOp(fail, zfail, zpass);
3098 checkGLcall("glStencilOp(fail, zfail, zpass);");
3100 break;
3101 case D3DRS_STENCILZFAIL :
3103 GLenum fail ;
3104 GLenum zpass ;
3105 GLenum zfail ;
3107 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3108 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3109 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
3110 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
3111 zfail = StencilOp(Value);
3113 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3114 glStencilOp(fail, zfail, zpass);
3115 checkGLcall("glStencilOp(fail, zfail, zpass);");
3117 break;
3118 case D3DRS_STENCILPASS :
3120 GLenum fail ;
3121 GLenum zpass ;
3122 GLenum zfail ;
3124 glGetIntegerv(GL_STENCIL_FAIL, &fail);
3125 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
3126 zpass = StencilOp(Value);
3127 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
3128 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
3130 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
3131 glStencilOp(fail, zfail, zpass);
3132 checkGLcall("glStencilOp(fail, zfail, zpass);");
3134 break;
3136 case D3DRS_STENCILWRITEMASK :
3138 glStencilMask(Value);
3139 TRACE("glStencilMask(%lu)\n", Value);
3140 checkGLcall("glStencilMask");
3142 break;
3144 case D3DRS_FOGENABLE :
3146 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
3147 glEnable(GL_FOG);
3148 checkGLcall("glEnable GL_FOG\n");
3149 } else {
3150 glDisable(GL_FOG);
3151 checkGLcall("glDisable GL_FOG\n");
3154 break;
3156 case D3DRS_FOGCOLOR :
3158 float col[4];
3159 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3160 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
3161 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
3162 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
3164 /* Set the default alpha blend color */
3165 glFogfv(GL_FOG_COLOR, &col[0]);
3166 checkGLcall("glFog GL_FOG_COLOR");
3168 break;
3170 case D3DRS_FOGSTART :
3172 float *f = (float *)&Value;
3173 glFogfv(GL_FOG_START, f);
3174 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3175 TRACE("Fog Start == %f\n", *f);
3177 break;
3179 case D3DRS_FOGEND :
3181 float *f = (float *)&Value;
3182 glFogfv(GL_FOG_END, f);
3183 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3184 TRACE("Fog End == %f\n", *f);
3186 break;
3188 case D3DRS_FOGDENSITY :
3190 glFogf(GL_FOG_DENSITY, (float) Value);
3191 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3193 break;
3195 case D3DRS_VERTEXBLEND :
3197 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3198 TRACE("Vertex Blending state to %ld\n", Value);
3200 break;
3202 case D3DRS_TWEENFACTOR :
3204 This->UpdateStateBlock->tween_factor = *((float*) &Value);
3205 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
3207 break;
3209 case D3DRS_INDEXEDVERTEXBLENDENABLE :
3211 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3213 break;
3216 case D3DRS_COLORVERTEX :
3217 case D3DRS_DIFFUSEMATERIALSOURCE :
3218 case D3DRS_SPECULARMATERIALSOURCE :
3219 case D3DRS_AMBIENTMATERIALSOURCE :
3220 case D3DRS_EMISSIVEMATERIALSOURCE :
3222 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3224 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
3225 glEnable(GL_COLOR_MATERIAL);
3226 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
3228 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3229 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
3230 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
3231 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
3232 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
3234 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3235 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3236 Parm = GL_AMBIENT_AND_DIFFUSE;
3237 } else {
3238 Parm = GL_DIFFUSE;
3240 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3241 Parm = GL_AMBIENT;
3242 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3243 Parm = GL_EMISSION;
3244 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3245 Parm = GL_SPECULAR;
3246 } else {
3247 Parm = -1;
3250 if (Parm == -1) {
3251 glDisable(GL_COLOR_MATERIAL);
3252 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3253 } else {
3254 TRACE("glColorMaterial Parm=%d\n", Parm);
3255 glColorMaterial(GL_FRONT_AND_BACK, Parm);
3256 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
3259 } else {
3260 glDisable(GL_COLOR_MATERIAL);
3261 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
3264 break;
3266 /* Unhandled yet...! */
3267 case D3DRS_LINEPATTERN :
3268 case D3DRS_LASTPIXEL :
3269 case D3DRS_ZVISIBLE :
3270 case D3DRS_FOGTABLEMODE :
3271 case D3DRS_EDGEANTIALIAS :
3272 case D3DRS_ZBIAS :
3273 case D3DRS_RANGEFOGENABLE :
3274 case D3DRS_WRAP0 :
3275 case D3DRS_WRAP1 :
3276 case D3DRS_WRAP2 :
3277 case D3DRS_WRAP3 :
3278 case D3DRS_WRAP4 :
3279 case D3DRS_WRAP5 :
3280 case D3DRS_WRAP6 :
3281 case D3DRS_WRAP7 :
3282 case D3DRS_FOGVERTEXMODE :
3283 case D3DRS_LOCALVIEWER :
3284 case D3DRS_NORMALIZENORMALS :
3285 case D3DRS_SOFTWAREVERTEXPROCESSING :
3286 case D3DRS_POINTSIZE :
3287 case D3DRS_POINTSIZE_MIN :
3288 case D3DRS_POINTSPRITEENABLE :
3289 case D3DRS_POINTSCALEENABLE :
3290 case D3DRS_POINTSCALE_A :
3291 case D3DRS_POINTSCALE_B :
3292 case D3DRS_POINTSCALE_C :
3293 case D3DRS_MULTISAMPLEANTIALIAS :
3294 case D3DRS_MULTISAMPLEMASK :
3295 case D3DRS_PATCHEDGESTYLE :
3296 case D3DRS_PATCHSEGMENTS :
3297 case D3DRS_DEBUGMONITORTOKEN :
3298 case D3DRS_POINTSIZE_MAX :
3299 case D3DRS_COLORWRITEENABLE :
3300 case D3DRS_POSITIONORDER :
3301 case D3DRS_NORMALORDER :
3302 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3303 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3304 break;
3305 default:
3306 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3309 return D3D_OK;
3311 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3312 ICOM_THIS(IDirect3DDevice8Impl,iface);
3313 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3314 *pValue = This->StateBlock->renderstate[State];
3315 return D3D_OK;
3317 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3318 ICOM_THIS(IDirect3DDevice8Impl,iface);
3320 TRACE("(%p)\n", This);
3322 return IDirect3DDeviceImpl_BeginStateBlock(This);
3324 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3325 IDirect3DStateBlockImpl* pSB;
3326 ICOM_THIS(IDirect3DDevice8Impl,iface);
3327 HRESULT res;
3329 TRACE("(%p)\n", This);
3331 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3332 *pToken = (DWORD) pSB;
3333 return res;
3336 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3337 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3338 ICOM_THIS(IDirect3DDevice8Impl,iface);
3340 TRACE("(%p)\n", This);
3342 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3345 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3346 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3347 ICOM_THIS(IDirect3DDevice8Impl,iface);
3349 TRACE("(%p)\n", This);
3351 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3353 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3354 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3355 ICOM_THIS(IDirect3DDevice8Impl,iface);
3357 TRACE("(%p)\n", This);
3359 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3362 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3363 IDirect3DStateBlockImpl* pSB;
3364 ICOM_THIS(IDirect3DDevice8Impl,iface);
3365 HRESULT res;
3367 TRACE("(%p) : for type %d\n", This, Type);
3369 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3370 *pToken = (DWORD) pSB;
3371 return res;
3374 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3375 ICOM_THIS(IDirect3DDevice8Impl,iface);
3376 FIXME("(%p) : stub\n", This); return D3D_OK;
3378 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3379 ICOM_THIS(IDirect3DDevice8Impl,iface);
3380 FIXME("(%p) : stub\n", This); return D3D_OK;
3382 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3383 ICOM_THIS(IDirect3DDevice8Impl,iface);
3384 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3385 *ppTexture = (LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage];
3386 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3387 return D3D_OK;
3389 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8* pTexture) {
3391 IDirect3DBaseTexture8 *oldTxt;
3392 BOOL reapplyStates = TRUE;
3394 ICOM_THIS(IDirect3DDevice8Impl,iface);
3395 D3DRESOURCETYPE textureType;
3397 oldTxt = This->UpdateStateBlock->textures[Stage];
3398 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3400 /* Reject invalid texture units */
3401 if (Stage >= This->TextureUnits) {
3402 TRACE("Attempt to access invalid texture rejected\n");
3403 return D3DERR_INVALIDCALL;
3406 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3407 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3408 This->UpdateStateBlock->textures[Stage] = pTexture;
3410 /* Handle recording of state blocks */
3411 if (This->isRecordingState) {
3412 TRACE("Recording... not performing anything\n");
3413 return D3D_OK;
3416 /* Make appropriate texture active */
3417 if (This->isMultiTexture) {
3418 #if defined(GL_VERSION_1_3)
3419 glActiveTexture(GL_TEXTURE0 + Stage);
3420 #else
3421 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3422 #endif
3423 checkGLcall("glActiveTextureARB");
3424 } else if (Stage>0) {
3425 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3428 /* Decrement the count of the previous texture */
3429 if (oldTxt != NULL) {
3430 IDirect3DBaseTexture8Impl_Release(oldTxt);
3433 if (pTexture) {
3434 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage]);
3436 /* Now setup the texture appropraitly */
3437 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3439 if (textureType == D3DRTYPE_TEXTURE) {
3440 IDirect3DTexture8Impl *pTexture2 = (IDirect3DTexture8Impl *) pTexture;
3442 if ((void *)oldTxt == (void *)pTexture2 && pTexture2->Dirty == FALSE) {
3443 TRACE("Skipping setting texture as old == new\n");
3444 reapplyStates = FALSE;
3445 } else {
3447 /* Standard 2D texture */
3448 TRACE("Standard 2d texture\n");
3449 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3451 /* Load up the texture now */
3452 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8)pTexture);
3454 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3455 IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture;
3456 int i;
3458 /* Standard 3D (volume) texture */
3459 TRACE("Standard 3d texture\n");
3460 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3462 for (i=0; i<pTexture2->levels; i++)
3465 if (i==0 && pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3466 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3467 checkGLcall("glBindTexture");
3468 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3470 /* No need to walk through all mip-map levels, since already all assigned */
3471 i = pTexture2->levels;
3472 } else {
3473 if (i==0) {
3475 if (pTexture2->volumes[i]->textureName == 0) {
3476 glGenTextures(1, &pTexture2->volumes[i]->textureName);
3477 checkGLcall("glGenTextures");
3478 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3481 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3482 checkGLcall("glBindTexture");
3484 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1);
3485 checkGLcall("glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1)");
3488 TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3489 GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width,
3490 pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth,
3491 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3492 pTexture2->volumes[i]->allocatedMemory);
3493 glTexImage3D(GL_TEXTURE_3D, i,
3494 fmt2glintFmt(pTexture2->format),
3495 pTexture2->volumes[i]->myDesc.Width,
3496 pTexture2->volumes[i]->myDesc.Height,
3497 pTexture2->volumes[i]->myDesc.Depth,
3499 fmt2glFmt(pTexture2->format),
3500 fmt2glType(pTexture2->format),
3501 pTexture2->volumes[i]->allocatedMemory
3503 checkGLcall("glTexImage3D");
3505 /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3506 pTexture2->Dirty = FALSE;
3510 } else {
3511 FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType);
3513 } else {
3514 TRACE("Setting to no texture (ie default texture)\n");
3515 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3516 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3517 checkGLcall("glBindTexture");
3518 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3521 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3522 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3523 if (reapplyStates) {
3524 setupTextureStates (iface, Stage);
3527 return D3D_OK;
3530 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3531 ICOM_THIS(IDirect3DDevice8Impl,iface);
3532 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3533 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3534 return D3D_OK;
3537 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) {
3538 ICOM_THIS(IDirect3DDevice8Impl,iface);
3540 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3542 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value);
3544 /* Reject invalid texture units */
3545 if (Stage >= This->TextureUnits) {
3546 TRACE("Attempt to access invalid texture rejected\n");
3547 return D3DERR_INVALIDCALL;
3550 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3551 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3552 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3554 /* Handle recording of state blocks */
3555 if (This->isRecordingState) {
3556 TRACE("Recording... not performing anything\n");
3557 return D3D_OK;
3560 /* Make appropriate texture active */
3561 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3562 if (This->isMultiTexture) {
3563 #if defined(GL_VERSION_1_3)
3564 glActiveTexture(GL_TEXTURE0 + Stage);
3565 vcheckGLcall("glActiveTexture");
3566 #else
3567 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3568 vcheckGLcall("glActiveTextureARB");
3569 #endif
3570 } else if (Stage > 0) {
3571 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3574 switch (Type) {
3576 case D3DTSS_MINFILTER :
3577 case D3DTSS_MIPFILTER :
3579 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3580 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3581 GLint realVal = GL_LINEAR;
3583 if (ValueMIN == D3DTEXF_POINT) {
3584 /* GL_NEAREST_* */
3585 if (ValueMIP == D3DTEXF_POINT) {
3586 realVal = GL_NEAREST_MIPMAP_NEAREST;
3587 } else if (ValueMIP == D3DTEXF_LINEAR) {
3588 realVal = GL_NEAREST_MIPMAP_LINEAR;
3589 } else if (ValueMIP == D3DTEXF_NONE) {
3590 realVal = GL_NEAREST;
3591 } else {
3592 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3593 realVal = GL_NEAREST_MIPMAP_LINEAR;
3595 } else if (ValueMIN == D3DTEXF_LINEAR) {
3596 /* GL_LINEAR_* */
3597 if (ValueMIP == D3DTEXF_POINT) {
3598 realVal = GL_LINEAR_MIPMAP_NEAREST;
3599 } else if (ValueMIP == D3DTEXF_LINEAR) {
3600 realVal = GL_LINEAR_MIPMAP_LINEAR;
3601 } else if (ValueMIP == D3DTEXF_NONE) {
3602 realVal = GL_LINEAR;
3603 } else {
3604 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3605 realVal = GL_LINEAR_MIPMAP_LINEAR;
3607 } else if (ValueMIN == D3DTEXF_NONE) {
3608 /* Doesnt really make sense - Windows just seems to disable
3609 mipmapping when this occurs */
3610 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3611 realVal = GL_LINEAR;
3613 } else {
3614 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3615 realVal = GL_LINEAR_MIPMAP_LINEAR;
3618 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3619 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3620 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3622 break;
3625 case D3DTSS_MAGFILTER :
3626 if (Value == D3DTEXF_POINT) {
3627 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3628 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3629 } else if (Value == D3DTEXF_LINEAR) {
3630 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3631 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3632 } else {
3633 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3635 break;
3637 case D3DTSS_COLORARG0 :
3638 case D3DTSS_ALPHAARG0 :
3639 /* FIXME: Mesa seems to struggle setting these at the moment */
3640 /*FIXME("COLORARG0/ALPHAARG0 support still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);*/
3641 /*break;*/
3643 case D3DTSS_COLORARG1 :
3644 case D3DTSS_COLORARG2 :
3645 case D3DTSS_ALPHAARG1 :
3646 case D3DTSS_ALPHAARG2 :
3648 BOOL isAlphaArg = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3649 int operand = GL_SRC_COLOR;
3650 int source = GL_TEXTURE;
3652 GetSrcAndOpFromValue(Value, isAlphaArg, &source, &operand);
3653 if (isAlphaArg) {
3654 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
3655 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
3656 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
3657 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
3658 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
3659 } else {
3660 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
3661 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
3662 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
3663 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
3664 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
3667 break;
3669 case D3DTSS_ALPHAOP :
3670 case D3DTSS_COLOROP :
3673 int Scale = 1;
3674 int Parm = (Type == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
3676 if (Type == D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
3677 /* TODO: Disable by making this and all later levels disabled */
3678 glDisable(GL_TEXTURE_1D);
3679 checkGLcall("Disable GL_TEXTURE_1D");
3680 glDisable(GL_TEXTURE_2D);
3681 checkGLcall("Disable GL_TEXTURE_2D");
3682 glDisable(GL_TEXTURE_3D);
3683 checkGLcall("Disable GL_TEXTURE_3D");
3684 } else {
3686 /* Enable only the appropriate texture dimension */
3687 if (Type == D3DTSS_COLOROP) {
3688 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3689 glEnable(GL_TEXTURE_1D);
3690 checkGLcall("Enable GL_TEXTURE_1D");
3691 } else {
3692 glDisable(GL_TEXTURE_1D);
3693 checkGLcall("Disable GL_TEXTURE_1D");
3695 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3696 glEnable(GL_TEXTURE_2D);
3697 checkGLcall("Enable GL_TEXTURE_2D");
3698 } else {
3699 glDisable(GL_TEXTURE_2D);
3700 checkGLcall("Disable GL_TEXTURE_2D");
3702 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3703 glEnable(GL_TEXTURE_3D);
3704 checkGLcall("Enable GL_TEXTURE_3D");
3705 } else {
3706 glDisable(GL_TEXTURE_3D);
3707 checkGLcall("Disable GL_TEXTURE_3D");
3711 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
3712 if (Value != D3DTOP_DISABLE) {
3713 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3716 /* Now set up the operand correctly */
3717 switch (Value) {
3718 case D3DTOP_DISABLE :
3719 /* Contrary to the docs, alpha can be disabled when colorop is enabled
3720 and it works, so ignore this op */
3721 TRACE("Disable ALPHAOP but COLOROP enabled!\n");
3722 break;
3724 case D3DTOP_SELECTARG1 :
3726 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3727 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3728 #if 0 /* don't seem to do anything */
3729 BOOL isAlphaOp = (Type == D3DTSS_ALPHAOP);
3730 DWORD dwValue = 0;
3731 GLenum source;
3732 GLenum operand;
3733 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3734 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3735 if (isAlphaOp) {
3736 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3737 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3738 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3739 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3740 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3741 } else {
3742 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3743 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3744 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3745 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3746 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3748 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3749 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3750 if (isAlphaOp) {
3751 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3752 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3753 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3754 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3755 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3756 } else {
3757 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3758 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3759 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3760 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3761 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3763 #endif
3765 break;
3767 case D3DTOP_SELECTARG2 :
3769 BOOL isAlphaOp = (Type == D3DTSS_ALPHAOP);
3770 DWORD dwValue = 0;
3771 GLenum source;
3772 GLenum operand;
3773 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3774 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3775 /* GL_REPLACE, swap args 0 and 1? */
3776 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
3777 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3778 if (isAlphaOp) {
3779 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
3780 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
3781 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
3782 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
3783 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
3784 } else {
3785 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
3786 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
3787 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
3788 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
3789 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
3791 dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
3792 GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
3793 if (isAlphaOp) {
3794 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
3795 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
3796 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
3797 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
3798 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
3799 } else {
3800 TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
3801 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
3802 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
3803 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
3804 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
3807 break;
3809 case D3DTOP_MODULATE4X : Scale = Scale * 2; /* Drop through */
3810 case D3DTOP_MODULATE2X : Scale = Scale * 2; /* Drop through */
3811 case D3DTOP_MODULATE :
3813 /* Correct scale */
3814 if (Type == D3DTSS_ALPHAOP) {
3815 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
3816 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
3817 } else {
3818 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
3819 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
3821 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
3822 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
3823 break;
3825 case D3DTOP_ADD :
3826 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
3827 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
3828 break;
3830 case D3DTOP_ADDSIGNED2X : Scale = Scale * 2; /* Drop through */
3831 case D3DTOP_ADDSIGNED :
3832 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
3833 vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
3834 break;
3836 case D3DTOP_DOTPRODUCT3 :
3837 #if defined(GL_VERSION_1_3)
3838 if (This->isDot3) {
3839 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
3840 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
3841 break;
3843 #endif
3844 FIXME("DotProduct3 extension requested but not supported via this version of opengl\n");
3845 break;
3847 case D3DTOP_SUBTRACT :
3848 #if defined(GL_VERSION_1_3)
3849 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT);
3850 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT)");
3851 break;
3852 #else
3854 * @TODO: to check:
3855 * if ARB_texture_env_combine is supported
3856 * we can use GL_SUBTRACT_ARB here
3858 #endif
3859 case D3DTOP_ADDSMOOTH :
3860 case D3DTOP_BLENDDIFFUSEALPHA :
3861 case D3DTOP_BLENDTEXTUREALPHA :
3862 case D3DTOP_BLENDFACTORALPHA :
3863 case D3DTOP_BLENDTEXTUREALPHAPM :
3864 case D3DTOP_BLENDCURRENTALPHA :
3865 case D3DTOP_PREMODULATE :
3866 case D3DTOP_MODULATEALPHA_ADDCOLOR :
3867 case D3DTOP_MODULATECOLOR_ADDALPHA :
3868 case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
3869 case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
3870 case D3DTOP_BUMPENVMAP :
3871 case D3DTOP_BUMPENVMAPLUMINANCE :
3872 case D3DTOP_MULTIPLYADD :
3873 case D3DTOP_LERP :
3874 default:
3875 FIXME("Unhandled texture operation %ld\n", Value);
3878 break;
3881 case D3DTSS_ADDRESSU :
3882 case D3DTSS_ADDRESSV :
3883 case D3DTSS_ADDRESSW :
3885 GLint wrapParm = GL_REPEAT;
3886 switch (Value) {
3887 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3888 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3889 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3890 #if defined(GL_VERSION_1_4)
3891 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3892 #elif defined(GL_ARB_texture_mirrored_repeat)
3893 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3894 #else
3895 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3896 #endif
3897 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3898 default:
3899 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3900 wrapParm = GL_REPEAT;
3903 switch (Type) {
3904 case D3DTSS_ADDRESSU:
3905 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3906 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3907 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3908 break;
3909 case D3DTSS_ADDRESSV:
3910 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3911 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3912 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3913 break;
3914 case D3DTSS_ADDRESSW:
3915 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3916 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3917 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3918 break;
3919 default: /* nop */
3920 break; /** stupic compilator */
3923 break;
3925 case D3DTSS_BORDERCOLOR :
3927 float col[4];
3928 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3929 col[1] = ((Value >> 8) & 0xFF) / 255.0;
3930 col[2] = ((Value >> 0) & 0xFF) / 255.0;
3931 col[3] = ((Value >> 24) & 0xFF) / 255.0;
3933 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3934 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3935 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3937 break;
3939 case D3DTSS_TEXCOORDINDEX :
3941 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3943 /**
3944 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3946 switch (Value & 0xFFFFFF00) {
3947 case D3DTSS_TCI_PASSTHRU:
3948 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3949 break;
3951 case D3DTSS_TCI_CAMERASPACEPOSITION:
3952 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3953 as the input texture coordinates for this stage's texture transformation. This
3954 equates roughly to EYE_LINEAR */
3956 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3957 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3958 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3959 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3960 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3962 glMatrixMode(GL_MODELVIEW);
3963 glPushMatrix();
3964 glLoadIdentity();
3965 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3966 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3967 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3968 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3969 glPopMatrix();
3971 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3972 glEnable(GL_TEXTURE_GEN_S);
3973 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3974 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3975 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3976 glEnable(GL_TEXTURE_GEN_T);
3977 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3978 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3979 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3980 glEnable(GL_TEXTURE_GEN_R);
3981 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3982 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3983 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3985 break;
3987 default:
3988 /* Todo: */
3989 /* ? disable GL_TEXTURE_GEN_n ? */
3990 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3991 break;
3994 break;
3996 /* Unhandled */
3997 case D3DTSS_BUMPENVMAT00 :
3998 case D3DTSS_BUMPENVMAT01 :
3999 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
4000 break;
4001 case D3DTSS_BUMPENVMAT10 :
4002 case D3DTSS_BUMPENVMAT11 :
4003 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
4004 break;
4006 case D3DTSS_MIPMAPLODBIAS :
4007 case D3DTSS_MAXMIPLEVEL :
4008 case D3DTSS_MAXANISOTROPY :
4009 case D3DTSS_BUMPENVLSCALE :
4010 case D3DTSS_BUMPENVLOFFSET :
4011 case D3DTSS_TEXTURETRANSFORMFLAGS :
4012 case D3DTSS_RESULTARG :
4013 default:
4014 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4015 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4017 return D3D_OK;
4019 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
4020 ICOM_THIS(IDirect3DDevice8Impl,iface);
4021 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
4022 return D3D_OK;
4024 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize) {
4025 ICOM_THIS(IDirect3DDevice8Impl,iface);
4026 FIXME("(%p) : stub\n", This); return D3D_OK;
4028 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,CONST PALETTEENTRY* pEntries) {
4029 ICOM_THIS(IDirect3DDevice8Impl,iface);
4030 FIXME("(%p) : stub\n", This); return D3D_OK;
4032 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,PALETTEENTRY* pEntries) {
4033 ICOM_THIS(IDirect3DDevice8Impl,iface);
4034 FIXME("(%p) : stub\n", This); return D3D_OK;
4036 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
4037 ICOM_THIS(IDirect3DDevice8Impl,iface);
4038 FIXME("(%p) : stub\n", This); return D3D_OK;
4040 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
4041 ICOM_THIS(IDirect3DDevice8Impl,iface);
4042 FIXME("(%p) : stub\n", This); return D3D_OK;
4044 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) {
4046 IDirect3DVertexBuffer8 *pVB;
4048 ICOM_THIS(IDirect3DDevice8Impl,iface);
4049 pVB = This->StateBlock->stream_source[0];
4051 TRACE("(%p) : Type=%d, Start=%d, Count=%d\n", This, PrimitiveType, StartVertex, PrimitiveCount);
4053 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
4054 This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
4056 return D3D_OK;
4058 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
4059 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
4060 UINT idxStride = 2;
4061 IDirect3DIndexBuffer8 *pIB;
4062 IDirect3DVertexBuffer8 *pVB;
4063 D3DINDEXBUFFER_DESC IdxBufDsc;
4065 ICOM_THIS(IDirect3DDevice8Impl,iface);
4066 pIB = This->StateBlock->pIndexData;
4067 pVB = This->StateBlock->stream_source[0];
4069 TRACE("(%p) : Type=%d, min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, PrimitiveType,
4070 minIndex, NumVertices, startIndex, primCount);
4072 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
4073 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
4074 idxStride = 2;
4075 } else {
4076 idxStride = 4;
4079 DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
4080 This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
4081 minIndex);
4083 return D3D_OK;
4085 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
4086 ICOM_THIS(IDirect3DDevice8Impl,iface);
4088 TRACE("(%p) : Type=%d, pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4090 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4092 This->StateBlock->stream_source[0] = NULL;
4093 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4094 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4095 0, 0, 0, NULL, 0);
4096 This->StateBlock->stream_stride[0] = 0;
4098 /*stream zero settings set to null at end */
4099 return D3D_OK;
4101 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4102 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4103 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4104 UINT VertexStreamZeroStride) {
4105 int idxStride;
4106 ICOM_THIS(IDirect3DDevice8Impl,iface);
4107 TRACE("(%p) : Type=%d, MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType,
4108 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4110 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4111 if (IndexDataFormat == D3DFMT_INDEX16) {
4112 idxStride = 2;
4113 } else {
4114 idxStride = 4;
4117 This->StateBlock->stream_source[0] = NULL;
4118 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4119 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
4120 This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4122 /*stream zero settings set to null at end */
4123 This->StateBlock->stream_stride[0] = 0;
4124 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4126 return D3D_OK;
4128 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4129 ICOM_THIS(IDirect3DDevice8Impl,iface);
4130 FIXME("(%p) : stub\n", This); return D3D_OK;
4132 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4133 ICOM_THIS(IDirect3DDevice8Impl,iface);
4134 IDirect3DVertexShaderImpl* object;
4135 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4136 HRESULT res;
4137 UINT i;
4139 TRACE("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
4140 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4141 return D3DERR_INVALIDCALL;
4143 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4144 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4145 return D3DERR_OUTOFVIDEOMEMORY;
4148 /** Create the Vertex Shader */
4149 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4150 /** TODO: check FAILED(res) */
4152 /** Create and Bind the Vertex Shader Declaration */
4153 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4154 /** TODO: check FAILED(res) */
4156 VertexShaders[i] = object;
4157 VertexShaderDeclarations[i] = attached_decl;
4158 *pHandle = VS_HIGHESTFIXEDFXF + i;
4160 return D3D_OK;
4162 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4163 ICOM_THIS(IDirect3DDevice8Impl,iface);
4165 This->UpdateStateBlock->VertexShader = Handle;
4166 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4167 This->UpdateStateBlock->Set.vertexShader = TRUE;
4169 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4170 FIXME("(%p) : Created shader, Handle=%lx\n", This, Handle);
4171 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4172 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4173 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4174 } else { /* use a fvf, so desactivate the vshader decl */
4175 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4176 This->UpdateStateBlock->vertexShaderDecl = NULL;
4177 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4178 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4180 /* Handle recording of state blocks */
4181 if (This->isRecordingState) {
4182 TRACE("Recording... not performing anything\n");
4183 return D3D_OK;
4186 * TODO: merge HAL shaders context switching from prototype
4188 return D3D_OK;
4190 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4191 ICOM_THIS(IDirect3DDevice8Impl,iface);
4192 TRACE("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4193 *pHandle = This->StateBlock->VertexShader;
4194 return D3D_OK;
4197 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4198 ICOM_THIS(IDirect3DDevice8Impl,iface);
4199 IDirect3DVertexShaderImpl* object;
4200 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4202 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4203 return D3DERR_INVALIDCALL;
4207 * Delete Vertex Shader
4209 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4210 if (NULL == object) {
4211 return D3DERR_INVALIDCALL;
4213 FIXME("(%p) : freing VertexShader %p\n", This, object);
4214 /* TODO: check validity of object */
4215 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4216 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4217 HeapFree(GetProcessHeap(), 0, (void *)object);
4218 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4221 * Delete Vertex Shader Declaration
4223 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4224 if (NULL == attached_decl) {
4225 return D3DERR_INVALIDCALL;
4227 FIXME("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4228 /* TODO: check validity of object */
4229 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4230 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4231 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4233 return D3D_OK;
4236 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4237 ICOM_THIS(IDirect3DDevice8Impl,iface);
4239 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4240 ERR("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4241 return D3DERR_INVALIDCALL;
4243 if (NULL == pConstantData) {
4244 return D3DERR_INVALIDCALL;
4246 if (ConstantCount > 1) {
4247 FLOAT* f = (FLOAT*)pConstantData;
4248 UINT i;
4249 TRACE("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4250 for (i = 0; i < ConstantCount; ++i) {
4251 TRACE("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4252 f += 4;
4254 } else {
4255 FLOAT* f = (FLOAT*)pConstantData;
4256 TRACE("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4258 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4259 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4260 return D3D_OK;
4262 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4263 ICOM_THIS(IDirect3DDevice8Impl,iface);
4265 TRACE("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4266 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4267 return D3DERR_INVALIDCALL;
4269 if (NULL == pConstantData) {
4270 return D3DERR_INVALIDCALL;
4272 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4273 return D3D_OK;
4275 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4276 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4277 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4279 attached_decl = VERTEX_SHADER_DECL(Handle);
4280 if (NULL == attached_decl) {
4281 return D3DERR_INVALIDCALL;
4283 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4285 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4286 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4287 IDirect3DVertexShaderImpl* object;
4289 object = VERTEX_SHADER(Handle);
4290 if (NULL == object) {
4291 return D3DERR_INVALIDCALL;
4293 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4296 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4297 ICOM_THIS(IDirect3DDevice8Impl,iface);
4298 IDirect3DIndexBuffer8 *oldIdxs;
4300 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4301 oldIdxs = This->StateBlock->pIndexData;
4303 This->UpdateStateBlock->Changed.Indices = TRUE;
4304 This->UpdateStateBlock->Set.Indices = TRUE;
4305 This->UpdateStateBlock->pIndexData = pIndexData;
4306 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4308 /* Handle recording of state blocks */
4309 if (This->isRecordingState) {
4310 TRACE("Recording... not performing anything\n");
4311 return D3D_OK;
4314 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4315 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4316 return D3D_OK;
4318 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4319 ICOM_THIS(IDirect3DDevice8Impl,iface);
4320 FIXME("(%p) : stub\n", This);
4322 *ppIndexData = This->StateBlock->pIndexData;
4323 /* up ref count on ppindexdata */
4324 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4325 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4327 return D3D_OK;
4329 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4330 ICOM_THIS(IDirect3DDevice8Impl,iface);
4331 IDirect3DPixelShaderImpl* object;
4332 UINT i;
4334 FIXME("(%p) : PixelShader not fully supported yet\n", This);
4335 if (NULL == pFunction || NULL == pHandle) {
4336 return D3DERR_INVALIDCALL;
4338 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4339 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4340 return D3DERR_OUTOFVIDEOMEMORY;
4342 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DPixelShaderImpl));
4343 if (NULL == object) {
4344 return D3DERR_OUTOFVIDEOMEMORY;
4347 object->data = NULL; /* TODO */
4349 PixelShaders[i] = object;
4350 *pHandle = VS_HIGHESTFIXEDFXF + i;
4352 object->function = pFunction;
4353 for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
4354 object->functionLength = i + 1;
4356 return D3D_OK;
4358 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4359 ICOM_THIS(IDirect3DDevice8Impl,iface);
4361 This->UpdateStateBlock->PixelShader = Handle;
4362 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4363 This->UpdateStateBlock->Set.pixelShader = TRUE;
4365 /* Handle recording of state blocks */
4366 if (This->isRecordingState) {
4367 TRACE("Recording... not performing anything\n");
4368 return D3D_OK;
4371 /* FIXME: Quieten when not being used */
4372 if (Handle != 0) {
4373 FIXME("(%p) : stub %ld\n", This, Handle);
4374 } else {
4375 TRACE("(%p) : stub %ld\n", This, Handle);
4378 return D3D_OK;
4380 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4381 ICOM_THIS(IDirect3DDevice8Impl,iface);
4382 TRACE("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4383 *pHandle = This->StateBlock->PixelShader;
4384 return D3D_OK;
4387 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4388 ICOM_THIS(IDirect3DDevice8Impl,iface);
4389 IDirect3DPixelShaderImpl* object;
4391 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4392 return D3DERR_INVALIDCALL;
4394 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4395 TRACE("(%p) : freeing PixelShader %p\n", This, object);
4396 /* TODO: check validity of object before free */
4397 HeapFree(GetProcessHeap(), 0, (void *)object);
4398 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
4399 return D3D_OK;
4402 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,CONST void* pConstantData, DWORD ConstantCount) {
4403 ICOM_THIS(IDirect3DDevice8Impl,iface);
4404 FIXME("(%p) : stub\n", This);
4405 return D3D_OK;
4407 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,void* pConstantData, DWORD ConstantCount) {
4408 ICOM_THIS(IDirect3DDevice8Impl,iface);
4409 FIXME("(%p) : stub\n", This);
4410 return D3D_OK;
4412 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4413 ICOM_THIS(IDirect3DDevice8Impl,iface);
4414 IDirect3DPixelShaderImpl* object;
4416 object = PIXEL_SHADER(Handle);
4417 if (NULL == object) {
4418 return D3DERR_INVALIDCALL;
4420 if (NULL == pData) {
4421 *pSizeOfData = object->functionLength;
4422 return D3D_OK;
4424 if (*pSizeOfData < object->functionLength) {
4425 *pSizeOfData = object->functionLength;
4426 return D3DERR_MOREDATA;
4428 TRACE("(%p) : GetPixelShaderFunction copying to %p\n", This, pData);
4429 memcpy(pData, object->function, object->functionLength);
4430 return D3D_OK;
4432 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4433 ICOM_THIS(IDirect3DDevice8Impl,iface);
4434 FIXME("(%p) : stub\n", This); return D3D_OK;
4436 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4437 ICOM_THIS(IDirect3DDevice8Impl,iface);
4438 FIXME("(%p) : stub\n", This); return D3D_OK;
4440 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4441 ICOM_THIS(IDirect3DDevice8Impl,iface);
4442 FIXME("(%p) : stub\n", This); return D3D_OK;
4445 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4446 IDirect3DVertexBuffer8 *oldSrc;
4447 ICOM_THIS(IDirect3DDevice8Impl,iface);
4449 oldSrc = This->StateBlock->stream_source[StreamNumber];
4450 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4452 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4453 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4454 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4455 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4457 /* Handle recording of state blocks */
4458 if (This->isRecordingState) {
4459 TRACE("Recording... not performing anything\n");
4460 return D3D_OK;
4463 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4464 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4465 return D3D_OK;
4467 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4468 ICOM_THIS(IDirect3DDevice8Impl,iface);
4469 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4470 *pStream = This->StateBlock->stream_source[StreamNumber];
4471 *pStride = This->StateBlock->stream_stride[StreamNumber];
4472 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4473 return D3D_OK;
4477 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4479 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4480 IDirect3DDevice8Impl_QueryInterface,
4481 IDirect3DDevice8Impl_AddRef,
4482 IDirect3DDevice8Impl_Release,
4483 IDirect3DDevice8Impl_TestCooperativeLevel,
4484 IDirect3DDevice8Impl_GetAvailableTextureMem,
4485 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4486 IDirect3DDevice8Impl_GetDirect3D,
4487 IDirect3DDevice8Impl_GetDeviceCaps,
4488 IDirect3DDevice8Impl_GetDisplayMode,
4489 IDirect3DDevice8Impl_GetCreationParameters,
4490 IDirect3DDevice8Impl_SetCursorProperties,
4491 IDirect3DDevice8Impl_SetCursorPosition,
4492 IDirect3DDevice8Impl_ShowCursor,
4493 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4494 IDirect3DDevice8Impl_Reset,
4495 IDirect3DDevice8Impl_Present,
4496 IDirect3DDevice8Impl_GetBackBuffer,
4497 IDirect3DDevice8Impl_GetRasterStatus,
4498 IDirect3DDevice8Impl_SetGammaRamp,
4499 IDirect3DDevice8Impl_GetGammaRamp,
4500 IDirect3DDevice8Impl_CreateTexture,
4501 IDirect3DDevice8Impl_CreateVolumeTexture,
4502 IDirect3DDevice8Impl_CreateCubeTexture,
4503 IDirect3DDevice8Impl_CreateVertexBuffer,
4504 IDirect3DDevice8Impl_CreateIndexBuffer,
4505 IDirect3DDevice8Impl_CreateRenderTarget,
4506 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4507 IDirect3DDevice8Impl_CreateImageSurface,
4508 IDirect3DDevice8Impl_CopyRects,
4509 IDirect3DDevice8Impl_UpdateTexture,
4510 IDirect3DDevice8Impl_GetFrontBuffer,
4511 IDirect3DDevice8Impl_SetRenderTarget,
4512 IDirect3DDevice8Impl_GetRenderTarget,
4513 IDirect3DDevice8Impl_GetDepthStencilSurface,
4514 IDirect3DDevice8Impl_BeginScene,
4515 IDirect3DDevice8Impl_EndScene,
4516 IDirect3DDevice8Impl_Clear,
4517 IDirect3DDevice8Impl_SetTransform,
4518 IDirect3DDevice8Impl_GetTransform,
4519 IDirect3DDevice8Impl_MultiplyTransform,
4520 IDirect3DDevice8Impl_SetViewport,
4521 IDirect3DDevice8Impl_GetViewport,
4522 IDirect3DDevice8Impl_SetMaterial,
4523 IDirect3DDevice8Impl_GetMaterial,
4524 IDirect3DDevice8Impl_SetLight,
4525 IDirect3DDevice8Impl_GetLight,
4526 IDirect3DDevice8Impl_LightEnable,
4527 IDirect3DDevice8Impl_GetLightEnable,
4528 IDirect3DDevice8Impl_SetClipPlane,
4529 IDirect3DDevice8Impl_GetClipPlane,
4530 IDirect3DDevice8Impl_SetRenderState,
4531 IDirect3DDevice8Impl_GetRenderState,
4532 IDirect3DDevice8Impl_BeginStateBlock,
4533 IDirect3DDevice8Impl_EndStateBlock,
4534 IDirect3DDevice8Impl_ApplyStateBlock,
4535 IDirect3DDevice8Impl_CaptureStateBlock,
4536 IDirect3DDevice8Impl_DeleteStateBlock,
4537 IDirect3DDevice8Impl_CreateStateBlock,
4538 IDirect3DDevice8Impl_SetClipStatus,
4539 IDirect3DDevice8Impl_GetClipStatus,
4540 IDirect3DDevice8Impl_GetTexture,
4541 IDirect3DDevice8Impl_SetTexture,
4542 IDirect3DDevice8Impl_GetTextureStageState,
4543 IDirect3DDevice8Impl_SetTextureStageState,
4544 IDirect3DDevice8Impl_ValidateDevice,
4545 IDirect3DDevice8Impl_GetInfo,
4546 IDirect3DDevice8Impl_SetPaletteEntries,
4547 IDirect3DDevice8Impl_GetPaletteEntries,
4548 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4549 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4550 IDirect3DDevice8Impl_DrawPrimitive,
4551 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4552 IDirect3DDevice8Impl_DrawPrimitiveUP,
4553 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4554 IDirect3DDevice8Impl_ProcessVertices,
4555 IDirect3DDevice8Impl_CreateVertexShader,
4556 IDirect3DDevice8Impl_SetVertexShader,
4557 IDirect3DDevice8Impl_GetVertexShader,
4558 IDirect3DDevice8Impl_DeleteVertexShader,
4559 IDirect3DDevice8Impl_SetVertexShaderConstant,
4560 IDirect3DDevice8Impl_GetVertexShaderConstant,
4561 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4562 IDirect3DDevice8Impl_GetVertexShaderFunction,
4563 IDirect3DDevice8Impl_SetStreamSource,
4564 IDirect3DDevice8Impl_GetStreamSource,
4565 IDirect3DDevice8Impl_SetIndices,
4566 IDirect3DDevice8Impl_GetIndices,
4567 IDirect3DDevice8Impl_CreatePixelShader,
4568 IDirect3DDevice8Impl_SetPixelShader,
4569 IDirect3DDevice8Impl_GetPixelShader,
4570 IDirect3DDevice8Impl_DeletePixelShader,
4571 IDirect3DDevice8Impl_SetPixelShaderConstant,
4572 IDirect3DDevice8Impl_GetPixelShaderConstant,
4573 IDirect3DDevice8Impl_GetPixelShaderFunction,
4574 IDirect3DDevice8Impl_DrawRectPatch,
4575 IDirect3DDevice8Impl_DrawTriPatch,
4576 IDirect3DDevice8Impl_DeletePatch