Add DotProduct3 support if supported by opengl.
[wine/dcerpc.git] / dlls / d3d8 / device.c
blob51530cd6602fd55365935cb8cfd2717b0c599948
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <math.h>
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "wine/debug.h"
33 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
34 /*#define GL_GLEXT_PROTOTYPES*/
35 #include "d3d8_private.h"
37 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
38 #undef GL_VERSION_1_4
40 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
42 /* Some #defines for additional diagnostics */
44 /* Per-vertex trace: */
45 #if 0
46 # define VTRACE(A) TRACE A
47 #else
48 # define VTRACE(A)
49 #endif
52 static IDirect3DVertexShaderImpl* VertexShaders[64];
53 static IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
54 static IDirect3DPixelShaderImpl* PixelShaders[64];
56 /* CreateVertexShader can return > 0xFFFF */
57 #define VS_HIGHESTFIXEDFXF 0xF0000000
60 * Utility functions or macros
62 #define conv_mat(mat,gl_mat) \
63 do { \
64 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
65 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
66 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
68 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
69 } while (0)
71 #define VERTEX_SHADER(Handle) \
72 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) ? NULL : VertexShaders[Handle]) : VertexShaders[Handle - VS_HIGHESTFIXEDFXF])
73 #define VERTEX_SHADER_DECL(Handle) \
74 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(VertexShaderDeclarations) / sizeof(IDirect3DVertexShaderDeclarationImpl*)) ? NULL : VertexShaderDeclarations[Handle]) : VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF])
75 #define PIXEL_SHADER(Handle) \
76 ((Handle <= VS_HIGHESTFIXEDFXF) ? ((Handle >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) ? NULL : PixelShaders[Handle]) : PixelShaders[Handle - VS_HIGHESTFIXEDFXF])
78 #define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
82 /* Routine common to the draw primitive and draw indexed primitive routines */
83 void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
84 int PrimitiveType,
85 long NumPrimitives,
86 BOOL isIndexed,
88 /* For Both:*/
89 D3DFORMAT fvf,
90 const void *vertexBufData,
92 /* for Indexed: */
93 long StartVertexIndex,
94 long StartIdx,
95 short idxBytes,
96 const void *idxData,
97 int minIndex) {
99 int NumVertexes = NumPrimitives;
100 IDirect3DVertexShaderImpl* vertex_shader = NULL;
101 BOOL useVertexShaderFunction = FALSE;
103 ICOM_THIS(IDirect3DDevice8Impl,iface);
105 /* Dont understand how to handle multiple streams, but if a fixed
106 FVF is passed in rather than a handle, it must use stream 0 */
108 if (This->UpdateStateBlock->VertexShader > VS_HIGHESTFIXEDFXF) {
109 vertex_shader = VERTEX_SHADER(This->UpdateStateBlock->VertexShader);
110 if (NULL == vertex_shader) {
111 ERR("trying to use unitialised vertex shader: %lu\n", This->UpdateStateBlock->VertexShader);
112 return ;
114 if (NULL == vertex_shader->function) {
115 TRACE("vertex shader declared without program, using FVF pure mode\n");
116 } else {
117 useVertexShaderFunction = TRUE;
119 fvf = (D3DFORMAT) This->UpdateStateBlock->vertexShaderDecl->fvf;
120 TRACE("vertex shader declared FVF: %lx\n", This->UpdateStateBlock->vertexShaderDecl->fvf);
121 memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8));
123 /** init Constants */
124 if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
125 TRACE("vertex shader init Constant\n");
126 IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
132 int skip = This->StateBlock->stream_stride[0];
133 GLenum primType = GL_POINTS;
134 BOOL normal;
135 BOOL isRHW;
136 BOOL isPtSize;
137 BOOL isDiffuse;
138 BOOL isSpecular;
139 int numBlends;
140 BOOL isLastUByte4;
141 int numTextures;
142 int textureNo;
143 const char *curVtx = NULL;
144 const short *pIdxBufS = NULL;
145 const long *pIdxBufL = NULL;
146 const char *curPos;
147 BOOL isLightingOn = FALSE;
148 BOOL enableTexture = FALSE;
149 int vx_index;
151 float x = 0.0f,
152 y = 0.0f,
153 z = 0.0f; /* x,y,z coordinates */
154 float nx = 0.0f,
155 ny =0.0,
156 nz = 0.0f; /* normal x,y,z coordinates */
157 float rhw = 0.0f; /* rhw */
158 float ptSize = 0.0f; /* Point size */
159 DWORD diffuseColor = 0xFFFFFFFF; /* Diffuse Color */
160 DWORD specularColor = 0; /* Specular Color */
162 ENTER_GL();
164 if (isIndexed) {
165 if (idxBytes == 2) pIdxBufS = (short *) idxData;
166 else pIdxBufL = (long *) idxData;
169 /* Check vertex formats expected ? */
170 /**
171 * FVF parser as seen it
172 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/Reference/CPP/D3D/FlexibleVertexFormatFlags.asp
174 normal = fvf & D3DFVF_NORMAL;
175 isRHW = fvf & D3DFVF_XYZRHW;
176 isLastUByte4 = fvf & D3DFVF_LASTBETA_UBYTE4;
177 numBlends = ((fvf & D3DFVF_POSITION_MASK) >> 1) - 2 + ((FALSE == isLastUByte4) ? 0 : -1); /* WARNING can be < 0 because -2 */
178 isPtSize = fvf & D3DFVF_PSIZE;
179 isDiffuse = fvf & D3DFVF_DIFFUSE;
180 isSpecular = fvf & D3DFVF_SPECULAR;
181 numTextures = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
183 TRACE("Drawing with FVF = %x, (n?%d, rhw?%d, ptSize(%d), diffuse?%d, specular?%d, numTextures=%d, numBlends=%d)\n",
184 fvf, normal, isRHW, isPtSize, isDiffuse, isSpecular, numTextures, numBlends);
186 /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is
187 set by the appropriate render state */
188 if (!normal) {
189 isLightingOn = glIsEnabled(GL_LIGHTING);
190 glDisable(GL_LIGHTING);
191 TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
194 if (isRHW) {
195 double height, width, minZ, maxZ;
197 * Already transformed vertex do not need transform
198 * matrices. Reset all matrices to identity.
199 * Leave the default matrix in world mode.
201 glMatrixMode(GL_PROJECTION);
202 checkGLcall("glMatrixMode");
203 glLoadIdentity();
204 checkGLcall("glLoadIdentity");
205 glMatrixMode(GL_MODELVIEW);
206 checkGLcall("glMatrixMode");
207 glLoadIdentity();
208 checkGLcall("glLoadIdentity");
209 height = This->StateBlock->viewport.Height;
210 width = This->StateBlock->viewport.Width;
211 minZ = This->StateBlock->viewport.MinZ;
212 maxZ = This->StateBlock->viewport.MaxZ;
213 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
214 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
215 checkGLcall("glOrtho");
216 } else {
217 glMatrixMode(GL_PROJECTION);
218 checkGLcall("glMatrixMode");
219 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
220 checkGLcall("glLoadMatrixf");
221 glMatrixMode(GL_MODELVIEW);
222 checkGLcall("glMatrixMode");
223 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
224 checkGLcall("glLoadMatrixf");
225 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
226 checkGLcall("glMultMatrixf");
229 /* Set OpenGL to the appropriate Primitive Type */
230 switch (PrimitiveType) {
231 case D3DPT_POINTLIST:
232 TRACE("POINTS\n");
233 primType = GL_POINTS;
234 NumVertexes = NumPrimitives;
235 break;
237 case D3DPT_LINELIST:
238 TRACE("LINES\n");
239 primType = GL_LINES;
240 NumVertexes = NumPrimitives * 2;
241 break;
243 case D3DPT_LINESTRIP:
244 TRACE("LINE_STRIP\n");
245 primType = GL_LINE_STRIP;
246 NumVertexes = NumPrimitives + 1;
247 break;
249 case D3DPT_TRIANGLELIST:
250 TRACE("TRIANGLES\n");
251 primType = GL_TRIANGLES;
252 NumVertexes = NumPrimitives * 3;
253 break;
255 case D3DPT_TRIANGLESTRIP:
256 TRACE("TRIANGLE_STRIP\n");
257 primType = GL_TRIANGLE_STRIP;
258 NumVertexes = NumPrimitives + 2;
259 break;
261 case D3DPT_TRIANGLEFAN:
262 TRACE("TRIANGLE_FAN\n");
263 primType = GL_TRIANGLE_FAN;
264 NumVertexes = NumPrimitives + 2;
265 break;
267 default:
268 FIXME("Unhandled primitive\n");
269 break;
272 /* Fixme, Ideally, only use this per-vertex code for software HAL
273 but until opengl supports all the functions returned to setup
274 vertex arrays, we need to drop down to the slow mechanism for
275 certain functions */
277 if (isPtSize || isDiffuse || useVertexShaderFunction==TRUE || (numBlends > 0)) {
278 TRACE("Using slow per-vertex code\n");
280 /* Enable this one to be able to debug what is going on, but it is slower
281 than the pointer/array version */
282 VTRACE(("glBegin(%x)\n", primType));
283 glBegin(primType);
285 /* Draw the primitives */
286 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
288 for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
290 if (!isIndexed) {
291 curPos = curVtx;
292 } else {
293 if (idxBytes == 2) {
294 VTRACE(("Idx for vertex %d = %d = %d\n", vx_index, pIdxBufS[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
295 curPos = curVtx + ((pIdxBufS[StartIdx+vx_index]) * skip);
296 } else {
297 VTRACE(("Idx for vertex %d = %ld = %d\n", vx_index, pIdxBufL[StartIdx+vx_index], (pIdxBufS[StartIdx+vx_index])));
298 curPos = curVtx + ((pIdxBufL[StartIdx+vx_index]) * skip);
302 /* Work through the vertex buffer */
303 x = *(float *)curPos;
304 curPos = curPos + sizeof(float);
305 y = *(float *)curPos;
306 curPos = curPos + sizeof(float);
307 z = *(float *)curPos;
308 curPos = curPos + sizeof(float);
309 VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
311 /* RHW follows, only if transformed */
312 if (isRHW) {
313 rhw = *(float *)curPos;
314 curPos = curPos + sizeof(float);
315 VTRACE(("rhw=%f\n", rhw));
318 /* Blending data */
319 if (numBlends > 0) {
320 UINT i;
321 D3DSHADERVECTOR skippedBlend = { 0.0f, 0.0f, 0.0f, 0.0f};
322 DWORD skippedBlendLastUByte4 = 0;
324 for (i = 0; i < ((FALSE == isLastUByte4) ? numBlends : numBlends - 1); ++i) {
325 ((float*)&skippedBlend)[i] = *(float *)curPos;
326 curPos = curPos + sizeof(float);
329 if (isLastUByte4) {
330 skippedBlendLastUByte4 = *(DWORD*)curPos;
331 curPos = curPos + sizeof(DWORD);
335 /* Vertex Normal Data (untransformed only) */
336 if (normal) {
337 nx = *(float *)curPos;
338 curPos = curPos + sizeof(float);
339 ny = *(float *)curPos;
340 curPos = curPos + sizeof(float);
341 nz = *(float *)curPos;
342 curPos = curPos + sizeof(float);
343 VTRACE(("nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
346 if (isPtSize) {
347 ptSize = *(float *)curPos;
348 VTRACE(("ptSize=%f\n", ptSize));
349 curPos = curPos + sizeof(float);
352 if (isDiffuse) {
353 diffuseColor = *(DWORD *)curPos;
354 VTRACE(("diffuseColor=%lx\n", diffuseColor));
355 curPos = curPos + sizeof(DWORD);
358 if (isSpecular) {
359 specularColor = *(DWORD *)curPos;
360 VTRACE(("specularColor=%lx\n", specularColor));
361 curPos = curPos + sizeof(DWORD);
364 /* ToDo: Texture coords */
365 for (textureNo = 0; textureNo < numTextures; ++textureNo) {
366 float s, t, r, q;
368 if (!(This->isMultiTexture) && textureNo > 0) {
369 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
370 continue ;
372 if (textureNo > This->TextureUnits) {
373 FIXME("Program using more concurrent textures than this opengl implementation support\n");
374 break ;
377 /* Query tex coords */
378 if (This->StateBlock->textures[textureNo] != NULL) {
379 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
380 case D3DRTYPE_TEXTURE:
381 s = *(float *)curPos;
382 curPos = curPos + sizeof(float);
383 t = *(float *)curPos;
384 curPos = curPos + sizeof(float);
385 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s,t));
387 if (TRUE == useVertexShaderFunction) {
388 /* Nothing to do */
389 } else {
390 if (This->isMultiTexture) {
391 #if defined(GL_VERSION_1_3)
392 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
393 #else
394 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
395 #endif
396 } else {
397 glTexCoord2f(s, t);
400 break;
402 case D3DRTYPE_VOLUMETEXTURE:
403 s = *(float *)curPos;
404 curPos = curPos + sizeof(float);
405 t = *(float *)curPos;
406 curPos = curPos + sizeof(float);
407 r = *(float *)curPos;
408 curPos = curPos + sizeof(float);
409 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r));
411 if (TRUE == useVertexShaderFunction) {
412 /* Nothing to do */
413 } else {
414 if (This->isMultiTexture) {
415 #if defined(GL_VERSION_1_3)
416 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
417 #else
418 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
419 #endif
421 } else {
422 glTexCoord3f(s, t, r);
425 break;
427 default:
428 r = 0.0f; q = 0.0f; /* Avoid compiler warnings, need these vars later for other textures */
429 FIXME("Unhandled texture type\n");
431 } else {
432 /* Note I have seen a program actually do this, so just hide it and continue */
433 VTRACE(("Very odd - texture requested in FVF but not bound!\n"));
438 /** if vertex shader program specified ... using it */
439 if (TRUE == useVertexShaderFunction) {
442 * this code must become the really
443 * vs input params init
445 * because its possible to use input registers for anything
446 * and some samples use registers for other things than they are
447 * declared
450 /**
451 * no really valid declaration, user defined input register use
452 * so fill input registers as described in vertex shader declaration
454 IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, vertexBufData, StartVertexIndex,
455 (!isIndexed) ? (vx_index * skip) :
456 (idxBytes == 2) ? ((pIdxBufS[StartIdx + vx_index]) * skip) :
457 ((pIdxBufL[StartIdx + vx_index]) * skip));
459 memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8));
460 IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
462 TRACE_VECTOR(vertex_shader->output.oPos);
463 TRACE_VECTOR(vertex_shader->output.oD[0]);
464 TRACE_VECTOR(vertex_shader->output.oD[1]);
465 TRACE_VECTOR(vertex_shader->output.oT[0]);
466 TRACE_VECTOR(vertex_shader->output.oT[1]);
467 TRACE_VECTOR(vertex_shader->input.V[0]);
468 TRACE_VECTOR(vertex_shader->data->C[0]);
469 TRACE_VECTOR(vertex_shader->data->C[1]);
470 TRACE_VECTOR(vertex_shader->data->C[2]);
471 TRACE_VECTOR(vertex_shader->data->C[3]);
472 TRACE_VECTOR(vertex_shader->data->C[4]);
473 TRACE_VECTOR(vertex_shader->data->C[5]);
474 TRACE_VECTOR(vertex_shader->data->C[6]);
475 TRACE_VECTOR(vertex_shader->data->C[7]);
477 x = vertex_shader->output.oPos.x;
478 y = vertex_shader->output.oPos.y;
479 z = vertex_shader->output.oPos.z;
481 if (1.0f != vertex_shader->output.oPos.w || isRHW) {
482 rhw = vertex_shader->output.oPos.w;
484 /*diffuseColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[0]);*/
485 glColor4fv((float*) &vertex_shader->output.oD[0]);
487 /* Requires secondary color extensions to compile... */
488 #if defined(GL_VERSION_1_4)
489 glSecondaryColor3fv((float*) &vertex_shader->output.oD[1]);
490 checkGLcall("glSecondaryColor3fv");
491 #else
492 if (checkGLSupport(EXT_SECONDARY_COLOR)) {
493 /*specularColor = D3DCOLOR_COLORVALUE(vertex_shader->output.oD[1]);*/
494 /*GLExtCall(glSecondaryColor3fvEXT)((float*) &vertex_shader->output.oD[1]);*/
495 /*checkGLcall("glSecondaryColor3fvEXT");*/
497 #endif
498 /** reupdate textures coords binding using vertex_shader->output.oT[0->3] */
499 for (textureNo = 0; textureNo < 4; ++textureNo) {
500 float s, t, r, q;
502 if (!(This->isMultiTexture) && textureNo > 0) {
503 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
504 continue ;
506 /* Query tex coords */
507 if (This->StateBlock->textures[textureNo] != NULL) {
508 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
509 case D3DRTYPE_TEXTURE:
510 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
511 s = vertex_shader->output.oT[textureNo].x;
512 t = vertex_shader->output.oT[textureNo].y;
513 VTRACE(("tex:%d, s,t=%f,%f\n", textureNo, s, t));
514 if (This->isMultiTexture) {
515 #if defined(GL_VERSION_1_3)
516 glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
517 #else
518 glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
519 #endif
520 /*checkGLcall("glMultiTexCoord2fARB");*/
521 } else {
522 glTexCoord2f(s, t);
523 /*checkGLcall("gTexCoord2f");*/
525 break;
527 case D3DRTYPE_VOLUMETEXTURE:
528 /*TRACE_VECTOR(vertex_shader->output.oT[textureNo]);*/
529 s = vertex_shader->output.oT[textureNo].x;
530 t = vertex_shader->output.oT[textureNo].y;
531 r = vertex_shader->output.oT[textureNo].z;
532 VTRACE(("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s, t, r));
533 if (This->isMultiTexture) {
534 #if defined(GL_VERSION_1_3)
535 glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
536 #else
537 glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
538 #endif
539 /*checkGLcall("glMultiTexCoord2fARB");*/
540 } else {
541 glTexCoord3f(s, t, r);
542 /*checkGLcall("gTexCoord3f");*/
544 break;
546 default:
547 /* Avoid compiler warnings, need these vars later for other textures */
548 r = 0.0f; q = 0.0f;
549 FIXME("Unhandled texture type\n");
554 if (1.0f == rhw || rhw < 0.01f) {
555 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
556 glVertex3f(x, y, z);
557 /*checkGLcall("glVertex3f");*/
558 } else {
559 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
560 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
561 /*checkGLcall("glVertex4f");*/
563 } else {
564 /**
565 * FALSE == useVertexShaderFunction
566 * using std FVF code
569 /* Handle these vertexes */
570 if (isDiffuse) {
571 glColor4ub((diffuseColor >> 16) & 0xFF,
572 (diffuseColor >> 8) & 0xFF,
573 (diffuseColor >> 0) & 0xFF,
574 (diffuseColor >> 24) & 0xFF);
575 VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n",
576 ((diffuseColor >> 16) & 0xFF) / 255.0f,
577 ((diffuseColor >> 8) & 0xFF) / 255.0f,
578 ((diffuseColor >> 0) & 0xFF) / 255.0f,
579 ((diffuseColor >> 24) & 0xFF) / 255.0f));
582 if (normal) {
583 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / glNormal:nx,ny,nz=%f,%f,%f\n", x,y,z,nx,ny,nz));
584 glNormal3f(nx, ny, nz);
585 glVertex3f(x, y, z);
586 } else {
587 if (1.0f == rhw || rhw < 0.01f) {
588 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
589 glVertex3f(x, y, z);
590 } else {
591 VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
592 glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
597 if (!isIndexed) {
598 curVtx = curVtx + skip;
602 glEnd();
603 checkGLcall("glEnd and previous calls");
605 } else {
606 TRACE("Using fast vertex array code\n");
608 /* Faster version, harder to debug */
609 /* Shuffle to the beginning of the vertexes to render and index from there */
610 curVtx = (const char *)vertexBufData + (StartVertexIndex * skip);
611 curPos = curVtx;
613 /* Set up the vertex pointers */
614 if (isRHW) {
615 glVertexPointer(4, GL_FLOAT, skip, curPos);
616 checkGLcall("glVertexPointer(4, ...)");
617 curPos += 4 * sizeof(float);
618 } else {
619 glVertexPointer(3, GL_FLOAT, skip, curPos);
620 checkGLcall("glVertexPointer(3, ...)");
621 curPos += 3 * sizeof(float);
623 glEnableClientState(GL_VERTEX_ARRAY);
624 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
626 if (numBlends > 0) {
627 /* no such functionality in the fixed function GL pipeline */
628 /* FIXME: Wont get here as will drop to slow method */
629 /* FIXME("Cannot handle blending data here in openGl\n");*/
630 if (checkGLSupport(ARB_VERTEX_BLEND)) {
631 FIXME("TODO\n");
632 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
633 FIXME("TODO\n");
635 GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos);
636 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
637 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
638 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
640 curPos += numBlends * sizeof(float);
641 } else {
642 FIXME("unsupported blending in openGl\n");
644 } else {
645 if (checkGLSupport(ARB_VERTEX_BLEND)) {
646 FIXME("TODO\n");
647 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
648 FIXME("TODO\n");
650 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
651 checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
657 if (normal) {
658 glNormalPointer(GL_FLOAT, skip, curPos);
659 checkGLcall("glNormalPointer");
660 glEnableClientState(GL_NORMAL_ARRAY);
661 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
662 curPos += 3 * sizeof(float);
663 } else {
664 glDisableClientState(GL_NORMAL_ARRAY);
665 checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
666 glNormal3f(0, 0, 1);
667 checkGLcall("glNormal3f(0, 0, 1)");
670 if (isPtSize) {
671 /* no such functionality in the fixed function GL pipeline */
672 /* FIXME: Wont get here as will drop to slow method */
673 FIXME("Cannot change ptSize here in openGl\n");
674 curPos = curPos + sizeof(float);
677 if (isDiffuse) {
678 glColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
679 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
680 glEnableClientState(GL_COLOR_ARRAY);
681 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
682 curPos += sizeof(DWORD);
684 else {
685 glDisableClientState(GL_COLOR_ARRAY);
686 checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
687 glColor4f(1, 1, 1, 1);
688 checkGLcall("glColor4f(1, 1, 1, 1)");
691 /* Requires secondary color extensions to compile... */
692 if (isSpecular) {
693 #if defined(GL_VERSION_1_4)
694 glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos);
695 checkGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, skip, curPos)");
696 glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
697 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
698 #else
699 # if 0
700 /* FIXME: check for GL_EXT_secondary_color */
701 glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos);
702 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, skip, curPos)");
703 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
704 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
705 # endif
706 #endif
707 curPos += sizeof(DWORD);
708 } else {
709 #if defined(GL_VERSION_1_4)
710 glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
711 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
712 glSecondaryColor3f(0, 0, 0);
713 checkGLcall("glSecondaryColor3f(0, 0, 0)");
714 #else
715 #if 0
716 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
717 checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
718 glSecondaryColor3fEXT(0, 0, 0);
719 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
720 #endif
721 #endif
725 /* ToDo: Texture coords */
726 for (textureNo = 0;textureNo<numTextures; textureNo++) {
728 /* Query tex coords */
729 #if defined(GL_VERSION_1_3)
730 glClientActiveTexture(GL_TEXTURE0 + textureNo);
731 #else
732 glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
733 #endif
734 if (This->StateBlock->textures[textureNo] != NULL) {
735 enableTexture = TRUE;
736 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock->textures[textureNo])) {
737 case D3DRTYPE_TEXTURE:
738 glTexCoordPointer(2, GL_FLOAT, skip, curPos);
739 checkGLcall("glTexCoordPointer(2, ...)");
740 curPos += 2*sizeof(float);
741 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
742 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
743 break;
745 case D3DRTYPE_VOLUMETEXTURE:
746 glTexCoordPointer(3, GL_FLOAT, skip, curPos);
747 checkGLcall("glTexCoordPointer(3, ...)");
748 curPos += 3*sizeof(float);
749 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
750 checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
751 break;
753 default:
754 FIXME("Unhandled texture type\n");
755 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
756 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
759 } else {
761 /* Note I have seen a program actually do this, so just hide it and continue */
762 TRACE("Very odd - texture requested in FVF but not bound!\n");
763 #if defined(GL_VERSION_1_3)
764 glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1);
765 checkGLcall("glMultiTexCoord4f(... , 0, 0, 0, 1)");
766 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
767 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
768 #else
769 glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1);
770 checkGLcall("glMultiTexCoord4fARB(... , 0, 0, 0, 1)");
771 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
772 checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
773 #endif
778 /* Finally do the drawing */
779 if (isIndexed) {
781 TRACE("glElements(%x, %d, %d, ...)\n", primType, NumVertexes, minIndex);
782 if (idxBytes==2) {
783 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
784 glDrawElements(primType, NumVertexes, GL_UNSIGNED_SHORT,
785 (char *)idxData+(2 * StartIdx));
786 #else
787 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
788 GL_UNSIGNED_SHORT, (char *)idxData+(2 * StartIdx));
789 #endif
790 } else {
791 #if 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
792 glDrawElements(primType, NumVertexes, GL_UNSIGNED_INT,
793 (char *)idxData+(4 * StartIdx));
794 #else
795 glDrawRangeElements(primType, minIndex, minIndex+NumVertexes-1, NumVertexes,
796 GL_UNSIGNED_INT, (char *)idxData+(2 * StartIdx));
797 #endif
799 checkGLcall("glDrawRangeElements");
801 } else {
803 /* Note first is now zero as we shuffled along earlier */
804 TRACE("glDrawArrays(%x, %ld, %d)\n", primType, StartIdx, NumVertexes);
805 glDrawArrays(primType, 0, NumVertexes);
806 checkGLcall("glDrawArrays");
811 /* If no normals, restore previous lighting state */
812 if (!normal) {
813 if (isLightingOn) glEnable(GL_LIGHTING);
814 else glDisable(GL_LIGHTING);
815 TRACE("Restored lighting to original state\n");
819 LEAVE_GL();
821 TRACE("glEnd\n");
825 Simple utility routines used for dx -> gl mapping of byte formats
827 SHORT bytesPerPixel(D3DFORMAT fmt) {
828 SHORT retVal;
830 switch (fmt) {
831 /* color buffer */
832 case D3DFMT_A4R4G4B4: retVal = 2; break;
833 case D3DFMT_A8R8G8B8: retVal = 4; break;
834 case D3DFMT_X8R8G8B8: retVal = 4; break;
835 case D3DFMT_R8G8B8: retVal = 3; break;
836 case D3DFMT_R5G6B5: retVal = 2; break;
837 case D3DFMT_A1R5G5B5: retVal = 2; break;
838 /* depth/stencil buffer */
839 case D3DFMT_D16_LOCKABLE: retVal = 2; break;
840 case D3DFMT_D32: retVal = 4; break;
841 case D3DFMT_D15S1: retVal = 2; break;
842 case D3DFMT_D24S8: retVal = 4; break;
843 case D3DFMT_D16: retVal = 2; break;
844 case D3DFMT_D24X8: retVal = 4; break;
845 case D3DFMT_D24X4S4: retVal = 4; break;
846 /* unknown */
847 case D3DFMT_UNKNOWN:
848 /* Guess at the highest value of the above */
849 TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %d\n", fmt);
850 retVal = 4;
851 break;
852 default:
853 FIXME("Unhandled fmt %d\n", fmt);
854 retVal = 4;
856 TRACE("bytes/Pxl for fmt %d = %d\n", fmt, retVal);
857 return retVal;
860 GLint fmt2glintFmt(D3DFORMAT fmt) {
861 GLint retVal;
863 switch (fmt) {
864 case D3DFMT_A4R4G4B4: retVal = GL_RGBA4; break;
865 case D3DFMT_A8R8G8B8: retVal = GL_RGBA8; break;
866 case D3DFMT_X8R8G8B8: retVal = GL_RGB8; break;
867 case D3DFMT_R8G8B8: retVal = GL_RGB8; break;
868 case D3DFMT_R5G6B5: retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
869 case D3DFMT_A1R5G5B5: retVal = GL_RGB5_A1; break;
870 default:
871 FIXME("Unhandled fmt %d\n", fmt);
872 retVal = 4;
874 TRACE("fmt2glintFmt for fmt %d = %x\n", fmt, retVal);
875 return retVal;
877 GLenum fmt2glFmt(D3DFORMAT fmt) {
878 GLenum retVal;
880 switch (fmt) {
881 case D3DFMT_A4R4G4B4: retVal = GL_BGRA; break;
882 case D3DFMT_A8R8G8B8: retVal = GL_BGRA; break;
883 case D3DFMT_X8R8G8B8: retVal = GL_BGRA; break;
884 case D3DFMT_R8G8B8: retVal = GL_BGR; break;
885 case D3DFMT_R5G6B5: retVal = GL_BGR; break;
886 case D3DFMT_A1R5G5B5: retVal = GL_BGRA; break;
887 default:
888 FIXME("Unhandled fmt %d\n", fmt);
889 retVal = 4;
891 TRACE("fmt2glFmt for fmt %d = %x\n", fmt, retVal);
892 return retVal;
894 DWORD fmt2glType(D3DFORMAT fmt) {
895 GLenum retVal;
897 switch (fmt) {
898 case D3DFMT_A4R4G4B4: retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
899 case D3DFMT_A8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
900 case D3DFMT_X8R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
901 case D3DFMT_R5G6B5: retVal = GL_UNSIGNED_SHORT_5_6_5_REV; break;
902 case D3DFMT_R8G8B8: retVal = GL_UNSIGNED_BYTE; break;
903 case D3DFMT_A1R5G5B5: retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
904 default:
905 FIXME("Unhandled fmt %d\n", fmt);
906 retVal = 4;
908 TRACE("fmt2glType for fmt %d = %x\n", fmt, retVal);
909 return retVal;
912 int SOURCEx_RGB_EXT(DWORD arg) {
913 switch(arg) {
914 case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
915 case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
916 case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
917 case D3DTSS_ALPHAARG0:
918 case D3DTSS_ALPHAARG1:
919 case D3DTSS_ALPHAARG2:
920 default:
921 FIXME("Invalid arg %ld\n", arg);
922 return GL_SOURCE0_RGB_EXT;
925 int OPERANDx_RGB_EXT(DWORD arg) {
926 switch(arg) {
927 case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
928 case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
929 case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
930 case D3DTSS_ALPHAARG0:
931 case D3DTSS_ALPHAARG1:
932 case D3DTSS_ALPHAARG2:
933 default:
934 FIXME("Invalid arg %ld\n", arg);
935 return GL_OPERAND0_RGB_EXT;
938 int SOURCEx_ALPHA_EXT(DWORD arg) {
939 switch(arg) {
940 case D3DTSS_ALPHAARG0: return GL_SOURCE2_ALPHA_EXT;
941 case D3DTSS_ALPHAARG1: return GL_SOURCE0_ALPHA_EXT;
942 case D3DTSS_ALPHAARG2: return GL_SOURCE1_ALPHA_EXT;
943 case D3DTSS_COLORARG0:
944 case D3DTSS_COLORARG1:
945 case D3DTSS_COLORARG2:
946 default:
947 FIXME("Invalid arg %ld\n", arg);
948 return GL_SOURCE0_ALPHA_EXT;
951 int OPERANDx_ALPHA_EXT(DWORD arg) {
952 switch(arg) {
953 case D3DTSS_ALPHAARG0: return GL_OPERAND2_ALPHA_EXT;
954 case D3DTSS_ALPHAARG1: return GL_OPERAND0_ALPHA_EXT;
955 case D3DTSS_ALPHAARG2: return GL_OPERAND1_ALPHA_EXT;
956 case D3DTSS_COLORARG0:
957 case D3DTSS_COLORARG1:
958 case D3DTSS_COLORARG2:
959 default:
960 FIXME("Invalid arg %ld\n", arg);
961 return GL_OPERAND0_ALPHA_EXT;
964 GLenum StencilOp(DWORD op) {
965 switch(op) {
966 case D3DSTENCILOP_KEEP : return GL_KEEP;
967 case D3DSTENCILOP_ZERO : return GL_ZERO;
968 case D3DSTENCILOP_REPLACE : return GL_REPLACE;
969 case D3DSTENCILOP_INCRSAT : return GL_INCR;
970 case D3DSTENCILOP_DECRSAT : return GL_DECR;
971 case D3DSTENCILOP_INVERT : return GL_INVERT;
972 case D3DSTENCILOP_INCR : FIXME("Unsupported stencil op %ld\n", op);
973 return GL_INCR; /* Fixme - needs to support wrap */
974 case D3DSTENCILOP_DECR : FIXME("Unsupported stencil op %ld\n", op);
975 return GL_DECR; /* Fixme - needs to support wrap */
976 default:
977 FIXME("Invalid stencil op %ld\n", op);
978 return GL_ALWAYS;
982 /* Apply the current values to the specified texture stage */
983 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
984 ICOM_THIS(IDirect3DDevice8Impl,iface);
985 int i=0;
986 float col[4];
988 /* Make appropriate texture active */
989 if (This->isMultiTexture) {
990 #if defined(GL_VERSION_1_3)
991 glActiveTexture(GL_TEXTURE0 + Stage);
992 #else
993 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
994 #endif
995 checkGLcall("glActiveTextureARB");
996 } else if (Stage > 0) {
997 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
1000 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
1001 for (i=1; i<HIGHEST_TEXTURE_STATE; i++) {
1002 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
1005 /* Note the D3DRS value applies to all textures, but GL has one
1006 per texture, so apply it now ready to be used! */
1007 col[0] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR]>> 16) & 0xFF) / 255.0;
1008 col[1] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 8 ) & 0xFF) / 255.0;
1009 col[2] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 0 ) & 0xFF) / 255.0;
1010 col[3] = ((This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR] >> 24 ) & 0xFF) / 255.0;
1011 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1012 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1014 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
1017 /* IDirect3D IUnknown parts follow: */
1018 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
1020 ICOM_THIS(IDirect3DDevice8Impl,iface);
1022 if (IsEqualGUID(riid, &IID_IUnknown)
1023 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
1024 IDirect3DDevice8Impl_AddRef(iface);
1025 *ppobj = This;
1026 return D3D_OK;
1029 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
1030 return E_NOINTERFACE;
1033 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
1034 ICOM_THIS(IDirect3DDevice8Impl,iface);
1035 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
1036 return ++(This->ref);
1039 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
1040 ICOM_THIS(IDirect3DDevice8Impl,iface);
1041 ULONG ref = --This->ref;
1042 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
1043 if (ref == 0) {
1044 HeapFree(GetProcessHeap(), 0, This);
1046 return ref;
1049 /* IDirect3DDevice Interface follow: */
1050 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
1051 ICOM_THIS(IDirect3DDevice8Impl,iface);
1052 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
1053 return D3D_OK;
1056 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
1057 ICOM_THIS(IDirect3DDevice8Impl,iface);
1058 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
1060 * pretend we have 32MB of any type of memory queried.
1062 return (1024*1024*32);
1065 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
1066 ICOM_THIS(IDirect3DDevice8Impl,iface);
1067 FIXME("(%p) : stub\n", This); return D3D_OK;
1069 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
1070 ICOM_THIS(IDirect3DDevice8Impl,iface);
1071 TRACE("(%p) : returning %p\n", This, This->direct3d8);
1073 /* Inc ref count */
1074 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
1076 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
1077 return D3D_OK;
1079 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
1080 ICOM_THIS(IDirect3DDevice8Impl,iface);
1081 FIXME("(%p) : stub, calling idirect3d for now\n", This);
1082 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
1083 return D3D_OK;
1085 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
1087 HDC hdc;
1088 int bpp = 0;
1090 ICOM_THIS(IDirect3DDevice8Impl,iface);
1091 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
1092 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
1093 pMode->RefreshRate = 85; /*FIXME: How to identify? */
1095 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1096 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1097 DeleteDC(hdc);
1099 switch (bpp) {
1100 case 8: pMode->Format = D3DFMT_R8G8B8; break;
1101 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1102 case 24: pMode->Format = D3DFMT_R8G8B8; break;
1103 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1104 default:
1105 FIXME("Unrecognized display mode format\n");
1106 pMode->Format = D3DFMT_UNKNOWN;
1109 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%d)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format);
1110 return D3D_OK;
1112 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
1113 ICOM_THIS(IDirect3DDevice8Impl,iface);
1114 TRACE("(%p) copying to %p\n", This, pParameters);
1115 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
1116 return D3D_OK;
1118 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
1119 ICOM_THIS(IDirect3DDevice8Impl,iface);
1120 FIXME("(%p) : stub\n", This); return D3D_OK;
1122 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace,DWORD Flags) {
1123 ICOM_THIS(IDirect3DDevice8Impl,iface);
1124 FIXME("(%p) : stub\n", This); return;
1126 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
1127 ICOM_THIS(IDirect3DDevice8Impl,iface);
1128 FIXME("(%p) : stub\n", This); return D3D_OK;
1130 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
1131 ICOM_THIS(IDirect3DDevice8Impl,iface);
1132 FIXME("(%p) : stub\n", This); return D3D_OK;
1134 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
1135 ICOM_THIS(IDirect3DDevice8Impl,iface);
1136 FIXME("(%p) : stub\n", This); return D3D_OK;
1138 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
1139 ICOM_THIS(IDirect3DDevice8Impl,iface);
1140 TRACE("(%p) : complete stub!\n", This);
1142 ENTER_GL();
1144 glXSwapBuffers(This->display, This->win);
1145 checkGLcall("glXSwapBuffers");
1147 LEAVE_GL();
1149 return D3D_OK;
1151 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface8** ppBackBuffer) {
1152 ICOM_THIS(IDirect3DDevice8Impl,iface);
1153 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
1154 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
1156 /* Note inc ref on returned surface */
1157 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
1159 return D3D_OK;
1161 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
1162 ICOM_THIS(IDirect3DDevice8Impl,iface);
1163 FIXME("(%p) : stub\n", This); return D3D_OK;
1165 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags,CONST D3DGAMMARAMP* pRamp) {
1166 ICOM_THIS(IDirect3DDevice8Impl,iface);
1167 FIXME("(%p) : stub\n", This); return;
1169 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
1170 ICOM_THIS(IDirect3DDevice8Impl,iface);
1171 FIXME("(%p) : stub\n", This); return;
1173 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
1174 D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture8** ppTexture) {
1175 IDirect3DTexture8Impl *object;
1176 int i;
1177 UINT tmpW;
1178 UINT tmpH;
1180 ICOM_THIS(IDirect3DDevice8Impl,iface);
1182 /* Allocate the storage for the device */
1183 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool);
1184 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
1185 object->lpVtbl = &Direct3DTexture8_Vtbl;
1186 object->Device = This; /* FIXME: AddRef(This) */
1187 object->ResourceType = D3DRTYPE_TEXTURE;
1188 object->ref = 1;
1189 object->width = Width;
1190 object->height = Height;
1191 object->levels = Levels;
1192 object->usage = Usage;
1193 object->format = Format;
1194 object->device = This;
1196 /* Calculate levels for mip mapping */
1197 if (Levels == 0) {
1198 object->levels++;
1199 tmpW = Width;
1200 tmpH = Height;
1201 while (tmpW > 1 && tmpH > 1) {
1202 tmpW = max(1,tmpW / 2);
1203 tmpH = max(1, tmpH / 2);
1204 object->levels++;
1206 TRACE("Calculated levels = %d\n", object->levels);
1209 /* Generate all the surfaces */
1210 tmpW = Width;
1211 tmpH = Height;
1212 for (i=0; i<object->levels; i++)
1214 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
1215 object->surfaces[i]->Container = (IUnknown*) object; /* FIXME: AddRef(object) */
1216 object->surfaces[i]->myDesc.Usage = Usage;
1217 object->surfaces[i]->myDesc.Pool = Pool ;
1219 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
1220 tmpW = max(1, tmpW / 2);
1221 tmpH = max(1, tmpH / 2);
1224 *ppTexture = (LPDIRECT3DTEXTURE8)object;
1225 return D3D_OK;
1227 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture8** ppVolumeTexture) {
1229 IDirect3DVolumeTexture8Impl *object;
1230 int i;
1231 UINT tmpW;
1232 UINT tmpH;
1233 UINT tmpD;
1235 ICOM_THIS(IDirect3DDevice8Impl,iface);
1237 /* Allocate the storage for it */
1238 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);
1239 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
1240 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
1241 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
1242 object->ref = 1;
1245 object->width = Width;
1246 object->height = Height;
1247 object->depth = Depth;
1248 object->levels = Levels;
1249 object->usage = Usage;
1250 object->format = Format;
1251 object->device = This;
1253 /* Calculate levels for mip mapping */
1254 if (Levels == 0) {
1255 object->levels++;
1256 tmpW = Width;
1257 tmpH = Height;
1258 tmpD = Depth;
1259 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
1260 tmpW = max(1,tmpW / 2);
1261 tmpH = max(1, tmpH / 2);
1262 tmpD = max(1, tmpD / 2);
1263 object->levels++;
1265 TRACE("Calculated levels = %d\n", object->levels);
1268 /* Generate all the surfaces */
1269 tmpW = Width;
1270 tmpH = Height;
1271 tmpD = Depth;
1273 for (i=0; i<object->levels; i++)
1275 IDirect3DVolume8Impl *volume;
1277 /* Create the volume - No entry point for this seperately?? */
1278 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
1279 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
1281 volume->lpVtbl = &Direct3DVolume8_Vtbl;
1282 volume->Device = This; /* FIXME: AddRef(This) */
1283 volume->ResourceType = D3DRTYPE_VOLUME;
1284 volume->Container = object;
1285 volume->ref = 1;
1287 volume->myDesc.Width = Width;
1288 volume->myDesc.Height= Height;
1289 volume->myDesc.Depth = Depth;
1290 volume->myDesc.Format= Format;
1291 volume->myDesc.Type = D3DRTYPE_VOLUME;
1292 volume->myDesc.Pool = Pool;
1293 volume->myDesc.Usage = Usage;
1294 volume->bytesPerPixel = bytesPerPixel(Format);
1295 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
1296 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
1298 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Depth, Format,
1299 volume, volume->allocatedMemory, volume->myDesc.Size);
1301 tmpW = max(1,tmpW / 2);
1302 tmpH = max(1, tmpH / 2);
1303 tmpD = max(1, tmpD / 2);
1306 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8)object;
1307 return D3D_OK;
1309 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture8** ppCubeTexture) {
1311 IDirect3DCubeTexture8Impl *object;
1312 ICOM_THIS(IDirect3DDevice8Impl,iface);
1313 int i,j;
1314 UINT tmpW;
1316 /* Allocate the storage for it */
1317 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%d), Pool(%d)\n", This, EdgeLength, Levels, Usage, Format, Pool);
1318 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
1319 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
1320 object->ref = 1;
1321 object->Device = This; /* FIXME: AddRef(This) */
1322 object->ResourceType = D3DRTYPE_CUBETEXTURE;
1324 object->edgeLength = EdgeLength;
1325 object->levels = Levels;
1326 object->usage = Usage;
1327 object->format = Format;
1328 object->device = This;
1330 /* Calculate levels for mip mapping */
1331 if (Levels == 0) {
1332 object->levels++;
1333 tmpW = EdgeLength;
1334 while (tmpW > 1) {
1335 tmpW = max(1,tmpW / 2);
1336 object->levels++;
1338 TRACE("Calculated levels = %d\n", object->levels);
1341 /* Generate all the surfaces */
1342 tmpW = EdgeLength;
1343 for (i=0; i<object->levels; i++)
1345 /* Create the 6 faces */
1346 for (j=0;j<6;j++) {
1347 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
1348 object->surfaces[j][i]->Container = (IUnknown*) object;
1349 object->surfaces[j][i]->myDesc.Usage = Usage;
1350 object->surfaces[j][i]->myDesc.Pool = Pool ;
1352 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
1353 tmpW = max(1,tmpW / 2);
1357 TRACE("(%p) : Iface@%p\n", This, object);
1358 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8)object;
1359 return D3D_OK;
1361 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage,
1362 DWORD FVF,D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
1363 IDirect3DVertexBuffer8Impl *object;
1365 ICOM_THIS(IDirect3DDevice8Impl,iface);
1367 /* Allocate the storage for the device */
1368 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
1369 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
1370 object->Device = This;
1371 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
1372 object->ref = 1;
1373 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
1374 object->currentDesc.Usage = Usage;
1375 object->currentDesc.Pool = Pool;
1376 object->currentDesc.FVF = FVF;
1377 object->currentDesc.Size = Size;
1379 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
1381 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8)object;
1383 return D3D_OK;
1385 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer8** ppIndexBuffer) {
1387 IDirect3DIndexBuffer8Impl *object;
1389 ICOM_THIS(IDirect3DDevice8Impl,iface);
1390 TRACE("(%p) : Len=%d, Use=%lx, Format=%x, Pool=%d\n", This, Length, Usage, Format, Pool);
1392 /* Allocate the storage for the device */
1393 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
1394 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
1395 object->ref = 1;
1396 object->Device = This;
1397 object->ResourceType = D3DRTYPE_INDEXBUFFER;
1399 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
1400 object->currentDesc.Usage = Usage;
1401 object->currentDesc.Pool = Pool;
1402 object->currentDesc.Format = Format;
1403 object->currentDesc.Size = Length;
1405 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
1407 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
1409 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8)object;
1411 return D3D_OK;
1413 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,BOOL Lockable,IDirect3DSurface8** ppSurface) {
1414 ICOM_THIS(IDirect3DDevice8Impl,iface);
1415 /* up ref count on surface, surface->container = This */
1416 FIXME("(%p) : stub\n", This); return D3D_OK;
1418 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,IDirect3DSurface8** ppSurface) {
1419 ICOM_THIS(IDirect3DDevice8Impl,iface);
1420 /* surface->container = This */
1421 FIXME("(%p) : stub\n", This); return D3D_OK;
1423 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width,UINT Height,D3DFORMAT Format,IDirect3DSurface8** ppSurface) {
1424 IDirect3DSurface8Impl *object;
1426 ICOM_THIS(IDirect3DDevice8Impl,iface);
1428 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
1429 *ppSurface = (LPDIRECT3DSURFACE8) object;
1430 object->lpVtbl = &Direct3DSurface8_Vtbl;
1431 object->Device = This;
1432 object->ResourceType = D3DRTYPE_SURFACE;
1433 object->Container = (IUnknown*) This;
1435 object->ref = 1;
1436 object->myDesc.Width = Width;
1437 object->myDesc.Height= Height;
1438 object->myDesc.Format= Format;
1439 object->myDesc.Type = D3DRTYPE_SURFACE;
1440 /*object->myDesc.Usage */
1441 object->myDesc.Pool = D3DPOOL_SYSTEMMEM ;
1442 object->bytesPerPixel = bytesPerPixel(Format);
1443 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
1444 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
1446 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);
1447 return D3D_OK;
1449 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pSourceSurface,CONST RECT* pSourceRectsArray,UINT cRects,
1450 IDirect3DSurface8* pDestinationSurface,CONST POINT* pDestPointsArray) {
1452 HRESULT rc = D3D_OK;
1453 IDirect3DBaseTexture8* texture = NULL;
1456 IDirect3DSurface8Impl *src = (IDirect3DSurface8Impl*) pSourceSurface;
1457 IDirect3DSurface8Impl *dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1459 ICOM_THIS(IDirect3DDevice8Impl,iface);
1460 TRACE("(%p) srcsur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1461 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1463 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1464 a sample and doesnt seem to break anything as far as I can tell */
1465 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1466 TRACE("Formats do not match %x / %x\n", src->myDesc.Format, dst->myDesc.Format);
1467 rc = D3DERR_INVALIDCALL;
1469 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1470 TRACE("Converting dest to same format as source, since dest was unknown\n");
1471 dst->myDesc.Format = src->myDesc.Format;
1473 /* Convert container as well */
1474 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1475 if (texture != NULL) {
1477 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1478 case D3DRTYPE_TEXTURE:
1479 ((IDirect3DTexture8Impl *)texture)->format = src->myDesc.Format;
1480 break;
1481 case D3DRTYPE_VOLUMETEXTURE:
1482 ((IDirect3DVolumeTexture8Impl *)texture)->format = src->myDesc.Format;
1483 break;
1484 case D3DRTYPE_CUBETEXTURE:
1485 ((IDirect3DCubeTexture8Impl *)texture)->format = src->myDesc.Format;
1486 break;
1487 default:
1488 FIXME("Unhandled texture type\n");
1491 /** Releasing texture after GetContainer */
1492 IDirect3DBaseTexture8_Release(texture);
1496 /* Quick if complete copy ... */
1497 if (rc == D3D_OK && (cRects == 0 && pSourceRectsArray==NULL && pDestPointsArray==NULL &&
1498 src->myDesc.Width == dst->myDesc.Width &&
1499 src->myDesc.Height == dst->myDesc.Height)) {
1500 TRACE("Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1501 memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);
1503 } else {
1504 int i;
1505 int bytesPerPixel = ((IDirect3DSurface8Impl *)pSourceSurface)->bytesPerPixel;
1506 int pitchFrom = ((IDirect3DSurface8Impl *)pSourceSurface)->myDesc.Width * bytesPerPixel;
1507 int pitchTo = ((IDirect3DSurface8Impl *)pDestinationSurface)->myDesc.Width * bytesPerPixel;
1509 char *copyfrom = ((IDirect3DSurface8Impl *)pSourceSurface)->allocatedMemory;
1510 char *copyto = ((IDirect3DSurface8Impl *)pDestinationSurface)->allocatedMemory;
1512 /* Copy rect by rect */
1513 for (i=0; i<cRects; i++) {
1514 CONST RECT *r = &pSourceRectsArray[i];
1515 CONST POINT *p = &pDestPointsArray[i];
1516 char *from;
1517 char *to;
1518 int copyperline = (r->right - r->left) * bytesPerPixel;
1519 int j;
1521 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top,
1522 r->right, r->bottom, p->x, p->y);
1524 /* Find where to start */
1525 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
1526 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
1528 /* Copy line by line */
1529 for (j=0; j<(r->bottom - r->top); j++) {
1530 memcpy(to + (j*pitchTo), from + (j*pitchFrom), copyperline);
1535 /* Set dirty */
1536 if (rc == D3D_OK) {
1537 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1538 if (texture != NULL) {
1540 switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) texture)) {
1541 case D3DRTYPE_TEXTURE:
1543 IDirect3DTexture8Impl *pTexture = (IDirect3DTexture8Impl *)texture;
1544 pTexture->Dirty = TRUE;
1546 break;
1547 case D3DRTYPE_VOLUMETEXTURE:
1549 IDirect3DVolumeTexture8Impl *pTexture = (IDirect3DVolumeTexture8Impl *)texture;
1550 pTexture->Dirty = TRUE;
1552 break;
1553 case D3DRTYPE_CUBETEXTURE:
1555 IDirect3DCubeTexture8Impl *pTexture = (IDirect3DCubeTexture8Impl *)texture;
1556 pTexture->Dirty = TRUE;
1558 break;
1559 default:
1560 FIXME("Unhandled texture type\n");
1563 /** Releasing texture after GetContainer */
1564 IDirect3DBaseTexture8_Release(texture);
1568 return D3D_OK;
1570 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture,IDirect3DBaseTexture8* pDestinationTexture) {
1571 ICOM_THIS(IDirect3DDevice8Impl,iface);
1572 FIXME("(%p) : stub\n", This); return D3D_OK;
1574 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1575 ICOM_THIS(IDirect3DDevice8Impl,iface);
1576 FIXME("(%p) : stub\n", This); return D3D_OK;
1578 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget,IDirect3DSurface8* pNewZStencil) {
1579 ICOM_THIS(IDirect3DDevice8Impl,iface);
1580 FIXME("(%p) : stub\n", This);
1582 return D3D_OK;
1584 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1585 ICOM_THIS(IDirect3DDevice8Impl,iface);
1586 /*TRACE("(%p) : returning %p\n", This, This->renderTarget); */
1587 FIXME("(%p) : stub\n", This);
1590 **ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1591 *IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1594 return D3D_OK;
1596 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1598 ICOM_THIS(IDirect3DDevice8Impl,iface);
1600 TRACE("(%p)->(%p)\n", This, ppZStencilSurface);
1602 /* Note inc ref on returned surface */
1603 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8)This->depthStencilBuffer);
1604 *ppZStencilSurface = (LPDIRECT3DSURFACE8)This->depthStencilBuffer;
1606 return D3D_OK;
1609 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1610 ICOM_THIS(IDirect3DDevice8Impl,iface);
1611 TRACE("(%p) : stub\n", This);
1612 return D3D_OK;
1614 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1615 ICOM_THIS(IDirect3DDevice8Impl,iface);
1616 TRACE("(%p)\n", This);
1618 ENTER_GL();
1620 glFlush();
1621 checkGLcall("glFlush");
1623 /* Useful for debugging sometimes!
1624 printf("Hit Enter ...\n");
1625 getchar(); */
1627 LEAVE_GL();
1628 return D3D_OK;
1630 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) {
1631 ICOM_THIS(IDirect3DDevice8Impl,iface);
1633 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1634 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1635 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1636 GLbitfield glMask = 0;
1637 int i;
1638 CONST D3DRECT *curRect;
1640 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1641 Count, pRects, Flags, Z, Stencil);
1643 ENTER_GL();
1644 if (Count > 0 && pRects) {
1645 glEnable(GL_SCISSOR_TEST);
1646 checkGLcall("glEnable GL_SCISSOR_TEST");
1647 curRect = pRects;
1648 } else {
1649 curRect = NULL;
1652 for (i=0;i<Count || i==0; i++) {
1654 if (curRect) {
1655 /* Note gl uses lower left, width/height */
1656 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1657 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1658 curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1659 glScissor(curRect->x1, curRect->y2, curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1660 checkGLcall("glScissor");
1663 /* Clear the whole screen */
1664 if (Flags & D3DCLEAR_STENCIL) {
1665 glClearStencil(Stencil);
1666 checkGLcall("glClearStencil");
1667 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1670 if (Flags & D3DCLEAR_ZBUFFER) {
1671 glClearDepth(Z);
1672 checkGLcall("glClearDepth");
1673 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1676 if (Flags & D3DCLEAR_TARGET) {
1677 TRACE("Clearing screen with glClear to color %lx\n", Color);
1678 glClearColor(((Color >> 16) & 0xFF) / 255.0, ((Color >> 8) & 0xFF) / 255.0,
1679 ((Color >> 0) & 0xFF) / 255.0, ((Color >> 24) & 0xFF) / 255.0);
1680 checkGLcall("glClearColor");
1681 glMask = glMask | GL_COLOR_BUFFER_BIT;
1684 glClear(glMask);
1685 checkGLcall("glClear");
1687 if (curRect) curRect = curRect + sizeof(D3DRECT);
1690 if (Count > 0 && pRects) {
1691 glDisable(GL_SCISSOR_TEST);
1692 checkGLcall("glDisable");
1694 LEAVE_GL();
1696 return D3D_OK;
1698 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
1699 ICOM_THIS(IDirect3DDevice8Impl,iface);
1700 D3DMATRIX m;
1701 int k;
1702 float f;
1704 /* Most of this routine, comments included copied from ddraw tree initially: */
1705 TRACE("(%p) : State=%d\n", This, d3dts);
1707 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1708 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1709 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1711 /* Handle recording of state blocks */
1712 if (This->isRecordingState) {
1713 TRACE("Recording... not performing anything\n");
1714 return D3D_OK;
1718 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1720 where ViewMat = Camera space, WorldMat = world space.
1722 In OpenGL, camera and world space is combined into GL_MODELVIEW
1723 matrix. The Projection matrix stay projection matrix. */
1725 /* After reading through both OpenGL and Direct3D documentations, I
1726 thought that D3D matrices were written in 'line major mode' transposed
1727 from OpenGL's 'column major mode'. But I found out that a simple memcpy
1728 works fine to transfer one matrix format to the other (it did not work
1729 when transposing)....
1731 So :
1732 1) are the documentations wrong
1733 2) does the matrix work even if they are not read correctly
1734 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
1735 loading using glLoadMatrix ?
1737 Anyway, I always use 'conv_mat' to transfer the matrices from one format
1738 to the other so that if I ever find out that I need to transpose them, I
1739 will able to do it quickly, only by changing the macro conv_mat. */
1741 if (d3dts < 256) {
1742 switch (d3dts) {
1743 case D3DTS_WORLDMATRIX(0):
1744 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)]);
1745 break;
1747 case D3DTS_VIEW:
1748 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
1749 break;
1751 case D3DTS_PROJECTION:
1752 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
1753 break;
1755 case D3DTS_TEXTURE0:
1756 case D3DTS_TEXTURE1:
1757 case D3DTS_TEXTURE2:
1758 case D3DTS_TEXTURE3:
1759 case D3DTS_TEXTURE4:
1760 case D3DTS_TEXTURE5:
1761 case D3DTS_TEXTURE6:
1762 case D3DTS_TEXTURE7:
1763 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
1764 FIXME("Unhandled transform state for TEXTURE%d!!!\n", d3dts - D3DTS_TEXTURE0);
1765 FIXME("must use glMatrixMode(GL_TEXTURE) before texturing\n");
1766 break;
1768 default:
1769 FIXME("Unhandled transform state!!\n");
1770 break;
1772 } else {
1773 /**
1774 * Indexed Vertex Blending Matrices 256 -> 511
1776 /** store it */
1777 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
1778 if (checkGLSupport(ARB_VERTEX_BLEND)) {
1779 FIXME("TODO\n");
1780 } else if (checkGLSupport(EXT_VERTEX_WEIGHTING)) {
1781 FIXME("TODO\n");
1786 * Move the GL operation to outside of switch to make it work
1787 * regardless of transform set order. Optimize later.
1789 ENTER_GL();
1790 glMatrixMode(GL_PROJECTION);
1791 checkGLcall("glMatrixMode");
1792 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
1793 checkGLcall("glLoadMatrixf");
1795 glMatrixMode(GL_MODELVIEW);
1796 checkGLcall("glMatrixMode");
1797 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1798 checkGLcall("glLoadMatrixf");
1800 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
1801 if (d3dts == D3DTS_VIEW) {
1803 /* NOTE: We have to reset the positions even if the light/plane is not currently
1804 enabled, since the call to enable it will not reset the position. */
1806 /* Reset lights */
1807 for (k = 0; k < This->maxLights; k++) {
1808 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
1809 checkGLcall("glLightfv posn");
1810 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
1811 checkGLcall("glLightfv dirn");
1814 /* Reset Clipping Planes if clipping is enabled */
1815 for (k = 0; k < This->clipPlanes; k++) {
1816 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1817 checkGLcall("glClipPlane");
1823 * Vertex Blending as described
1824 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
1826 switch (This->UpdateStateBlock->vertex_blend) {
1827 case D3DVBF_DISABLE:
1829 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
1830 checkGLcall("glMultMatrixf");
1832 break;
1833 case D3DVBF_1WEIGHTS:
1834 case D3DVBF_2WEIGHTS:
1835 case D3DVBF_3WEIGHTS:
1837 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
1839 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
1840 * so waiting for the values before matrix work
1841 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
1842 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
1843 checkGLcall("glMultMatrixf");
1847 break;
1848 case D3DVBF_TWEENING:
1850 FIXME("valid/correct D3DVBF_TWEENING\n");
1851 f = This->UpdateStateBlock->tween_factor;
1852 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
1853 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
1854 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
1855 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
1856 glMultMatrixf((float *) &m.u.m[0][0]);
1857 checkGLcall("glMultMatrixf");
1859 break;
1860 case D3DVBF_0WEIGHTS:
1862 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
1863 /* single matrix of weight 1.0f */
1864 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
1865 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
1866 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
1867 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
1868 glMultMatrixf((float *) &m.u.m[0][0]);
1869 checkGLcall("glMultMatrixf");
1871 break;
1872 default:
1873 break; /* stupid compilator */
1876 LEAVE_GL();
1878 return D3D_OK;
1881 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1882 ICOM_THIS(IDirect3DDevice8Impl,iface);
1883 TRACE("(%p) : for State %d\n", This, State);
1884 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1885 return D3D_OK;
1888 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1889 ICOM_THIS(IDirect3DDevice8Impl,iface);
1890 FIXME("(%p) : stub\n", This); return D3D_OK;
1892 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1893 ICOM_THIS(IDirect3DDevice8Impl,iface);
1895 TRACE("(%p)\n", This);
1896 This->UpdateStateBlock->Changed.viewport = TRUE;
1897 This->UpdateStateBlock->Set.viewport = TRUE;
1898 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1900 /* Handle recording of state blocks */
1901 if (This->isRecordingState) {
1902 TRACE("Recording... not performing anything\n");
1903 return D3D_OK;
1906 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1907 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1909 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1910 checkGLcall("glDepthRange");
1911 /* Fixme? Note GL requires lower left, DirectX supplies upper left */
1912 glViewport(pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height);
1913 checkGLcall("glViewport");
1916 return D3D_OK;
1919 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1920 ICOM_THIS(IDirect3DDevice8Impl,iface);
1921 TRACE("(%p)\n", This);
1922 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1923 return D3D_OK;
1926 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1927 ICOM_THIS(IDirect3DDevice8Impl,iface);
1929 This->UpdateStateBlock->Changed.material = TRUE;
1930 This->UpdateStateBlock->Set.material = TRUE;
1931 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1933 /* Handle recording of state blocks */
1934 if (This->isRecordingState) {
1935 TRACE("Recording... not performing anything\n");
1936 return D3D_OK;
1939 ENTER_GL();
1940 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1941 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1942 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1943 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1944 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1946 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&This->UpdateStateBlock->material.Ambient);
1947 checkGLcall("glMaterialfv");
1948 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&This->UpdateStateBlock->material.Diffuse);
1949 checkGLcall("glMaterialfv");
1951 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&This->UpdateStateBlock->material.Specular);
1952 checkGLcall("glMaterialfv");
1953 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&This->UpdateStateBlock->material.Emissive);
1954 checkGLcall("glMaterialfv");
1955 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1956 checkGLcall("glMaterialf");
1958 LEAVE_GL();
1959 return D3D_OK;
1961 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1962 ICOM_THIS(IDirect3DDevice8Impl,iface);
1963 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1964 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1965 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1966 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1967 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1968 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1969 return D3D_OK;
1972 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
1973 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
1974 float rho;
1975 float quad_att;
1977 ICOM_THIS(IDirect3DDevice8Impl,iface);
1978 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1980 if (Index > This->maxLights) {
1981 FIXME("Cannot handle more lights than device supports\n");
1982 return D3DERR_INVALIDCALL;
1985 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,
1986 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1987 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1988 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1989 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1990 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1991 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1993 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
1994 This->UpdateStateBlock->Set.lights[Index] = TRUE;
1995 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
1997 /* Handle recording of state blocks */
1998 if (This->isRecordingState) {
1999 TRACE("Recording... not performing anything\n");
2000 return D3D_OK;
2003 /* Diffuse: */
2004 colRGBA[0] = pLight->Diffuse.r;
2005 colRGBA[1] = pLight->Diffuse.g;
2006 colRGBA[2] = pLight->Diffuse.b;
2007 colRGBA[3] = pLight->Diffuse.a;
2008 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
2009 checkGLcall("glLightfv");
2011 /* Specular */
2012 colRGBA[0] = pLight->Specular.r;
2013 colRGBA[1] = pLight->Specular.g;
2014 colRGBA[2] = pLight->Specular.b;
2015 colRGBA[3] = pLight->Specular.a;
2016 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
2017 checkGLcall("glLightfv");
2019 /* Ambient */
2020 colRGBA[0] = pLight->Ambient.r;
2021 colRGBA[1] = pLight->Ambient.g;
2022 colRGBA[2] = pLight->Ambient.b;
2023 colRGBA[3] = pLight->Ambient.a;
2024 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
2025 checkGLcall("glLightfv");
2027 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
2028 glMatrixMode(GL_MODELVIEW);
2029 glPushMatrix();
2030 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2032 /* Attenuation - Are these right? guessing... */
2033 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
2034 checkGLcall("glLightf");
2035 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
2036 checkGLcall("glLightf");
2038 quad_att = 1.4/(pLight->Range*pLight->Range);
2039 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
2040 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
2041 checkGLcall("glLightf");
2043 switch (pLight->Type) {
2044 case D3DLIGHT_POINT:
2045 /* Position */
2046 This->lightPosn[Index][0] = pLight->Position.x;
2047 This->lightPosn[Index][1] = pLight->Position.y;
2048 This->lightPosn[Index][2] = pLight->Position.z;
2049 This->lightPosn[Index][3] = 1.0;
2050 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2051 checkGLcall("glLightfv");
2053 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
2054 checkGLcall("glLightf");
2056 /* FIXME: Range */
2057 break;
2059 case D3DLIGHT_SPOT:
2060 /* Position */
2061 This->lightPosn[Index][0] = pLight->Position.x;
2062 This->lightPosn[Index][1] = pLight->Position.y;
2063 This->lightPosn[Index][2] = pLight->Position.z;
2064 This->lightPosn[Index][3] = 1.0;
2065 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
2066 checkGLcall("glLightfv");
2068 /* Direction */
2069 This->lightDirn[Index][0] = pLight->Direction.x;
2070 This->lightDirn[Index][1] = pLight->Direction.y;
2071 This->lightDirn[Index][2] = pLight->Direction.z;
2072 This->lightDirn[Index][3] = 1.0;
2073 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
2074 checkGLcall("glLightfv");
2077 * opengl-ish and d3d-ish spot lights use too different models for the
2078 * light "intensity" as a function of the angle towards the main light direction,
2079 * so we only can approximate very roughly.
2080 * however spot lights are rather rarely used in games (if ever used at all).
2081 * furthermore if still used, probably nobody pays attention to such details.
2083 if (pLight->Falloff == 0) {
2084 rho = 6.28f;
2085 } else {
2086 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2088 if (rho < 0.0001) rho = 0.0001f;
2089 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
2090 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
2092 /* FIXME: Range */
2093 break;
2094 case D3DLIGHT_DIRECTIONAL:
2095 /* Direction */
2096 This->lightPosn[Index][0] = -pLight->Direction.x;
2097 This->lightPosn[Index][1] = -pLight->Direction.y;
2098 This->lightPosn[Index][2] = -pLight->Direction.z;
2099 This->lightPosn[Index][3] = 0.0;
2100 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
2101 checkGLcall("glLightfv");
2103 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
2104 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
2107 break;
2108 default:
2109 FIXME("Unrecognized light type %d\n", pLight->Type);
2112 /* Restore the modelview matrix */
2113 glPopMatrix();
2115 return D3D_OK;
2117 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
2118 ICOM_THIS(IDirect3DDevice8Impl,iface);
2119 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
2121 if (Index > This->maxLights) {
2122 FIXME("Cannot handle more lights than device supports\n");
2123 return D3DERR_INVALIDCALL;
2126 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
2127 return D3D_OK;
2129 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
2130 ICOM_THIS(IDirect3DDevice8Impl,iface);
2131 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
2133 if (Index > This->maxLights) {
2134 FIXME("Cannot handle more lights than device supports\n");
2135 return D3DERR_INVALIDCALL;
2138 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
2139 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
2140 This->UpdateStateBlock->lightEnable[Index] = Enable;
2142 /* Handle recording of state blocks */
2143 if (This->isRecordingState) {
2144 TRACE("Recording... not performing anything\n");
2145 return D3D_OK;
2148 if (Enable) {
2149 glEnable(GL_LIGHT0+Index);
2150 checkGLcall("glEnable GL_LIGHT0+Index");
2151 } else {
2152 glDisable(GL_LIGHT0+Index);
2153 checkGLcall("glDisable GL_LIGHT0+Index");
2155 return D3D_OK;
2157 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2158 ICOM_THIS(IDirect3DDevice8Impl,iface);
2159 TRACE("(%p) : for idx(%ld)\n", This, Index);
2161 if (Index > This->maxLights) {
2162 FIXME("Cannot handle more lights than device supports\n");
2163 return D3DERR_INVALIDCALL;
2166 *pEnable = This->StateBlock->lightEnable[Index];
2167 return D3D_OK;
2169 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2170 ICOM_THIS(IDirect3DDevice8Impl,iface);
2171 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2173 /* Validate Index */
2174 if (Index >= This->clipPlanes ) {
2175 TRACE("Application has requested clipplane this device doesnt support\n");
2176 return D3DERR_INVALIDCALL;
2179 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2180 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2181 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2182 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2183 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2184 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2186 /* Handle recording of state blocks */
2187 if (This->isRecordingState) {
2188 TRACE("Recording... not performing anything\n");
2189 return D3D_OK;
2192 /* Apply it */
2194 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2195 glMatrixMode(GL_MODELVIEW);
2196 glPushMatrix();
2197 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2199 TRACE("Clipplane [%f,%f,%f,%f]\n", This->UpdateStateBlock->clipplane[Index][0], This->UpdateStateBlock->clipplane[Index][1],
2200 This->UpdateStateBlock->clipplane[Index][2], This->UpdateStateBlock->clipplane[Index][3]);
2201 glClipPlane(GL_CLIP_PLANE0+Index, This->UpdateStateBlock->clipplane[Index]);
2203 glPopMatrix();
2204 checkGLcall("glClipPlane");
2206 return D3D_OK;
2208 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2209 ICOM_THIS(IDirect3DDevice8Impl,iface);
2210 TRACE("(%p) : for idx %ld\n", This, Index);
2212 /* Validate Index */
2213 if (Index >= This->clipPlanes ) {
2214 TRACE("Application has requested clipplane this device doesnt support\n");
2215 return D3DERR_INVALIDCALL;
2218 pPlane[0] = This->StateBlock->clipplane[Index][0];
2219 pPlane[1] = This->StateBlock->clipplane[Index][0];
2220 pPlane[2] = This->StateBlock->clipplane[Index][0];
2221 pPlane[3] = This->StateBlock->clipplane[Index][0];
2222 return D3D_OK;
2224 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2225 ICOM_THIS(IDirect3DDevice8Impl,iface);
2226 DWORD OldValue = This->StateBlock->renderstate[State];
2228 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
2229 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2230 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2231 This->UpdateStateBlock->renderstate[State] = Value;
2233 /* Handle recording of state blocks */
2234 if (This->isRecordingState) {
2235 TRACE("Recording... not performing anything\n");
2236 return D3D_OK;
2239 switch (State) {
2240 case D3DRS_FILLMODE :
2241 switch ((D3DFILLMODE) Value) {
2242 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2243 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2244 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2245 default:
2246 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2248 checkGLcall("glPolygonMode (fillmode)");
2249 break;
2251 case D3DRS_LIGHTING :
2252 if (Value) {
2253 glEnable(GL_LIGHTING);
2254 checkGLcall("glEnable GL_LIGHTING");
2255 } else {
2256 glDisable(GL_LIGHTING);
2257 checkGLcall("glDisable GL_LIGHTING");
2259 break;
2261 case D3DRS_ZENABLE :
2262 switch ((D3DZBUFFERTYPE) Value) {
2263 case D3DZB_FALSE:
2264 glDisable(GL_DEPTH_TEST);
2265 checkGLcall("glDisable GL_DEPTH_TEST");
2266 break;
2267 case D3DZB_TRUE:
2268 glEnable(GL_DEPTH_TEST);
2269 checkGLcall("glEnable GL_DEPTH_TEST");
2270 break;
2272 case D3DZB_USEW:
2273 default:
2274 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2276 break;
2278 case D3DRS_CULLMODE :
2280 /* If we are culling "back faces with clockwise vertices" then
2281 set front faces to be counter clockwise and enable culling
2282 of back faces */
2283 switch ((D3DCULL) Value) {
2284 case D3DCULL_NONE:
2285 glDisable(GL_CULL_FACE);
2286 checkGLcall("glDisable GL_CULL_FACE");
2287 break;
2288 case D3DCULL_CW:
2289 glEnable(GL_CULL_FACE);
2290 checkGLcall("glEnable GL_CULL_FACE");
2291 glFrontFace(GL_CCW);
2292 checkGLcall("glFrontFace GL_CCW");
2293 glCullFace(GL_BACK);
2294 break;
2295 case D3DCULL_CCW:
2296 glEnable(GL_CULL_FACE);
2297 checkGLcall("glEnable GL_CULL_FACE");
2298 glFrontFace(GL_CW);
2299 checkGLcall("glFrontFace GL_CW");
2300 glCullFace(GL_BACK);
2301 break;
2302 default:
2303 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2305 break;
2307 case D3DRS_SHADEMODE :
2308 switch ((D3DSHADEMODE) Value) {
2309 case D3DSHADE_FLAT:
2310 glShadeModel(GL_FLAT);
2311 checkGLcall("glShadeModel");
2312 break;
2313 case D3DSHADE_GOURAUD:
2314 glShadeModel(GL_SMOOTH);
2315 checkGLcall("glShadeModel");
2316 break;
2317 case D3DSHADE_PHONG:
2318 FIXME("D3DSHADE_PHONG isnt supported?\n");
2319 return D3DERR_INVALIDCALL;
2320 default:
2321 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2323 break;
2325 case D3DRS_DITHERENABLE :
2326 if (Value) {
2327 glEnable(GL_DITHER);
2328 checkGLcall("glEnable GL_DITHER");
2329 } else {
2330 glDisable(GL_DITHER);
2331 checkGLcall("glDisable GL_DITHER");
2333 break;
2335 case D3DRS_ZWRITEENABLE :
2336 if (Value) {
2337 glDepthMask(1);
2338 checkGLcall("glDepthMask");
2339 } else {
2340 glDepthMask(0);
2341 checkGLcall("glDepthMask");
2343 break;
2345 case D3DRS_ZFUNC :
2347 int glParm = GL_LESS;
2349 switch ((D3DCMPFUNC) Value) {
2350 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2351 case D3DCMP_LESS: glParm=GL_LESS; break;
2352 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2353 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2354 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2355 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2356 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2357 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2358 default:
2359 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2361 glDepthFunc(glParm);
2362 checkGLcall("glDepthFunc");
2364 break;
2366 case D3DRS_AMBIENT :
2369 float col[4];
2370 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2371 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2372 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2373 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2374 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0],col[1],col[2],col[3]);
2375 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2376 checkGLcall("glLightModel for MODEL_AMBIENT");
2379 break;
2381 case D3DRS_ALPHABLENDENABLE :
2382 if (Value) {
2383 glEnable(GL_BLEND);
2384 checkGLcall("glEnable GL_BLEND");
2385 } else {
2386 glDisable(GL_BLEND);
2387 checkGLcall("glDisable GL_BLEND");
2389 break;
2391 case D3DRS_SRCBLEND :
2392 case D3DRS_DESTBLEND :
2394 int newVal = GL_ZERO;
2395 switch (Value) {
2396 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2397 case D3DBLEND_ONE : newVal = GL_ONE; break;
2398 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2399 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2400 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2401 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2402 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2403 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2404 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2405 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2406 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2408 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2409 This->srcBlend = newVal;
2410 This->dstBlend = newVal;
2411 break;
2413 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2414 This->srcBlend = newVal;
2415 This->dstBlend = newVal;
2416 break;
2417 default:
2418 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2421 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2422 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2423 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2424 glBlendFunc(This->srcBlend, This->dstBlend);
2426 checkGLcall("glBlendFunc");
2428 break;
2430 case D3DRS_ALPHATESTENABLE :
2431 if (Value) {
2432 glEnable(GL_ALPHA_TEST);
2433 checkGLcall("glEnable GL_ALPHA_TEST");
2434 } else {
2435 glDisable(GL_ALPHA_TEST);
2436 checkGLcall("glDisable GL_ALPHA_TEST");
2438 break;
2440 case D3DRS_ALPHAFUNC :
2442 int glParm = GL_LESS;
2443 float ref = 1.0;
2445 glGetFloatv(GL_ALPHA_TEST_REF, &ref);
2446 checkGLcall("glGetFloatv(GL_ALPHA_TEST_REF, &ref);");
2448 switch ((D3DCMPFUNC) Value) {
2449 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2450 case D3DCMP_LESS: glParm=GL_LESS; break;
2451 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2452 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2453 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2454 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2455 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2456 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2457 default:
2458 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2460 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2461 glAlphaFunc(glParm, ref);
2462 checkGLcall("glAlphaFunc");
2464 break;
2466 case D3DRS_ALPHAREF :
2468 int glParm = GL_LESS;
2469 float ref = 1.0;
2471 glGetIntegerv(GL_ALPHA_TEST_FUNC, &glParm);
2472 checkGLcall("glGetFloatv(GL_ALPHA_TEST_FUNC, &glParm);");
2474 ref = ((float) Value) / 255.0;
2475 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2476 glAlphaFunc(glParm, ref);
2477 checkGLcall("glAlphaFunc");
2479 break;
2481 case D3DRS_CLIPPLANEENABLE :
2482 case D3DRS_CLIPPING :
2484 /* Ensure we only do the changed clip planes */
2485 DWORD enable = 0xFFFFFFFF;
2486 DWORD disable = 0x00000000;
2488 /* If enabling / disabling all */
2489 if (State == D3DRS_CLIPPING) {
2490 if (Value) {
2491 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2492 disable = 0x00;
2493 } else {
2494 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2495 enable = 0x00;
2497 } else {
2498 enable = Value & ~OldValue;
2499 disable = ~Value & OldValue;
2502 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2503 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2504 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2505 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2506 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2507 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2509 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2510 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2511 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2512 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2513 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2514 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2516 break;
2518 case D3DRS_BLENDOP :
2520 int glParm = GL_FUNC_ADD;
2522 switch ((D3DBLENDOP) Value) {
2523 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2524 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2525 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2526 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2527 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2528 default:
2529 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2531 TRACE("glBlendEquation(%x)\n", glParm);
2532 glBlendEquation(glParm);
2533 checkGLcall("glBlendEquation");
2535 break;
2537 case D3DRS_TEXTUREFACTOR :
2539 int i;
2541 /* Note the texture color applies to all textures whereas
2542 GL_TEXTURE_ENV_COLOR applies to active only */
2543 float col[4];
2544 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2545 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2546 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2547 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2549 /* Set the default alpha blend color */
2550 glBlendColor(col[0], col[1], col[2], col[3]);
2551 checkGLcall("glBlendColor");
2553 /* And now the default texture color as well */
2554 for (i = 0; i < This->TextureUnits; i++) {
2556 /* Note the D3DRS value applies to all textures, but GL has one
2557 per texture, so apply it now ready to be used! */
2558 if (This->isMultiTexture) {
2559 #if defined(GL_VERSION_1_3)
2560 glActiveTexture(GL_TEXTURE0 + i);
2561 #else
2562 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2563 #endif
2564 checkGLcall("Activate texture.. to update const color");
2565 } else if (i>0) {
2566 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2569 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2570 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2573 break;
2575 case D3DRS_SPECULARENABLE :
2577 if (Value) {
2578 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
2579 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);");
2580 } else {
2581 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
2582 checkGLcall("glLightModel (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);");
2585 break;
2587 case D3DRS_STENCILENABLE :
2588 if (Value) {
2589 glEnable(GL_STENCIL_TEST);
2590 checkGLcall("glEnable GL_STENCIL_TEST");
2591 } else {
2592 glDisable(GL_STENCIL_TEST);
2593 checkGLcall("glDisable GL_STENCIL_TEST");
2595 break;
2597 case D3DRS_STENCILFUNC :
2599 int glParm = GL_ALWAYS;
2600 int ref = 0;
2601 GLuint mask = 0xFFFFFFFF;
2603 glGetIntegerv(GL_STENCIL_REF, &ref);
2604 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
2605 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
2606 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
2608 switch ((D3DCMPFUNC) Value) {
2609 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2610 case D3DCMP_LESS: glParm=GL_LESS; break;
2611 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2612 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2613 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2614 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2615 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2616 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2617 default:
2618 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2620 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2621 glStencilFunc(glParm, ref, mask);
2622 checkGLcall("glStencilFunc");
2624 break;
2626 case D3DRS_STENCILREF :
2628 int glParm = GL_ALWAYS;
2629 int ref = 0;
2630 GLuint mask = 0xFFFFFFFF;
2632 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
2633 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
2634 glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask);
2635 checkGLcall("glGetFloatv(GL_STENCIL_VALUE_MASK, &glParm);");
2637 ref = Value;
2638 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2639 glStencilFunc(glParm, ref, mask);
2640 checkGLcall("glStencilFunc");
2642 break;
2644 case D3DRS_STENCILMASK :
2646 int glParm = GL_ALWAYS;
2647 int ref = 0.0;
2648 GLuint mask = Value;
2650 glGetIntegerv(GL_STENCIL_REF, &ref);
2651 checkGLcall("glGetFloatv(GL_STENCIL_REF, &ref);");
2652 glGetIntegerv(GL_STENCIL_FUNC, &glParm);
2653 checkGLcall("glGetFloatv(GL_STENCIL_FUNC, &glParm);");
2655 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2656 glStencilFunc(glParm, ref, mask);
2657 checkGLcall("glStencilFunc");
2659 break;
2661 case D3DRS_STENCILFAIL :
2663 GLenum fail ;
2664 GLenum zpass ;
2665 GLenum zfail ;
2667 fail = StencilOp(Value);
2668 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2669 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2670 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2671 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2673 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2674 glStencilOp(fail, zfail, zpass);
2675 checkGLcall("glStencilOp(fail, zfail, zpass);");
2677 break;
2678 case D3DRS_STENCILZFAIL :
2680 GLenum fail ;
2681 GLenum zpass ;
2682 GLenum zfail ;
2684 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2685 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2686 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2687 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2688 zfail = StencilOp(Value);
2690 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2691 glStencilOp(fail, zfail, zpass);
2692 checkGLcall("glStencilOp(fail, zfail, zpass);");
2694 break;
2695 case D3DRS_STENCILPASS :
2697 GLenum fail ;
2698 GLenum zpass ;
2699 GLenum zfail ;
2701 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2702 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2703 zpass = StencilOp(Value);
2704 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2705 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2707 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2708 glStencilOp(fail, zfail, zpass);
2709 checkGLcall("glStencilOp(fail, zfail, zpass);");
2711 break;
2713 case D3DRS_STENCILWRITEMASK :
2715 glStencilMask(Value);
2716 TRACE("glStencilMask(%lu)\n", Value);
2717 checkGLcall("glStencilMask");
2719 break;
2721 case D3DRS_FOGENABLE :
2723 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2724 glEnable(GL_FOG);
2725 checkGLcall("glEnable GL_FOG\n");
2726 } else {
2727 glDisable(GL_FOG);
2728 checkGLcall("glDisable GL_FOG\n");
2731 break;
2733 case D3DRS_FOGCOLOR :
2735 float col[4];
2736 col[0] = ((Value >> 16) & 0xFF) / 255.0;
2737 col[1] = ((Value >> 8 ) & 0xFF) / 255.0;
2738 col[2] = ((Value >> 0 ) & 0xFF) / 255.0;
2739 col[3] = ((Value >> 24 ) & 0xFF) / 255.0;
2741 /* Set the default alpha blend color */
2742 glFogfv(GL_FOG_COLOR, &col[0]);
2743 checkGLcall("glFog GL_FOG_COLOR");
2745 break;
2747 case D3DRS_FOGSTART :
2749 float *f = (float *)&Value;
2750 glFogfv(GL_FOG_START, f);
2751 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2752 TRACE("Fog Start == %f\n", *f);
2754 break;
2756 case D3DRS_FOGEND :
2758 float *f = (float *)&Value;
2759 glFogfv(GL_FOG_END, f);
2760 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2761 TRACE("Fog End == %f\n", *f);
2763 break;
2765 case D3DRS_FOGDENSITY :
2767 glFogf(GL_FOG_DENSITY, (float) Value);
2768 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2770 break;
2772 case D3DRS_VERTEXBLEND :
2774 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2775 TRACE("Vertex Blending state to %ld\n", Value);
2777 break;
2779 case D3DRS_TWEENFACTOR :
2781 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2782 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2784 break;
2786 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2788 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2790 break;
2793 case D3DRS_COLORVERTEX :
2794 case D3DRS_DIFFUSEMATERIALSOURCE :
2795 case D3DRS_SPECULARMATERIALSOURCE :
2796 case D3DRS_AMBIENTMATERIALSOURCE :
2797 case D3DRS_EMISSIVEMATERIALSOURCE :
2799 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2801 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2802 glEnable(GL_COLOR_MATERIAL);
2803 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
2805 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2806 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2807 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2808 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2809 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2811 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2812 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2813 Parm = GL_AMBIENT_AND_DIFFUSE;
2814 } else {
2815 Parm = GL_DIFFUSE;
2817 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2818 Parm = GL_AMBIENT;
2819 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2820 Parm = GL_EMISSION;
2821 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2822 Parm = GL_SPECULAR;
2823 } else {
2824 Parm = -1;
2827 if (Parm == -1) {
2828 glDisable(GL_COLOR_MATERIAL);
2829 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
2830 } else {
2831 TRACE("glColorMaterial Parm=%d\n", Parm);
2832 glColorMaterial(GL_FRONT_AND_BACK, Parm);
2833 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
2836 } else {
2837 glDisable(GL_COLOR_MATERIAL);
2838 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
2841 break;
2843 /* Unhandled yet...! */
2844 case D3DRS_LINEPATTERN :
2845 case D3DRS_LASTPIXEL :
2846 case D3DRS_ZVISIBLE :
2847 case D3DRS_FOGTABLEMODE :
2848 case D3DRS_EDGEANTIALIAS :
2849 case D3DRS_ZBIAS :
2850 case D3DRS_RANGEFOGENABLE :
2851 case D3DRS_WRAP0 :
2852 case D3DRS_WRAP1 :
2853 case D3DRS_WRAP2 :
2854 case D3DRS_WRAP3 :
2855 case D3DRS_WRAP4 :
2856 case D3DRS_WRAP5 :
2857 case D3DRS_WRAP6 :
2858 case D3DRS_WRAP7 :
2859 case D3DRS_FOGVERTEXMODE :
2860 case D3DRS_LOCALVIEWER :
2861 case D3DRS_NORMALIZENORMALS :
2862 case D3DRS_SOFTWAREVERTEXPROCESSING :
2863 case D3DRS_POINTSIZE :
2864 case D3DRS_POINTSIZE_MIN :
2865 case D3DRS_POINTSPRITEENABLE :
2866 case D3DRS_POINTSCALEENABLE :
2867 case D3DRS_POINTSCALE_A :
2868 case D3DRS_POINTSCALE_B :
2869 case D3DRS_POINTSCALE_C :
2870 case D3DRS_MULTISAMPLEANTIALIAS :
2871 case D3DRS_MULTISAMPLEMASK :
2872 case D3DRS_PATCHEDGESTYLE :
2873 case D3DRS_PATCHSEGMENTS :
2874 case D3DRS_DEBUGMONITORTOKEN :
2875 case D3DRS_POINTSIZE_MAX :
2876 case D3DRS_COLORWRITEENABLE :
2877 case D3DRS_POSITIONORDER :
2878 case D3DRS_NORMALORDER :
2879 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2880 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2881 break;
2882 default:
2883 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2886 return D3D_OK;
2888 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2889 ICOM_THIS(IDirect3DDevice8Impl,iface);
2890 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2891 *pValue = This->StateBlock->renderstate[State];
2892 return D3D_OK;
2894 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2895 ICOM_THIS(IDirect3DDevice8Impl,iface);
2897 TRACE("(%p)\n", This);
2899 return IDirect3DDeviceImpl_BeginStateBlock(This);
2901 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2902 IDirect3DStateBlockImpl* pSB;
2903 ICOM_THIS(IDirect3DDevice8Impl,iface);
2904 HRESULT res;
2906 TRACE("(%p)\n", This);
2908 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2909 *pToken = (DWORD) pSB;
2910 return res;
2913 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2914 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2915 ICOM_THIS(IDirect3DDevice8Impl,iface);
2917 TRACE("(%p)\n", This);
2919 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2922 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2923 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2924 ICOM_THIS(IDirect3DDevice8Impl,iface);
2926 TRACE("(%p)\n", This);
2928 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2930 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2931 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2932 ICOM_THIS(IDirect3DDevice8Impl,iface);
2934 TRACE("(%p)\n", This);
2936 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2939 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2940 IDirect3DStateBlockImpl* pSB;
2941 ICOM_THIS(IDirect3DDevice8Impl,iface);
2942 HRESULT res;
2944 TRACE("(%p) : for type %d\n", This, Type);
2946 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
2947 *pToken = (DWORD) pSB;
2948 return res;
2951 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
2952 ICOM_THIS(IDirect3DDevice8Impl,iface);
2953 FIXME("(%p) : stub\n", This); return D3D_OK;
2955 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
2956 ICOM_THIS(IDirect3DDevice8Impl,iface);
2957 FIXME("(%p) : stub\n", This); return D3D_OK;
2959 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
2960 ICOM_THIS(IDirect3DDevice8Impl,iface);
2961 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
2962 *ppTexture = (LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage];
2963 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
2964 return D3D_OK;
2966 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8* pTexture) {
2968 IDirect3DBaseTexture8 *oldTxt;
2970 ICOM_THIS(IDirect3DDevice8Impl,iface);
2971 D3DRESOURCETYPE textureType;
2973 oldTxt = This->UpdateStateBlock->textures[Stage];
2974 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
2976 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
2977 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
2978 This->UpdateStateBlock->textures[Stage] = pTexture;
2980 /* Handle recording of state blocks */
2981 if (This->isRecordingState) {
2982 TRACE("Recording... not performing anything\n");
2983 return D3D_OK;
2986 /* Make appropriate texture active */
2987 if (This->isMultiTexture) {
2988 #if defined(GL_VERSION_1_3)
2989 glActiveTexture(GL_TEXTURE0 + Stage);
2990 #else
2991 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2992 #endif
2993 checkGLcall("glActiveTextureARB");
2994 } else if (Stage>0) {
2995 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2998 /* Decrement the count of the previous texture */
2999 /* FIXME PERF: If old == new and not dirty then skip all this */
3000 if (oldTxt != NULL) {
3001 IDirect3DBaseTexture8Impl_Release(oldTxt);
3004 if (pTexture) {
3005 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8)This->UpdateStateBlock->textures[Stage]);
3007 /* Now setup the texture appropraitly */
3008 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3010 if (textureType == D3DRTYPE_TEXTURE) {
3011 IDirect3DTexture8Impl *pTexture2 = (IDirect3DTexture8Impl *) pTexture;
3012 int i;
3014 /* Standard 2D texture */
3015 TRACE("Standard 2d texture\n");
3016 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3018 for (i=0; i<pTexture2->levels; i++)
3021 if (i==0 && pTexture2->surfaces[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3022 glBindTexture(GL_TEXTURE_2D, pTexture2->surfaces[i]->textureName);
3023 checkGLcall("glBindTexture");
3024 TRACE("Texture %p (level %d) given name %d\n", pTexture2->surfaces[i], i, pTexture2->surfaces[i]->textureName);
3025 /* No need to walk through all mip-map levels, since already all assigned */
3026 i = pTexture2->levels;
3028 } else {
3029 if (i==0) {
3031 if (pTexture2->surfaces[i]->textureName == 0) {
3032 glGenTextures(1, &pTexture2->surfaces[i]->textureName);
3033 checkGLcall("glGenTextures");
3034 TRACE("Texture %p (level %d) given name %d\n", pTexture2->surfaces[i], i, pTexture2->surfaces[i]->textureName);
3037 glBindTexture(GL_TEXTURE_2D, pTexture2->surfaces[i]->textureName);
3038 checkGLcall("glBindTexture");
3040 TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", pTexture2->levels-1);
3041 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1);
3042 checkGLcall("glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels)");
3045 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3046 GL_TEXTURE_2D, i, fmt2glintFmt(pTexture2->format), pTexture2->surfaces[i]->myDesc.Width,
3047 pTexture2->surfaces[i]->myDesc.Height, 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3048 pTexture2->surfaces[i]->allocatedMemory);
3049 glTexImage2D(GL_TEXTURE_2D, i,
3050 fmt2glintFmt(pTexture2->format),
3051 pTexture2->surfaces[i]->myDesc.Width,
3052 pTexture2->surfaces[i]->myDesc.Height,
3054 fmt2glFmt(pTexture2->format),
3055 fmt2glType(pTexture2->format),
3056 pTexture2->surfaces[i]->allocatedMemory
3058 checkGLcall("glTexImage2D");
3060 /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3061 pTexture2->Dirty = FALSE;
3066 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3067 IDirect3DVolumeTexture8Impl *pTexture2 = (IDirect3DVolumeTexture8Impl *) pTexture;
3068 int i;
3070 /* Standard 3D (volume) texture */
3071 TRACE("Standard 3d texture\n");
3072 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3074 for (i=0; i<pTexture2->levels; i++)
3077 if (i==0 && pTexture2->volumes[i]->textureName != 0 && pTexture2->Dirty == FALSE) {
3078 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3079 checkGLcall("glBindTexture");
3080 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3082 /* No need to walk through all mip-map levels, since already all assigned */
3083 i = pTexture2->levels;
3084 } else {
3085 if (i==0) {
3087 if (pTexture2->volumes[i]->textureName == 0) {
3088 glGenTextures(1, &pTexture2->volumes[i]->textureName);
3089 checkGLcall("glGenTextures");
3090 TRACE("Texture %p given name %d\n", pTexture2->volumes[i], pTexture2->volumes[i]->textureName);
3093 glBindTexture(GL_TEXTURE_3D, pTexture2->volumes[i]->textureName);
3094 checkGLcall("glBindTexture");
3096 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1);
3097 checkGLcall("glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, pTexture2->levels-1)");
3100 TRACE("Calling glTexImage3D %x i=%d, intfmt=%x, w=%d, h=%d,d=%d, 0=%d, glFmt=%x, glType=%lx, Mem=%p\n",
3101 GL_TEXTURE_3D, i, fmt2glintFmt(pTexture2->format), pTexture2->volumes[i]->myDesc.Width,
3102 pTexture2->volumes[i]->myDesc.Height, pTexture2->volumes[i]->myDesc.Depth,
3103 0, fmt2glFmt(pTexture2->format),fmt2glType(pTexture2->format),
3104 pTexture2->volumes[i]->allocatedMemory);
3105 glTexImage3D(GL_TEXTURE_3D, i,
3106 fmt2glintFmt(pTexture2->format),
3107 pTexture2->volumes[i]->myDesc.Width,
3108 pTexture2->volumes[i]->myDesc.Height,
3109 pTexture2->volumes[i]->myDesc.Depth,
3111 fmt2glFmt(pTexture2->format),
3112 fmt2glType(pTexture2->format),
3113 pTexture2->volumes[i]->allocatedMemory
3115 checkGLcall("glTexImage3D");
3117 /* Removed glTexParameterf now TextureStageStates are initialized at startup */
3118 pTexture2->Dirty = FALSE;
3122 } else {
3123 FIXME("(%p) : Incorrect type for a texture : %d\n", This, textureType);
3125 } else {
3126 TRACE("Setting to no texture (ie default texture)\n");
3127 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3128 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3129 checkGLcall("glBindTexture");
3130 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3133 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3134 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3135 setupTextureStates (iface, Stage);
3137 return D3D_OK;
3140 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3141 ICOM_THIS(IDirect3DDevice8Impl,iface);
3142 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3143 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3144 return D3D_OK;
3147 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) {
3148 ICOM_THIS(IDirect3DDevice8Impl,iface);
3150 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3152 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value);
3154 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3155 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3156 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3158 /* Handle recording of state blocks */
3159 if (This->isRecordingState) {
3160 TRACE("Recording... not performing anything\n");
3161 return D3D_OK;
3164 /* Make appropriate texture active */
3165 TRACE("Activating appropriate texture state %ld\n", Stage);
3166 if (This->isMultiTexture) {
3167 #if defined(GL_VERSION_1_3)
3168 glActiveTexture(GL_TEXTURE0 + Stage);
3169 checkGLcall("glActiveTexture");
3170 #else
3171 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3172 checkGLcall("glActiveTextureARB");
3173 #endif
3175 } else if (Stage>0) {
3176 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3179 switch (Type) {
3181 case D3DTSS_MINFILTER :
3182 case D3DTSS_MIPFILTER :
3184 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3185 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3186 GLint realVal = GL_LINEAR;
3188 if (ValueMIN == D3DTEXF_POINT) {
3189 /* GL_NEAREST_* */
3190 if (ValueMIP == D3DTEXF_POINT) {
3191 realVal = GL_NEAREST_MIPMAP_NEAREST;
3192 } else if (ValueMIP == D3DTEXF_LINEAR) {
3193 realVal = GL_NEAREST_MIPMAP_LINEAR;
3194 } else if (ValueMIP == D3DTEXF_NONE) {
3195 realVal = GL_NEAREST;
3196 } else {
3197 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3198 realVal = GL_NEAREST_MIPMAP_LINEAR;
3200 } else if (ValueMIN == D3DTEXF_LINEAR) {
3201 /* GL_LINEAR_* */
3202 if (ValueMIP == D3DTEXF_POINT) {
3203 realVal = GL_LINEAR_MIPMAP_NEAREST;
3204 } else if (ValueMIP == D3DTEXF_LINEAR) {
3205 realVal = GL_LINEAR_MIPMAP_LINEAR;
3206 } else if (ValueMIP == D3DTEXF_NONE) {
3207 realVal = GL_LINEAR;
3208 } else {
3209 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3210 realVal = GL_LINEAR_MIPMAP_LINEAR;
3212 } else if (ValueMIN == D3DTEXF_NONE) {
3213 /* Doesnt really make sense - Windows just seems to disable
3214 mipmapping when this occurs */
3215 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3216 realVal = GL_LINEAR;
3218 } else {
3219 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3220 realVal = GL_LINEAR_MIPMAP_LINEAR;
3223 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3224 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3225 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3227 break;
3230 case D3DTSS_MAGFILTER :
3231 if (Value == D3DTEXF_POINT) {
3232 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3233 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3234 } else if (Value == D3DTEXF_LINEAR) {
3235 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3236 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3237 } else {
3238 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3240 break;
3242 case D3DTSS_COLORARG0 :
3243 case D3DTSS_ALPHAARG0 :
3244 /* FIXME: Mesa seems to struggle setting these at the moment */
3245 break;
3247 case D3DTSS_COLORARG1 :
3248 case D3DTSS_COLORARG2 :
3249 case D3DTSS_ALPHAARG1 :
3250 case D3DTSS_ALPHAARG2 :
3252 BOOL isAlphaReplicate = FALSE;
3253 BOOL isComplement = FALSE;
3254 BOOL isAlphaArg = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3255 int operand= GL_SRC_COLOR;
3256 int source = GL_TEXTURE;
3258 /* Catch alpha replicate */
3259 if (Value & D3DTA_ALPHAREPLICATE) {
3260 Value = Value & ~D3DTA_ALPHAREPLICATE;
3261 isAlphaReplicate = TRUE;
3264 /* Catch Complement */
3265 if (Value & D3DTA_COMPLEMENT) {
3266 Value = Value & ~D3DTA_COMPLEMENT;
3267 isComplement = TRUE;
3270 /* Calculate the operand */
3271 if (isAlphaReplicate && !isComplement) {
3272 operand = GL_SRC_ALPHA;
3273 } else if (isAlphaReplicate && isComplement) {
3274 operand = GL_ONE_MINUS_SRC_ALPHA;
3275 } else if (isComplement) {
3276 if (isAlphaArg) {
3277 operand = GL_ONE_MINUS_SRC_ALPHA;
3278 } else {
3279 operand = GL_ONE_MINUS_SRC_COLOR;
3281 } else {
3282 if (isAlphaArg) {
3283 operand = GL_SRC_ALPHA;
3284 } else {
3285 operand = GL_SRC_COLOR;
3289 /* Calculate the source */
3290 switch (Value) {
3291 case D3DTA_CURRENT: source = GL_PREVIOUS_EXT;
3292 break;
3293 case D3DTA_DIFFUSE: source = GL_PRIMARY_COLOR_EXT;
3294 break;
3295 case D3DTA_TEXTURE: source = GL_TEXTURE;
3296 break;
3297 case D3DTA_TFACTOR: source = GL_CONSTANT_EXT;
3298 break;
3300 /* According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
3301 isnt supported until base GL supports it
3302 There is no concept of temp registers as far as I can tell */
3304 default:
3305 FIXME("Unrecognized or unhandled texture arg %ld\n", Value);
3308 if (isAlphaArg) {
3309 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
3310 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
3311 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
3312 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
3313 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
3314 } else {
3315 TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
3316 glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
3317 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
3318 glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
3319 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
3322 break;
3324 case D3DTSS_ALPHAOP :
3325 case D3DTSS_COLOROP :
3328 int Scale = 1;
3329 int Parm = (Type == D3DTSS_ALPHAOP)? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
3331 if (Type==D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
3332 /* TODO: Disable by making this and all later levels disabled */
3333 glDisable(GL_TEXTURE_1D);
3334 checkGLcall("Disable GL_TEXTURE_1D");
3335 glDisable(GL_TEXTURE_2D);
3336 checkGLcall("Disable GL_TEXTURE_2D");
3337 glDisable(GL_TEXTURE_3D);
3338 checkGLcall("Disable GL_TEXTURE_3D");
3339 } else {
3341 /* Enable only the appropriate texture dimension */
3342 if (Type==D3DTSS_COLOROP) {
3343 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3344 glEnable(GL_TEXTURE_1D);
3345 checkGLcall("Enable GL_TEXTURE_1D");
3346 } else {
3347 glDisable(GL_TEXTURE_1D);
3348 checkGLcall("Disable GL_TEXTURE_1D");
3350 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3351 glEnable(GL_TEXTURE_2D);
3352 checkGLcall("Enable GL_TEXTURE_2D");
3353 } else {
3354 glDisable(GL_TEXTURE_2D);
3355 checkGLcall("Disable GL_TEXTURE_2D");
3357 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3358 glEnable(GL_TEXTURE_3D);
3359 checkGLcall("Enable GL_TEXTURE_3D");
3360 } else {
3361 glDisable(GL_TEXTURE_3D);
3362 checkGLcall("Disable GL_TEXTURE_3D");
3366 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
3367 if (Value != D3DTOP_DISABLE) {
3368 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3371 /* Now set up the operand correctly */
3372 switch (Value) {
3373 case D3DTOP_DISABLE :
3374 /* Contrary to the docs, alpha can be disabled when colorop is enabled
3375 and it works, so ignore this op */
3376 TRACE("Disable ALPHAOP but COLOROP enabled!\n");
3377 break;
3379 case D3DTOP_SELECTARG1 :
3380 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
3381 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
3382 break;
3384 case D3DTOP_MODULATE4X : Scale = Scale * 2; /* Drop through */
3385 case D3DTOP_MODULATE2X : Scale = Scale * 2; /* Drop through */
3386 case D3DTOP_MODULATE :
3388 /* Correct scale */
3389 if (Type == D3DTSS_ALPHAOP) {
3390 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
3391 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
3392 } else {
3393 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
3394 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
3396 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
3397 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
3398 break;
3400 case D3DTOP_ADD :
3401 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
3402 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
3403 break;
3405 case D3DTOP_ADDSIGNED2X : Scale = Scale * 2; /* Drop through */
3406 case D3DTOP_ADDSIGNED :
3407 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
3408 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
3409 break;
3411 case D3DTOP_DOTPRODUCT3 :
3412 if (This->isDot3) {
3413 glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
3414 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
3415 } else {
3416 FIXME("DotProduct3 extension requested but not supported via this version of opengl\n");
3418 break;
3420 case D3DTOP_SUBTRACT :
3421 /* glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT); Missing? */
3422 case D3DTOP_SELECTARG2 :
3423 /* GL_REPLACE, swap args 0 and 1? */
3424 case D3DTOP_ADDSMOOTH :
3425 case D3DTOP_BLENDDIFFUSEALPHA :
3426 case D3DTOP_BLENDTEXTUREALPHA :
3427 case D3DTOP_BLENDFACTORALPHA :
3428 case D3DTOP_BLENDTEXTUREALPHAPM :
3429 case D3DTOP_BLENDCURRENTALPHA :
3430 case D3DTOP_PREMODULATE :
3431 case D3DTOP_MODULATEALPHA_ADDCOLOR :
3432 case D3DTOP_MODULATECOLOR_ADDALPHA :
3433 case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
3434 case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
3435 case D3DTOP_BUMPENVMAP :
3436 case D3DTOP_BUMPENVMAPLUMINANCE :
3437 case D3DTOP_MULTIPLYADD :
3438 case D3DTOP_LERP :
3439 default:
3440 FIXME("Unhandled texture operation %ld\n", Value);
3443 break;
3446 case D3DTSS_ADDRESSU :
3447 case D3DTSS_ADDRESSV :
3448 case D3DTSS_ADDRESSW :
3450 GLint wrapParm = GL_REPEAT;
3451 switch (Value) {
3452 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3453 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3454 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3455 #if defined(GL_VERSION_1_3)
3456 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3457 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL but pretent mirror */
3458 #else
3459 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3460 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3461 #endif
3462 default:
3463 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3464 wrapParm = GL_REPEAT;
3467 switch (Type) {
3468 case D3DTSS_ADDRESSU:
3469 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3470 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3471 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3472 break;
3473 case D3DTSS_ADDRESSV:
3474 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3475 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3476 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3477 break;
3478 case D3DTSS_ADDRESSW:
3479 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3480 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3481 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3482 break;
3483 default: /* nop */
3484 break; /** stupic compilator */
3487 break;
3489 case D3DTSS_BORDERCOLOR :
3491 float col[4];
3492 col[0] = ((Value >> 16) & 0xFF) / 255.0;
3493 col[1] = ((Value >> 8) & 0xFF) / 255.0;
3494 col[2] = ((Value >> 0) & 0xFF) / 255.0;
3495 col[3] = ((Value >> 24) & 0xFF) / 255.0;
3497 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3498 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3499 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3501 break;
3503 /* Unhandled */
3504 case D3DTSS_BUMPENVMAT00 :
3505 case D3DTSS_BUMPENVMAT01 :
3506 case D3DTSS_BUMPENVMAT10 :
3507 case D3DTSS_BUMPENVMAT11 :
3508 case D3DTSS_TEXCOORDINDEX :
3509 case D3DTSS_MIPMAPLODBIAS :
3510 case D3DTSS_MAXMIPLEVEL :
3511 case D3DTSS_MAXANISOTROPY :
3512 case D3DTSS_BUMPENVLSCALE :
3513 case D3DTSS_BUMPENVLOFFSET :
3514 case D3DTSS_TEXTURETRANSFORMFLAGS :
3515 case D3DTSS_RESULTARG :
3516 default:
3517 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3518 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3520 return D3D_OK;
3522 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3523 ICOM_THIS(IDirect3DDevice8Impl,iface);
3524 FIXME("(%p) : stub\n", This); return D3D_OK;
3526 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID,void* pDevInfoStruct,DWORD DevInfoStructSize) {
3527 ICOM_THIS(IDirect3DDevice8Impl,iface);
3528 FIXME("(%p) : stub\n", This); return D3D_OK;
3530 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,CONST PALETTEENTRY* pEntries) {
3531 ICOM_THIS(IDirect3DDevice8Impl,iface);
3532 FIXME("(%p) : stub\n", This); return D3D_OK;
3534 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber,PALETTEENTRY* pEntries) {
3535 ICOM_THIS(IDirect3DDevice8Impl,iface);
3536 FIXME("(%p) : stub\n", This); return D3D_OK;
3538 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3539 ICOM_THIS(IDirect3DDevice8Impl,iface);
3540 FIXME("(%p) : stub\n", This); return D3D_OK;
3542 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3543 ICOM_THIS(IDirect3DDevice8Impl,iface);
3544 FIXME("(%p) : stub\n", This); return D3D_OK;
3546 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) {
3548 IDirect3DVertexBuffer8 *pVB;
3550 ICOM_THIS(IDirect3DDevice8Impl,iface);
3551 pVB = This->StateBlock->stream_source[0];
3553 TRACE("(%p) : Type=%d, Start=%d, Count=%d\n", This, PrimitiveType, StartVertex, PrimitiveCount);
3555 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE,
3556 This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory, StartVertex, -1, 0, NULL, 0);
3558 return D3D_OK;
3560 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3561 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3562 UINT idxStride = 2;
3563 IDirect3DIndexBuffer8 *pIB;
3564 IDirect3DVertexBuffer8 *pVB;
3565 D3DINDEXBUFFER_DESC IdxBufDsc;
3567 ICOM_THIS(IDirect3DDevice8Impl,iface);
3568 pIB = This->StateBlock->pIndexData;
3569 pVB = This->StateBlock->stream_source[0];
3571 TRACE("(%p) : Type=%d, min=%d, CountV=%d, startIdx=%d, countP=%d \n", This, PrimitiveType,
3572 minIndex, NumVertices, startIndex, primCount);
3574 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3575 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3576 idxStride = 2;
3577 } else {
3578 idxStride = 4;
3581 DrawPrimitiveI(iface, PrimitiveType, primCount, TRUE, This->StateBlock->VertexShader, ((IDirect3DVertexBuffer8Impl *)pVB)->allocatedMemory,
3582 This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3583 minIndex);
3585 return D3D_OK;
3587 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3588 ICOM_THIS(IDirect3DDevice8Impl,iface);
3590 TRACE("(%p) : Type=%d, pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3592 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3594 This->StateBlock->stream_source[0] = NULL;
3595 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3596 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, FALSE, This->StateBlock->VertexShader, pVertexStreamZeroData,
3597 0, 0, 0, NULL, 0);
3598 This->StateBlock->stream_stride[0] = 0;
3600 /*stream zero settings set to null at end */
3601 return D3D_OK;
3603 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3604 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3605 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3606 UINT VertexStreamZeroStride) {
3607 int idxStride;
3608 ICOM_THIS(IDirect3DDevice8Impl,iface);
3609 TRACE("(%p) : Type=%d, MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType,
3610 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3612 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3613 if (IndexDataFormat == D3DFMT_INDEX16) {
3614 idxStride = 2;
3615 } else {
3616 idxStride = 4;
3619 This->StateBlock->stream_source[0] = NULL;
3620 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3621 DrawPrimitiveI(iface, PrimitiveType, PrimitiveCount, TRUE, This->StateBlock->VertexShader, pVertexStreamZeroData,
3622 This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3624 /*stream zero settings set to null at end */
3625 This->StateBlock->stream_stride[0] = 0;
3626 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3628 return D3D_OK;
3630 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3631 ICOM_THIS(IDirect3DDevice8Impl,iface);
3632 FIXME("(%p) : stub\n", This); return D3D_OK;
3634 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3635 ICOM_THIS(IDirect3DDevice8Impl,iface);
3636 IDirect3DVertexShaderImpl* object;
3637 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3638 HRESULT res;
3639 UINT i;
3641 TRACE("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
3642 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3643 return D3DERR_INVALIDCALL;
3645 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3646 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3647 return D3DERR_OUTOFVIDEOMEMORY;
3650 /** Create the Vertex Shader */
3651 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3652 /** TODO: check FAILED(res) */
3654 /** Create and Bind the Vertex Shader Declaration */
3655 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3656 /** TODO: check FAILED(res) */
3658 VertexShaders[i] = object;
3659 VertexShaderDeclarations[i] = attached_decl;
3660 *pHandle = VS_HIGHESTFIXEDFXF + i;
3662 return D3D_OK;
3664 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3665 ICOM_THIS(IDirect3DDevice8Impl,iface);
3667 This->UpdateStateBlock->VertexShader = Handle;
3668 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3669 This->UpdateStateBlock->Set.vertexShader = TRUE;
3671 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3672 FIXME("(%p) : Created shader, Handle=%lx\n", This, Handle);
3673 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3674 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3675 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3676 } else { /* use a fvf, so desactivate the vshader decl */
3677 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3678 This->UpdateStateBlock->vertexShaderDecl = NULL;
3679 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3680 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3682 /* Handle recording of state blocks */
3683 if (This->isRecordingState) {
3684 TRACE("Recording... not performing anything\n");
3685 return D3D_OK;
3688 * TODO: merge HAL shaders context switching from prototype
3690 return D3D_OK;
3692 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3693 ICOM_THIS(IDirect3DDevice8Impl,iface);
3694 TRACE("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3695 *pHandle = This->StateBlock->VertexShader;
3696 return D3D_OK;
3699 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3700 ICOM_THIS(IDirect3DDevice8Impl,iface);
3701 IDirect3DVertexShaderImpl* object;
3702 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3704 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3705 return D3DERR_INVALIDCALL;
3709 * Delete Vertex Shader
3711 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3712 if (NULL == object) {
3713 return D3DERR_INVALIDCALL;
3715 FIXME("(%p) : freing VertexShader %p\n", This, object);
3716 /* TODO: check validity of object */
3717 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3718 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3719 HeapFree(GetProcessHeap(), 0, (void *)object);
3720 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3723 * Delete Vertex Shader Declaration
3725 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3726 if (NULL == attached_decl) {
3727 return D3DERR_INVALIDCALL;
3729 FIXME("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3730 /* TODO: check validity of object */
3731 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3732 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3733 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3735 return D3D_OK;
3738 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3739 ICOM_THIS(IDirect3DDevice8Impl,iface);
3741 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3742 /*ERR("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);*/
3743 return D3DERR_INVALIDCALL;
3745 if (NULL == pConstantData) {
3746 return D3DERR_INVALIDCALL;
3748 if (ConstantCount > 1) {
3749 FLOAT* f = (FLOAT*)pConstantData;
3750 UINT i;
3751 FIXME("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3752 for (i = 0; i < ConstantCount; ++i) {
3753 DPRINTF("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3754 f += 4;
3756 } else {
3757 FLOAT* f = (FLOAT*)pConstantData;
3758 FIXME("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3760 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3761 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3762 return D3D_OK;
3764 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3765 ICOM_THIS(IDirect3DDevice8Impl,iface);
3767 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3768 return D3DERR_INVALIDCALL;
3770 if (NULL == pConstantData) {
3771 return D3DERR_INVALIDCALL;
3773 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3774 return D3D_OK;
3776 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3777 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3778 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3780 attached_decl = VERTEX_SHADER_DECL(Handle);
3781 if (NULL == attached_decl) {
3782 return D3DERR_INVALIDCALL;
3784 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3786 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3787 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3788 IDirect3DVertexShaderImpl* object;
3790 object = VERTEX_SHADER(Handle);
3791 if (NULL == object) {
3792 return D3DERR_INVALIDCALL;
3794 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3797 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3798 ICOM_THIS(IDirect3DDevice8Impl,iface);
3799 IDirect3DIndexBuffer8 *oldIdxs;
3801 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3802 oldIdxs = This->StateBlock->pIndexData;
3804 This->UpdateStateBlock->Changed.Indices = TRUE;
3805 This->UpdateStateBlock->Set.Indices = TRUE;
3806 This->UpdateStateBlock->pIndexData = pIndexData;
3807 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3809 /* Handle recording of state blocks */
3810 if (This->isRecordingState) {
3811 TRACE("Recording... not performing anything\n");
3812 return D3D_OK;
3815 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3816 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3817 return D3D_OK;
3819 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3820 ICOM_THIS(IDirect3DDevice8Impl,iface);
3821 FIXME("(%p) : stub\n", This);
3823 *ppIndexData = This->StateBlock->pIndexData;
3824 /* up ref count on ppindexdata */
3825 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3826 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3828 return D3D_OK;
3830 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3831 ICOM_THIS(IDirect3DDevice8Impl,iface);
3832 IDirect3DPixelShaderImpl* object;
3833 UINT i;
3835 FIXME("(%p) : PixelShader not fully supported yet\n", This);
3836 if (NULL == pFunction || NULL == pHandle) {
3837 return D3DERR_INVALIDCALL;
3839 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3840 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3841 return D3DERR_OUTOFVIDEOMEMORY;
3843 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DPixelShaderImpl));
3844 if (NULL == object) {
3845 return D3DERR_OUTOFVIDEOMEMORY;
3848 object->data = NULL; /* TODO */
3850 PixelShaders[i] = object;
3851 *pHandle = VS_HIGHESTFIXEDFXF + i;
3853 object->function = pFunction;
3854 for (i = 0; 0xFFFFFFFF != pFunction[i]; ++i) ;
3855 object->functionLength = i + 1;
3857 return D3D_OK;
3859 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3860 ICOM_THIS(IDirect3DDevice8Impl,iface);
3862 This->UpdateStateBlock->PixelShader = Handle;
3863 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3864 This->UpdateStateBlock->Set.pixelShader = TRUE;
3866 /* Handle recording of state blocks */
3867 if (This->isRecordingState) {
3868 TRACE("Recording... not performing anything\n");
3869 return D3D_OK;
3872 /* FIXME: Quieten when not being used */
3873 if (Handle != 0) {
3874 FIXME("(%p) : stub %ld\n", This, Handle);
3875 } else {
3876 TRACE("(%p) : stub %ld\n", This, Handle);
3879 return D3D_OK;
3881 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3882 ICOM_THIS(IDirect3DDevice8Impl,iface);
3883 TRACE("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3884 *pHandle = This->StateBlock->PixelShader;
3885 return D3D_OK;
3888 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3889 ICOM_THIS(IDirect3DDevice8Impl,iface);
3890 IDirect3DPixelShaderImpl* object;
3892 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3893 return D3DERR_INVALIDCALL;
3895 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3896 TRACE("(%p) : freeing PixelShader %p\n", This, object);
3897 /* TODO: check validity of object before free */
3898 HeapFree(GetProcessHeap(), 0, (void *)object);
3899 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = 0;
3900 return D3D_OK;
3903 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,CONST void* pConstantData, DWORD ConstantCount) {
3904 ICOM_THIS(IDirect3DDevice8Impl,iface);
3905 FIXME("(%p) : stub\n", This);
3906 return D3D_OK;
3908 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register,void* pConstantData, DWORD ConstantCount) {
3909 ICOM_THIS(IDirect3DDevice8Impl,iface);
3910 FIXME("(%p) : stub\n", This);
3911 return D3D_OK;
3913 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3914 ICOM_THIS(IDirect3DDevice8Impl,iface);
3915 IDirect3DPixelShaderImpl* object;
3917 object = PIXEL_SHADER(Handle);
3918 if (NULL == object) {
3919 return D3DERR_INVALIDCALL;
3921 if (NULL == pData) {
3922 *pSizeOfData = object->functionLength;
3923 return D3D_OK;
3925 if (*pSizeOfData < object->functionLength) {
3926 *pSizeOfData = object->functionLength;
3927 return D3DERR_MOREDATA;
3929 TRACE("(%p) : GetPixelShaderFunction copying to %p\n", This, pData);
3930 memcpy(pData, object->function, object->functionLength);
3931 return D3D_OK;
3933 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
3934 ICOM_THIS(IDirect3DDevice8Impl,iface);
3935 FIXME("(%p) : stub\n", This); return D3D_OK;
3937 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
3938 ICOM_THIS(IDirect3DDevice8Impl,iface);
3939 FIXME("(%p) : stub\n", This); return D3D_OK;
3941 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
3942 ICOM_THIS(IDirect3DDevice8Impl,iface);
3943 FIXME("(%p) : stub\n", This); return D3D_OK;
3946 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
3947 IDirect3DVertexBuffer8 *oldSrc;
3948 ICOM_THIS(IDirect3DDevice8Impl,iface);
3950 oldSrc = This->StateBlock->stream_source[StreamNumber];
3951 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
3953 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
3954 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
3955 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
3956 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
3958 /* Handle recording of state blocks */
3959 if (This->isRecordingState) {
3960 TRACE("Recording... not performing anything\n");
3961 return D3D_OK;
3964 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
3965 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
3966 return D3D_OK;
3968 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
3969 ICOM_THIS(IDirect3DDevice8Impl,iface);
3970 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
3971 *pStream = This->StateBlock->stream_source[StreamNumber];
3972 *pStride = This->StateBlock->stream_stride[StreamNumber];
3973 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
3974 return D3D_OK;
3978 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
3980 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3981 IDirect3DDevice8Impl_QueryInterface,
3982 IDirect3DDevice8Impl_AddRef,
3983 IDirect3DDevice8Impl_Release,
3984 IDirect3DDevice8Impl_TestCooperativeLevel,
3985 IDirect3DDevice8Impl_GetAvailableTextureMem,
3986 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
3987 IDirect3DDevice8Impl_GetDirect3D,
3988 IDirect3DDevice8Impl_GetDeviceCaps,
3989 IDirect3DDevice8Impl_GetDisplayMode,
3990 IDirect3DDevice8Impl_GetCreationParameters,
3991 IDirect3DDevice8Impl_SetCursorProperties,
3992 IDirect3DDevice8Impl_SetCursorPosition,
3993 IDirect3DDevice8Impl_ShowCursor,
3994 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
3995 IDirect3DDevice8Impl_Reset,
3996 IDirect3DDevice8Impl_Present,
3997 IDirect3DDevice8Impl_GetBackBuffer,
3998 IDirect3DDevice8Impl_GetRasterStatus,
3999 IDirect3DDevice8Impl_SetGammaRamp,
4000 IDirect3DDevice8Impl_GetGammaRamp,
4001 IDirect3DDevice8Impl_CreateTexture,
4002 IDirect3DDevice8Impl_CreateVolumeTexture,
4003 IDirect3DDevice8Impl_CreateCubeTexture,
4004 IDirect3DDevice8Impl_CreateVertexBuffer,
4005 IDirect3DDevice8Impl_CreateIndexBuffer,
4006 IDirect3DDevice8Impl_CreateRenderTarget,
4007 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4008 IDirect3DDevice8Impl_CreateImageSurface,
4009 IDirect3DDevice8Impl_CopyRects,
4010 IDirect3DDevice8Impl_UpdateTexture,
4011 IDirect3DDevice8Impl_GetFrontBuffer,
4012 IDirect3DDevice8Impl_SetRenderTarget,
4013 IDirect3DDevice8Impl_GetRenderTarget,
4014 IDirect3DDevice8Impl_GetDepthStencilSurface,
4015 IDirect3DDevice8Impl_BeginScene,
4016 IDirect3DDevice8Impl_EndScene,
4017 IDirect3DDevice8Impl_Clear,
4018 IDirect3DDevice8Impl_SetTransform,
4019 IDirect3DDevice8Impl_GetTransform,
4020 IDirect3DDevice8Impl_MultiplyTransform,
4021 IDirect3DDevice8Impl_SetViewport,
4022 IDirect3DDevice8Impl_GetViewport,
4023 IDirect3DDevice8Impl_SetMaterial,
4024 IDirect3DDevice8Impl_GetMaterial,
4025 IDirect3DDevice8Impl_SetLight,
4026 IDirect3DDevice8Impl_GetLight,
4027 IDirect3DDevice8Impl_LightEnable,
4028 IDirect3DDevice8Impl_GetLightEnable,
4029 IDirect3DDevice8Impl_SetClipPlane,
4030 IDirect3DDevice8Impl_GetClipPlane,
4031 IDirect3DDevice8Impl_SetRenderState,
4032 IDirect3DDevice8Impl_GetRenderState,
4033 IDirect3DDevice8Impl_BeginStateBlock,
4034 IDirect3DDevice8Impl_EndStateBlock,
4035 IDirect3DDevice8Impl_ApplyStateBlock,
4036 IDirect3DDevice8Impl_CaptureStateBlock,
4037 IDirect3DDevice8Impl_DeleteStateBlock,
4038 IDirect3DDevice8Impl_CreateStateBlock,
4039 IDirect3DDevice8Impl_SetClipStatus,
4040 IDirect3DDevice8Impl_GetClipStatus,
4041 IDirect3DDevice8Impl_GetTexture,
4042 IDirect3DDevice8Impl_SetTexture,
4043 IDirect3DDevice8Impl_GetTextureStageState,
4044 IDirect3DDevice8Impl_SetTextureStageState,
4045 IDirect3DDevice8Impl_ValidateDevice,
4046 IDirect3DDevice8Impl_GetInfo,
4047 IDirect3DDevice8Impl_SetPaletteEntries,
4048 IDirect3DDevice8Impl_GetPaletteEntries,
4049 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4050 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4051 IDirect3DDevice8Impl_DrawPrimitive,
4052 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4053 IDirect3DDevice8Impl_DrawPrimitiveUP,
4054 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4055 IDirect3DDevice8Impl_ProcessVertices,
4056 IDirect3DDevice8Impl_CreateVertexShader,
4057 IDirect3DDevice8Impl_SetVertexShader,
4058 IDirect3DDevice8Impl_GetVertexShader,
4059 IDirect3DDevice8Impl_DeleteVertexShader,
4060 IDirect3DDevice8Impl_SetVertexShaderConstant,
4061 IDirect3DDevice8Impl_GetVertexShaderConstant,
4062 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4063 IDirect3DDevice8Impl_GetVertexShaderFunction,
4064 IDirect3DDevice8Impl_SetStreamSource,
4065 IDirect3DDevice8Impl_GetStreamSource,
4066 IDirect3DDevice8Impl_SetIndices,
4067 IDirect3DDevice8Impl_GetIndices,
4068 IDirect3DDevice8Impl_CreatePixelShader,
4069 IDirect3DDevice8Impl_SetPixelShader,
4070 IDirect3DDevice8Impl_GetPixelShader,
4071 IDirect3DDevice8Impl_DeletePixelShader,
4072 IDirect3DDevice8Impl_SetPixelShaderConstant,
4073 IDirect3DDevice8Impl_GetPixelShaderConstant,
4074 IDirect3DDevice8Impl_GetPixelShaderFunction,
4075 IDirect3DDevice8Impl_DrawRectPatch,
4076 IDirect3DDevice8Impl_DrawTriPatch,
4077 IDirect3DDevice8Impl_DeletePatch