Minor fixes - Remove light debug statements, handle disabled specular
[wine.git] / dlls / d3d8 / device.c
blob2e4f15bdc75dbd1f1fdaf9d150a557682cc91de4
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>
24 #include <stdarg.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
34 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
35 /*#define GL_GLEXT_PROTOTYPES*/
36 /*#undef GLX_GLXEXT_LEGACY*/
37 #include "d3d8_private.h"
39 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
40 #undef GL_VERSION_1_4
42 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
43 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
44 WINE_DECLARE_DEBUG_CHANNEL(fps);
46 IDirect3DVertexShaderImpl* VertexShaders[64];
47 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
48 IDirect3DPixelShaderImpl* PixelShaders[64];
50 /* Debugging aids: */
51 #ifdef FRAME_DEBUGGING
52 BOOL isOn = FALSE;
53 BOOL isDumpingFrames = FALSE;
54 LONG primCounter = 0;
55 #endif
58 * Utility functions or macros
60 #define conv_mat(mat,gl_mat) \
61 do { \
62 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
63 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
64 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
65 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
66 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
67 } while (0)
69 /* Apply the current values to the specified texture stage */
70 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
71 ICOM_THIS(IDirect3DDevice8Impl,iface);
72 int i = 0;
73 float col[4];
74 BOOL changeTexture = TRUE;
76 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
77 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
79 BOOL skip = FALSE;
81 switch (i) {
82 /* Performance: For texture states where multiples effect the outcome, only bother
83 applying the last one as it will pick up all the other values */
84 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
85 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
86 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
87 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
88 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
89 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
90 skip = TRUE;
91 break;
93 /* Performance: If the texture states only impact settings for the texture unit
94 (compared to the texture object) then there is no need to reapply them. The
95 only time they need applying is the first time, since we cheat and put the
96 values into the stateblock without applying.
97 Per-texture unit: texture function (eg. combine), ops and args
98 texture env color
99 texture generation settings
100 Note: Due to some special conditions there may be a need to do particular ones
101 of these, which is what the Flags allows */
102 case D3DTSS_COLOROP:
103 case D3DTSS_TEXCOORDINDEX:
104 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
105 break;
107 case D3DTSS_ALPHAOP:
108 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
109 break;
111 default:
112 skip = FALSE;
115 if (skip == FALSE) {
116 /* Performance: Only change to this texture if we have to */
117 if (changeTexture) {
118 /* Make appropriate texture active */
119 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
120 #if defined(GL_VERSION_1_3)
121 glActiveTexture(GL_TEXTURE0 + Stage);
122 #else
123 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
124 #endif
125 checkGLcall("glActiveTextureARB");
126 } else if (Stage > 0) {
127 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
129 changeTexture = FALSE;
132 /* Now apply the change */
133 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
137 /* Note the D3DRS value applies to all textures, but GL has one
138 * per texture, so apply it now ready to be used!
140 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
141 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
142 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
144 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
147 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
148 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
150 float quad_att;
151 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
152 ICOM_THIS(IDirect3DDevice8Impl,iface);
154 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
155 glMatrixMode(GL_MODELVIEW);
156 glPushMatrix();
157 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
159 /* Diffuse: */
160 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
161 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
162 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
163 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
164 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
165 checkGLcall("glLightfv");
167 /* Specular */
168 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
169 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
170 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
171 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
172 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
173 checkGLcall("glLightfv");
175 /* Ambient */
176 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
177 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
178 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
179 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
180 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
181 checkGLcall("glLightfv");
183 /* Attenuation - Are these right? guessing... */
184 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
185 checkGLcall("glLightf");
186 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
187 checkGLcall("glLightf");
189 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
190 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
191 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
192 checkGLcall("glLightf");
194 switch (lightInfo->OriginalParms.Type) {
195 case D3DLIGHT_POINT:
196 /* Position */
197 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
198 checkGLcall("glLightfv");
199 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
200 checkGLcall("glLightf");
201 /* FIXME: Range */
202 break;
204 case D3DLIGHT_SPOT:
205 /* Position */
206 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
207 checkGLcall("glLightfv");
208 /* Direction */
209 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214 checkGLcall("glLightf");
215 /* FIXME: Range */
216 break;
218 case D3DLIGHT_DIRECTIONAL:
219 /* Direction */
220 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
221 checkGLcall("glLightfv");
222 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
223 checkGLcall("glLightf");
224 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
225 checkGLcall("glLightf");
226 break;
228 default:
229 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
232 /* Restore the modelview matrix */
233 glPopMatrix();
236 /* Setup this textures matrix */
237 static void set_texture_matrix(float *smat, DWORD flags)
239 float mat[16];
241 glMatrixMode(GL_TEXTURE);
243 if (flags == D3DTTFF_DISABLE) {
244 glLoadIdentity();
245 checkGLcall("glLoadIdentity()");
246 return;
249 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
250 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
251 checkGLcall("glLoadIdentity()");
252 return;
255 memcpy(mat, smat, 16*sizeof(float));
257 switch (flags & ~D3DTTFF_PROJECTED) {
258 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
259 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
260 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
263 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
264 case D3DTTFF_COUNT2:
265 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
266 mat[1] = mat[5] = mat[9] = mat[13] = 0;
267 break;
268 case D3DTTFF_COUNT3:
269 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
270 mat[2] = mat[6] = mat[10] = mat[14] = 0;
271 break;
273 glLoadMatrixf(mat);
274 checkGLcall("glLoadMatrixf(mat)");
277 /* IDirect3D IUnknown parts follow: */
278 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
280 ICOM_THIS(IDirect3DDevice8Impl,iface);
282 if (IsEqualGUID(riid, &IID_IUnknown)
283 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
284 IDirect3DDevice8Impl_AddRef(iface);
285 *ppobj = This;
286 return D3D_OK;
289 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
290 return E_NOINTERFACE;
293 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
294 ICOM_THIS(IDirect3DDevice8Impl,iface);
295 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
296 return ++(This->ref);
299 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
300 ICOM_THIS(IDirect3DDevice8Impl,iface);
301 ULONG ref = --This->ref;
302 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
303 if (ref == 0) {
304 IDirect3DDevice8Impl_CleanRender(iface);
305 HeapFree(GetProcessHeap(), 0, This);
307 return ref;
310 /* IDirect3DDevice Interface follow: */
311 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
312 ICOM_THIS(IDirect3DDevice8Impl,iface);
313 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
314 return D3D_OK;
317 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
318 ICOM_THIS(IDirect3DDevice8Impl,iface);
319 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
321 * pretend we have 32MB of any type of memory queried.
323 return (1024*1024*32);
326 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
327 ICOM_THIS(IDirect3DDevice8Impl,iface);
328 FIXME("(%p) : stub\n", This); return D3D_OK;
330 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
331 ICOM_THIS(IDirect3DDevice8Impl,iface);
332 TRACE("(%p) : returning %p\n", This, This->direct3d8);
334 /* Inc ref count */
335 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
337 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
338 return D3D_OK;
340 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
341 ICOM_THIS(IDirect3DDevice8Impl,iface);
342 FIXME("(%p) : stub, calling idirect3d for now\n", This);
343 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
344 return D3D_OK;
346 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
348 HDC hdc;
349 int bpp = 0;
351 ICOM_THIS(IDirect3DDevice8Impl,iface);
352 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
353 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
354 pMode->RefreshRate = 85; /*FIXME: How to identify? */
356 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
357 bpp = GetDeviceCaps(hdc, BITSPIXEL);
358 DeleteDC(hdc);
360 switch (bpp) {
361 case 8: pMode->Format = D3DFMT_R8G8B8; break;
362 case 16: pMode->Format = D3DFMT_R5G6B5; break;
363 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
364 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
365 default:
366 FIXME("Unrecognized display mode format\n");
367 pMode->Format = D3DFMT_UNKNOWN;
370 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
371 pMode->Format, debug_d3dformat(pMode->Format));
372 return D3D_OK;
374 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
375 ICOM_THIS(IDirect3DDevice8Impl,iface);
376 TRACE("(%p) copying to %p\n", This, pParameters);
377 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
378 return D3D_OK;
380 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
381 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
382 ICOM_THIS(IDirect3DDevice8Impl,iface);
383 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
385 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
386 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
387 return D3DERR_INVALIDCALL;
389 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
390 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
391 return D3DERR_INVALIDCALL;
394 This->xHotSpot = XHotSpot;
395 This->yHotSpot = YHotSpot;
396 return D3D_OK;
398 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
399 ICOM_THIS(IDirect3DDevice8Impl,iface);
400 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
401 This->xScreenSpace = XScreenSpace;
402 This->yScreenSpace = YScreenSpace;
403 return;
405 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
406 ICOM_THIS(IDirect3DDevice8Impl,iface);
407 TRACE("(%p) : visible(%d)\n", This, bShow);
408 This->bCursorVisible = bShow;
409 return D3D_OK;
411 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
412 IDirect3DSwapChain8Impl* object;
413 ICOM_THIS(IDirect3DDevice8Impl,iface);
414 FIXME("(%p) : stub\n", This);
416 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
417 if (NULL == object) {
418 return D3DERR_OUTOFVIDEOMEMORY;
420 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
421 object->ref = 1;
423 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
424 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
425 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
427 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
428 (pPresentationParameters->BackBufferHeight == 0))) {
429 RECT Rect;
431 GetClientRect(This->win_handle, &Rect);
433 if (pPresentationParameters->BackBufferWidth == 0) {
434 pPresentationParameters->BackBufferWidth = Rect.right;
435 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
437 if (pPresentationParameters->BackBufferHeight == 0) {
438 pPresentationParameters->BackBufferHeight = Rect.bottom;
439 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
443 /* Save the presentation parms now filled in correctly */
444 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
446 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
447 pPresentationParameters->BackBufferWidth,
448 pPresentationParameters->BackBufferHeight,
449 pPresentationParameters->BackBufferFormat,
450 pPresentationParameters->MultiSampleType,
451 TRUE,
452 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
454 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
455 pPresentationParameters->BackBufferWidth,
456 pPresentationParameters->BackBufferHeight,
457 pPresentationParameters->BackBufferFormat,
458 pPresentationParameters->MultiSampleType,
459 TRUE,
460 (LPDIRECT3DSURFACE8*) &object->backBuffer);
462 if (pPresentationParameters->EnableAutoDepthStencil) {
463 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
464 pPresentationParameters->BackBufferWidth,
465 pPresentationParameters->BackBufferHeight,
466 pPresentationParameters->AutoDepthStencilFormat,
467 D3DMULTISAMPLE_NONE,
468 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
469 } else {
470 object->depthStencilBuffer = NULL;
473 *pSwapChain = (IDirect3DSwapChain8*) object;
474 return D3D_OK;
476 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
477 ICOM_THIS(IDirect3DDevice8Impl,iface);
478 FIXME("(%p) : stub\n", This); return D3D_OK;
480 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
481 ICOM_THIS(IDirect3DDevice8Impl,iface);
482 TRACE("(%p) : complete stub!\n", This);
484 ENTER_GL();
486 glXSwapBuffers(This->display, This->drawable);
487 /* Dont call checkGLcall, as glGetError is not applicable here */
488 TRACE("glXSwapBuffers called, Starting new frame\n");
490 /* FPS support */
491 if (TRACE_ON(fps))
493 static long prev_time, frames;
495 DWORD time = GetTickCount();
496 frames++;
497 /* every 1.5 seconds */
498 if (time - prev_time > 1500) {
499 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
500 prev_time = time;
501 frames = 0;
505 #if defined(FRAME_DEBUGGING)
507 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
508 if (!isOn) {
509 isOn = TRUE;
510 FIXME("Enabling D3D Trace\n");
511 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
512 #if defined(SHOW_FRAME_MAKEUP)
513 FIXME("Singe Frame snapshots Starting\n");
514 isDumpingFrames = TRUE;
515 glClear(GL_COLOR_BUFFER_BIT);
516 #endif
518 #if defined(SINGLE_FRAME_DEBUGGING)
519 } else {
520 #if defined(SHOW_FRAME_MAKEUP)
521 FIXME("Singe Frame snapshots Finishing\n");
522 isDumpingFrames = FALSE;
523 #endif
524 FIXME("Singe Frame trace complete\n");
525 DeleteFileA("C:\\D3DTRACE");
526 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
527 #endif
529 } else {
530 if (isOn) {
531 isOn = FALSE;
532 #if defined(SHOW_FRAME_MAKEUP)
533 FIXME("Singe Frame snapshots Finishing\n");
534 isDumpingFrames = FALSE;
535 #endif
536 FIXME("Disabling D3D Trace\n");
537 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
541 #endif
543 LEAVE_GL();
545 return D3D_OK;
547 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
548 ICOM_THIS(IDirect3DDevice8Impl,iface);
549 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
550 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
552 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
553 FIXME("Only one backBuffer currently supported\n");
554 return D3DERR_INVALIDCALL;
557 /* Note inc ref on returned surface */
558 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
560 return D3D_OK;
562 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
563 ICOM_THIS(IDirect3DDevice8Impl,iface);
564 FIXME("(%p) : stub\n", This);
565 return D3D_OK;
567 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
568 HDC hDC;
569 ICOM_THIS(IDirect3DDevice8Impl,iface);
571 FIXME("(%p) : pRamp@%p\n", This, pRamp);
572 hDC = GetDC(This->win_handle);
573 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
574 ReleaseDC(This->win_handle, hDC);
575 return;
577 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
578 HDC hDC;
579 ICOM_THIS(IDirect3DDevice8Impl,iface);
581 FIXME("(%p) : pRamp@%p\n", This, pRamp);
582 hDC = GetDC(This->win_handle);
583 GetDeviceGammaRamp(hDC, pRamp);
584 ReleaseDC(This->win_handle, hDC);
585 return;
587 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
588 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
589 IDirect3DTexture8Impl *object;
590 int i;
591 UINT tmpW;
592 UINT tmpH;
594 ICOM_THIS(IDirect3DDevice8Impl,iface);
596 /* Allocate the storage for the device */
597 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, debug_d3dformat(Format), Pool);
598 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
599 object->lpVtbl = &Direct3DTexture8_Vtbl;
600 object->Device = This;
601 object->ResourceType = D3DRTYPE_TEXTURE;
602 object->ref = 1;
603 object->width = Width;
604 object->height = Height;
605 object->levels = Levels;
606 object->usage = Usage;
607 object->format = Format;
609 /* Calculate levels for mip mapping */
610 if (Levels == 0) {
611 object->levels++;
612 tmpW = Width;
613 tmpH = Height;
614 while (tmpW > 1 && tmpH > 1) {
615 tmpW = max(1, tmpW / 2);
616 tmpH = max(1, tmpH / 2);
617 object->levels++;
619 TRACE("Calculated levels = %d\n", object->levels);
622 /* Generate all the surfaces */
623 tmpW = Width;
624 tmpH = Height;
625 for (i = 0; i < object->levels; i++)
627 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
628 object->surfaces[i]->Container = (IUnknown*) object;
629 object->surfaces[i]->myDesc.Usage = Usage;
630 object->surfaces[i]->myDesc.Pool = Pool;
631 /**
632 * As written in msdn in IDirect3DTexture8::LockRect
633 * Textures created in D3DPOOL_DEFAULT are not lockable.
635 if (D3DPOOL_DEFAULT == Pool) {
636 object->surfaces[i]->lockable = FALSE;
639 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
640 tmpW = max(1, tmpW / 2);
641 tmpH = max(1, tmpH / 2);
644 *ppTexture = (LPDIRECT3DTEXTURE8) object;
645 TRACE("(%p) : Created texture %p\n", This, object);
646 return D3D_OK;
648 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
649 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
650 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
652 IDirect3DVolumeTexture8Impl *object;
653 int i;
654 UINT tmpW;
655 UINT tmpH;
656 UINT tmpD;
658 ICOM_THIS(IDirect3DDevice8Impl,iface);
660 /* Allocate the storage for it */
661 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
662 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
663 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
664 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
665 object->Device = This;
666 object->ref = 1;
668 object->width = Width;
669 object->height = Height;
670 object->depth = Depth;
671 object->levels = Levels;
672 object->usage = Usage;
673 object->format = Format;
675 /* Calculate levels for mip mapping */
676 if (Levels == 0) {
677 object->levels++;
678 tmpW = Width;
679 tmpH = Height;
680 tmpD = Depth;
681 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
682 tmpW = max(1, tmpW / 2);
683 tmpH = max(1, tmpH / 2);
684 tmpD = max(1, tmpD / 2);
685 object->levels++;
687 TRACE("Calculated levels = %d\n", object->levels);
690 /* Generate all the surfaces */
691 tmpW = Width;
692 tmpH = Height;
693 tmpD = Depth;
695 for (i = 0; i < object->levels; i++)
697 IDirect3DVolume8Impl* volume;
699 /* Create the volume - No entry point for this seperately?? */
700 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
701 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
703 volume->lpVtbl = &Direct3DVolume8_Vtbl;
704 volume->Device = This;
705 volume->ResourceType = D3DRTYPE_VOLUME;
706 volume->Container = (IUnknown*) object;
707 volume->ref = 1;
709 volume->myDesc.Width = Width;
710 volume->myDesc.Height = Height;
711 volume->myDesc.Depth = Depth;
712 volume->myDesc.Format = Format;
713 volume->myDesc.Type = D3DRTYPE_VOLUME;
714 volume->myDesc.Pool = Pool;
715 volume->myDesc.Usage = Usage;
716 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
717 /* Note: Volume textures cannot be dxtn, hence no need to check here */
718 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
719 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
721 volume->lockable = TRUE;
722 volume->locked = FALSE;
723 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
724 volume->Dirty = FALSE;
725 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
727 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
728 This, Width, Height, Depth, Format, debug_d3dformat(Format),
729 volume, volume->allocatedMemory, volume->myDesc.Size);
731 tmpW = max(1, tmpW / 2);
732 tmpH = max(1, tmpH / 2);
733 tmpD = max(1, tmpD / 2);
736 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
737 TRACE("(%p) : Created volume texture %p\n", This, object);
738 return D3D_OK;
740 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
741 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
743 IDirect3DCubeTexture8Impl *object;
744 ICOM_THIS(IDirect3DDevice8Impl,iface);
745 int i,j;
746 UINT tmpW;
748 /* Allocate the storage for it */
749 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
750 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
751 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
752 object->ref = 1;
753 object->Device = This;
754 object->ResourceType = D3DRTYPE_CUBETEXTURE;
756 object->edgeLength = EdgeLength;
757 object->levels = Levels;
758 object->usage = Usage;
759 object->format = Format;
761 /* Calculate levels for mip mapping */
762 if (Levels == 0) {
763 object->levels++;
764 tmpW = EdgeLength;
765 while (tmpW > 1) {
766 tmpW = max(1, tmpW / 2);
767 object->levels++;
769 TRACE("Calculated levels = %d\n", object->levels);
772 /* Generate all the surfaces */
773 tmpW = EdgeLength;
774 for (i = 0; i < object->levels; i++) {
775 /* Create the 6 faces */
776 for (j = 0; j < 6; j++) {
777 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
778 object->surfaces[j][i]->Container = (IUnknown*) object;
779 object->surfaces[j][i]->myDesc.Usage = Usage;
780 object->surfaces[j][i]->myDesc.Pool = Pool;
781 /**
782 * As written in msdn in IDirect3DCubeTexture8::LockRect
783 * Textures created in D3DPOOL_DEFAULT are not lockable.
785 if (D3DPOOL_DEFAULT == Pool) {
786 object->surfaces[j][i]->lockable = FALSE;
789 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
791 tmpW = max(1, tmpW / 2);
794 TRACE("(%p) : Iface@%p\n", This, object);
795 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
796 return D3D_OK;
798 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
799 IDirect3DVertexBuffer8Impl *object;
801 ICOM_THIS(IDirect3DDevice8Impl,iface);
803 /* Allocate the storage for the device */
804 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
805 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
806 object->Device = This;
807 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
808 object->ref = 1;
809 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
810 object->currentDesc.Usage = Usage;
811 object->currentDesc.Pool = Pool;
812 object->currentDesc.FVF = FVF;
813 object->currentDesc.Size = Size;
815 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
817 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
819 return D3D_OK;
821 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
822 IDirect3DIndexBuffer8Impl *object;
824 ICOM_THIS(IDirect3DDevice8Impl,iface);
825 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
827 /* Allocate the storage for the device */
828 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
829 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
830 object->Device = This;
831 object->ref = 1;
832 object->ResourceType = D3DRTYPE_INDEXBUFFER;
834 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
835 object->currentDesc.Usage = Usage;
836 object->currentDesc.Pool = Pool;
837 object->currentDesc.Format = Format;
838 object->currentDesc.Size = Length;
840 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
842 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
844 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
846 return D3D_OK;
848 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
849 IDirect3DSurface8Impl *object;
850 ICOM_THIS(IDirect3DDevice8Impl,iface);
852 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
853 if (NULL == object) {
854 *ppSurface = NULL;
855 return D3DERR_OUTOFVIDEOMEMORY;
857 *ppSurface = (LPDIRECT3DSURFACE8) object;
858 object->lpVtbl = &Direct3DSurface8_Vtbl;
859 object->Device = This;
860 object->ResourceType = D3DRTYPE_SURFACE;
861 object->Container = (IUnknown*) This;
863 object->ref = 1;
864 object->myDesc.Width = Width;
865 object->myDesc.Height = Height;
866 object->myDesc.Format = Format;
867 object->myDesc.Type = D3DRTYPE_SURFACE;
868 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
869 object->myDesc.Pool = D3DPOOL_DEFAULT;
870 object->myDesc.MultiSampleType = MultiSample;
871 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
872 if (Format == D3DFMT_DXT1) {
873 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
874 } else {
875 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
877 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
878 object->lockable = Lockable;
879 object->locked = FALSE;
880 memset(&object->lockedRect, 0, sizeof(RECT));
881 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
883 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), Lockable, *ppSurface, object->allocatedMemory, object->myDesc.Size);
884 return D3D_OK;
886 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
887 IDirect3DSurface8Impl *object;
889 ICOM_THIS(IDirect3DDevice8Impl,iface);
891 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
892 if (NULL == object) {
893 *ppSurface = NULL;
894 return D3DERR_OUTOFVIDEOMEMORY;
896 *ppSurface = (LPDIRECT3DSURFACE8) object;
897 object->lpVtbl = &Direct3DSurface8_Vtbl;
898 object->Device = This;
899 object->ResourceType = D3DRTYPE_SURFACE;
900 object->Container = (IUnknown*) This;
902 object->ref = 1;
903 object->myDesc.Width = Width;
904 object->myDesc.Height = Height;
905 object->myDesc.Format = Format;
906 object->myDesc.Type = D3DRTYPE_SURFACE;
907 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
908 object->myDesc.Pool = D3DPOOL_DEFAULT;
909 object->myDesc.MultiSampleType = MultiSample;
910 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
911 if (Format == D3DFMT_DXT1) {
912 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
913 } else {
914 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
916 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
917 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
918 object->locked = FALSE;
919 memset(&object->lockedRect, 0, sizeof(RECT));
920 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
922 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
923 return D3D_OK;
925 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
926 IDirect3DSurface8Impl *object;
928 ICOM_THIS(IDirect3DDevice8Impl,iface);
930 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
931 *ppSurface = (LPDIRECT3DSURFACE8) object;
932 object->lpVtbl = &Direct3DSurface8_Vtbl;
933 object->Device = This;
934 object->ResourceType = D3DRTYPE_SURFACE;
935 object->Container = (IUnknown*) This;
937 object->ref = 1;
938 object->myDesc.Width = Width;
939 object->myDesc.Height = Height;
940 object->myDesc.Format = Format;
941 object->myDesc.Type = D3DRTYPE_SURFACE;
942 object->myDesc.Usage = 0;
943 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
944 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
945 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
946 it is based around 4x4 pixel blocks it requires padding, so allocate enough
947 space! */
948 if (Format == D3DFMT_DXT1) {
949 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
950 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
951 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
952 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
953 } else {
954 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
956 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
957 object->lockable = TRUE;
958 object->locked = FALSE;
959 memset(&object->lockedRect, 0, sizeof(RECT));
960 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
962 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
963 return D3D_OK;
965 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
966 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
967 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
969 HRESULT rc = D3D_OK;
970 IDirect3DBaseTexture8* texture = NULL;
973 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
974 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
976 ICOM_THIS(IDirect3DDevice8Impl,iface);
977 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
978 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
980 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
981 a sample and doesnt seem to break anything as far as I can tell */
982 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
983 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
984 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
985 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
986 rc = D3DERR_INVALIDCALL;
988 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
989 TRACE("Converting dest to same format as source, since dest was unknown\n");
990 dst->myDesc.Format = src->myDesc.Format;
992 /* Convert container as well */
993 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
994 if (texture != NULL) {
995 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
996 /** Releasing texture after GetContainer */
997 IDirect3DBaseTexture8_Release(texture);
998 texture = NULL;
1002 /* Quick if complete copy ... */
1003 if (rc == D3D_OK && cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1005 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1007 D3DLOCKED_RECT lrSrc;
1008 D3DLOCKED_RECT lrDst;
1009 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1010 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1011 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1013 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1015 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1016 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1017 TRACE("Unlocked src and dst\n");
1019 } else {
1021 FIXME("Wanted to copy all surfaces but size not compatible\n");
1022 rc = D3DERR_INVALIDCALL;
1026 } else {
1028 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1030 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1031 int i;
1033 /* Copy rect by rect */
1034 for (i = 0; i < cRects; i++) {
1035 CONST RECT* r = &pSourceRectsArray[i];
1036 CONST POINT* p = &pDestPointsArray[i];
1037 int copyperline;
1038 int j;
1039 D3DLOCKED_RECT lrSrc;
1040 D3DLOCKED_RECT lrDst;
1041 RECT dest_rect;
1044 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1045 if (src->myDesc.Format == D3DFMT_DXT1) {
1046 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1047 } else {
1048 copyperline = ((r->right - r->left) * bytesPerPixel);
1050 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1051 dest_rect.left = p->x;
1052 dest_rect.top = p->y;
1053 dest_rect.right = p->x + (r->right - r->left);
1054 dest_rect.left = p->y + (r->bottom - r->top);
1055 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1056 TRACE("Locked src and dst\n");
1058 /* Find where to start */
1059 for (j = 0; j < (r->bottom - r->top); j++) {
1060 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1063 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1064 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1065 TRACE("Unlocked src and dst\n");
1068 } else {
1070 FIXME("Wanted to copy partial surfaces not implemented\n");
1071 rc = D3DERR_INVALIDCALL;
1076 return rc;
1078 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1079 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1080 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1081 D3DRESOURCETYPE srcType;
1082 D3DRESOURCETYPE dstType;
1084 ICOM_THIS(IDirect3DDevice8Impl,iface);
1085 TRACE("(%p) : first try\n", This);
1087 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1088 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1090 if (srcType != dstType) {
1091 return D3DERR_INVALIDCALL;
1093 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1094 return D3DERR_INVALIDCALL;
1096 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1097 return D3DERR_INVALIDCALL;
1099 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1100 /** Only copy Dirty textures */
1101 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1102 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1103 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1104 UINT i, j;
1106 for (i = skipLevels; i < srcLevelCnt; ++i) {
1107 HRESULT hr;
1109 switch (srcType) {
1110 case D3DRTYPE_TEXTURE:
1112 IDirect3DSurface8* srcSur = NULL;
1113 IDirect3DSurface8* dstSur = NULL;
1114 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1115 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1117 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1118 about dst with less levels than the source?) */
1119 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1121 IDirect3DSurface8Impl_Release(srcSur);
1122 IDirect3DSurface8Impl_Release(dstSur);
1124 break;
1125 case D3DRTYPE_VOLUMETEXTURE:
1127 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1129 break;
1130 case D3DRTYPE_CUBETEXTURE:
1132 IDirect3DSurface8* srcSur = NULL;
1133 IDirect3DSurface8* dstSur = NULL;
1134 for (j = 0; j < 5; ++j) {
1135 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1136 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1137 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1138 IDirect3DSurface8Impl_Release(srcSur);
1139 IDirect3DSurface8Impl_Release(dstSur);
1142 break;
1143 default:
1144 break;
1147 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1150 return D3D_OK;
1152 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1153 HRESULT hr;
1154 D3DLOCKED_RECT lockedRect;
1155 RECT wantedRect;
1156 GLint prev_store;
1157 GLenum prev_read;
1159 ICOM_THIS(IDirect3DDevice8Impl,iface);
1161 FIXME("(%p) : see if behavior correct\n", This);
1163 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1164 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1165 return D3DERR_INVALIDCALL;
1168 wantedRect.left = 0;
1169 wantedRect.top = 0;
1170 wantedRect.right = This->PresentParms.BackBufferWidth;
1171 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1173 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1174 if (FAILED(hr)) {
1175 ERR("(%p) : cannot lock surface\n", This);
1176 return D3DERR_INVALIDCALL;
1179 ENTER_GL();
1181 glFlush();
1182 vcheckGLcall("glFlush");
1183 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1184 vcheckGLcall("glIntegerv");
1185 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1186 vcheckGLcall("glIntegerv");
1188 glReadBuffer(GL_FRONT);
1189 vcheckGLcall("glReadBuffer");
1190 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1191 vcheckGLcall("glPixelStorei");
1192 /* stupid copy */
1194 long j;
1195 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1196 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1197 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1198 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1199 vcheckGLcall("glReadPixels");
1202 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1203 vcheckGLcall("glPixelStorei");
1204 glReadBuffer(prev_read);
1205 vcheckGLcall("glReadBuffer");
1207 LEAVE_GL();
1209 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1210 return hr;
1212 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1213 HRESULT hr;
1215 ICOM_THIS(IDirect3DDevice8Impl,iface);
1217 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1218 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1219 return D3D_OK;
1222 IDirect3DDevice8Impl_CleanRender(iface);
1224 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1225 IDirect3DSurface8Impl* tmp;
1227 TRACE("retoring SetRenderTarget defaults\n");
1229 tmp = This->renderTarget;
1230 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1231 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1232 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1234 tmp = This->stencilBufferTarget;
1235 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1236 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1237 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1239 return D3D_OK;
1242 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1244 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1246 return hr;
1249 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1250 ICOM_THIS(IDirect3DDevice8Impl,iface);
1252 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1254 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1255 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1257 return D3D_OK;
1260 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1261 ICOM_THIS(IDirect3DDevice8Impl,iface);
1263 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1265 /* Note inc ref on returned surface */
1266 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1267 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1269 return D3D_OK;
1272 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1273 ICOM_THIS(IDirect3DDevice8Impl,iface);
1274 TRACE("(%p) : stub\n", This);
1275 return D3D_OK;
1277 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1278 IDirect3DBaseTexture8* cont = NULL;
1279 HRESULT hr;
1280 ICOM_THIS(IDirect3DDevice8Impl,iface);
1281 TRACE("(%p)\n", This);
1283 ENTER_GL();
1285 glFlush();
1286 checkGLcall("glFlush");
1288 /* Useful for debugging sometimes!
1289 printf("Hit Enter ...\n");
1290 getchar(); */
1292 if (This->frontBuffer != This->renderTarget) {
1294 GLenum prev_read;
1295 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1296 vcheckGLcall("glIntegerv");
1297 glReadBuffer(GL_BACK);
1298 vcheckGLcall("glReadBuffer");
1300 long j;
1301 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1303 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1304 pitch = pitch / 2;
1306 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1307 glReadPixels(0,
1308 This->renderTarget->myDesc.Height - j - 1,
1309 This->renderTarget->myDesc.Width,
1311 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1312 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1313 This->renderTarget->allocatedMemory + j * pitch);
1314 vcheckGLcall("glReadPixels");
1317 glReadBuffer(prev_read);
1318 vcheckGLcall("glReadBuffer");
1321 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1322 if (SUCCEEDED(hr) && NULL != cont) {
1323 /** always dirtify for now. we must find a better way to see that surface have been modified */
1324 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1325 IDirect3DBaseTexture8_PreLoad(cont);
1326 IDirect3DBaseTexture8Impl_Release(cont);
1327 cont = NULL;
1331 LEAVE_GL();
1332 return D3D_OK;
1334 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1335 ICOM_THIS(IDirect3DDevice8Impl,iface);
1337 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1338 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1339 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1340 GLbitfield glMask = 0;
1341 GLboolean old_ztest;
1342 GLfloat old_z_clear_value;
1343 GLint old_stencil_clear_value;
1344 GLfloat old_color_clear_value[4];
1345 int i;
1346 CONST D3DRECT* curRect;
1348 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1349 Count, pRects, Flags, Z, Stencil);
1351 ENTER_GL();
1352 if (Count > 0 && pRects) {
1353 glEnable(GL_SCISSOR_TEST);
1354 checkGLcall("glEnable GL_SCISSOR_TEST");
1355 curRect = pRects;
1356 } else {
1357 curRect = NULL;
1360 /* Only set the values up once, as they are not changing */
1361 if (Flags & D3DCLEAR_STENCIL) {
1362 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1363 glClearStencil(Stencil);
1364 checkGLcall("glClearStencil");
1365 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1368 if (Flags & D3DCLEAR_ZBUFFER) {
1369 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1370 glDepthMask(GL_TRUE);
1371 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1372 glClearDepth(Z);
1373 checkGLcall("glClearDepth");
1374 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1377 if (Flags & D3DCLEAR_TARGET) {
1378 TRACE("Clearing screen with glClear to color %lx\n", Color);
1379 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1380 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1381 ((Color >> 8) & 0xFF) / 255.0f,
1382 ((Color >> 0) & 0xFF) / 255.0f,
1383 ((Color >> 24) & 0xFF) / 255.0f);
1384 checkGLcall("glClearColor");
1385 glMask = glMask | GL_COLOR_BUFFER_BIT;
1388 /* Now process each rect in turn */
1389 for (i = 0; i < Count || i == 0; i++) {
1391 if (curRect) {
1392 /* Note gl uses lower left, width/height */
1393 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1394 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1395 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1396 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1397 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1398 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1399 checkGLcall("glScissor");
1402 /* Clear the selected rectangle (or full screen) */
1403 glClear(glMask);
1404 checkGLcall("glClear");
1406 /* Step to the next rectangle */
1407 if (curRect) curRect = curRect + sizeof(D3DRECT);
1410 /* Restore the old values (why..?) */
1411 if (Flags & D3DCLEAR_STENCIL) {
1412 glClearStencil(old_stencil_clear_value);
1414 if (Flags & D3DCLEAR_ZBUFFER) {
1415 glDepthMask(old_ztest);
1416 glClearDepth(old_z_clear_value);
1418 if (Flags & D3DCLEAR_TARGET) {
1419 glClearColor(old_color_clear_value[0],
1420 old_color_clear_value[1],
1421 old_color_clear_value[2],
1422 old_color_clear_value[3]);
1425 if (Count > 0 && pRects) {
1426 glDisable(GL_SCISSOR_TEST);
1427 checkGLcall("glDisable");
1429 LEAVE_GL();
1431 return D3D_OK;
1433 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1434 ICOM_THIS(IDirect3DDevice8Impl,iface);
1435 int k;
1437 /* Most of this routine, comments included copied from ddraw tree initially: */
1438 TRACE("(%p) : State=%d\n", This, d3dts);
1440 /* Handle recording of state blocks */
1441 if (This->isRecordingState) {
1442 TRACE("Recording... not performing anything\n");
1443 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1444 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1445 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1446 return D3D_OK;
1450 * if the new matrix is the same as the current one,
1451 * we cut off any further processing. this seems to be a reasonable
1452 * optimization because as was noticed, some apps (warcraft3 for example)
1453 * tend towards setting the same matrix repeatedly for some dumb reason.
1455 * From here on we assume that the new matrix is different, wherever it matters
1456 * but note
1458 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1459 TRACE("The app is setting the same matrix over again\n");
1460 return D3D_OK;
1461 } else {
1462 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1466 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1467 where ViewMat = Camera space, WorldMat = world space.
1469 In OpenGL, camera and world space is combined into GL_MODELVIEW
1470 matrix. The Projection matrix stay projection matrix.
1473 /* Capture the times we can just ignore the change */
1474 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1475 This->modelview_valid = FALSE;
1476 return D3D_OK;
1478 } else if (d3dts == D3DTS_PROJECTION) {
1479 This->proj_valid = FALSE;
1480 return D3D_OK;
1482 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1483 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1484 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1485 return D3D_OK;
1488 /* Chances are we really are going to have to change a matrix */
1489 ENTER_GL();
1491 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1492 if (d3dts < GL_LIMITS(textures)) {
1493 int tex = d3dts - D3DTS_TEXTURE0;
1494 #if defined(GL_VERSION_1_3)
1495 glActiveTexture(GL_TEXTURE0 + tex);
1496 #else
1497 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1498 #endif
1499 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1502 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1504 PLIGHTINFOEL *lightChain = NULL;
1505 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1506 This->modelview_valid = FALSE;
1507 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1508 glMatrixMode(GL_MODELVIEW);
1509 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1510 glPushMatrix();
1511 glLoadMatrixf((float *)lpmatrix);
1512 checkGLcall("glLoadMatrixf(...)");
1514 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1515 * NOTE: We have to reset the positions even if the light/plane is not currently
1516 * enabled, since the call to enable it will not reset the position.
1517 * NOTE2: Apparently texture transforms do NOT need reapplying
1520 /* Reset lights */
1521 lightChain = This->StateBlock->lights;
1522 while (lightChain && lightChain->glIndex != -1) {
1523 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1524 checkGLcall("glLightfv posn");
1525 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1526 checkGLcall("glLightfv dirn");
1527 lightChain = lightChain->next;
1529 /* Reset Clipping Planes if clipping is enabled */
1530 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1531 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1532 checkGLcall("glClipPlane");
1534 glPopMatrix();
1536 } else { /* What was requested!?? */
1537 WARN("invalid matrix specified: %i\n", d3dts);
1541 /* Release lock, all done */
1542 LEAVE_GL();
1543 return D3D_OK;
1546 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1547 ICOM_THIS(IDirect3DDevice8Impl,iface);
1548 TRACE("(%p) : for State %d\n", This, State);
1549 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1550 return D3D_OK;
1553 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1554 D3DMATRIX *mat = NULL;
1555 D3DMATRIX temp;
1557 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1558 but works regardless of recording being on.
1559 If this is found to be wrong, change to StateBlock. */
1560 ICOM_THIS(IDirect3DDevice8Impl,iface);
1561 TRACE("(%p) : For state %u\n", This, State);
1563 if (State < HIGHEST_TRANSFORMSTATE)
1565 mat = &This->UpdateStateBlock->transforms[State];
1566 } else {
1567 FIXME("Unhandled transform state!!\n");
1570 /* Copied from ddraw code: */
1571 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1572 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1573 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1574 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1576 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1577 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1578 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1579 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1581 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1582 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1583 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1584 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1586 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1587 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1588 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1589 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1591 /* Apply change via set transform - will reapply to eg. lights this way */
1592 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1593 return D3D_OK;
1595 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1596 ICOM_THIS(IDirect3DDevice8Impl,iface);
1598 TRACE("(%p)\n", This);
1599 This->UpdateStateBlock->Changed.viewport = TRUE;
1600 This->UpdateStateBlock->Set.viewport = TRUE;
1601 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1603 /* Handle recording of state blocks */
1604 if (This->isRecordingState) {
1605 TRACE("Recording... not performing anything\n");
1606 return D3D_OK;
1609 ENTER_GL();
1611 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1612 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1614 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1615 checkGLcall("glDepthRange");
1616 /* Note: GL requires lower left, DirectX supplies upper left */
1617 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1618 pViewport->Width, pViewport->Height);
1619 checkGLcall("glViewport");
1621 LEAVE_GL();
1623 return D3D_OK;
1626 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1627 ICOM_THIS(IDirect3DDevice8Impl,iface);
1628 TRACE("(%p)\n", This);
1629 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1630 return D3D_OK;
1633 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1634 ICOM_THIS(IDirect3DDevice8Impl,iface);
1636 This->UpdateStateBlock->Changed.material = TRUE;
1637 This->UpdateStateBlock->Set.material = TRUE;
1638 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1640 /* Handle recording of state blocks */
1641 if (This->isRecordingState) {
1642 TRACE("Recording... not performing anything\n");
1643 return D3D_OK;
1646 ENTER_GL();
1647 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1648 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1649 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1650 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1651 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1653 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1654 checkGLcall("glMaterialfv");
1655 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1656 checkGLcall("glMaterialfv");
1658 /* Only change material color if specular is enabled, otherwise it is set to black */
1659 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1660 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1661 checkGLcall("glMaterialfv");
1662 } else {
1663 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1664 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1665 checkGLcall("glMaterialfv");
1667 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1668 checkGLcall("glMaterialfv");
1669 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1670 checkGLcall("glMaterialf");
1672 LEAVE_GL();
1673 return D3D_OK;
1675 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1676 ICOM_THIS(IDirect3DDevice8Impl,iface);
1677 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1678 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1679 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1680 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1681 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1682 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1683 return D3D_OK;
1686 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1687 you can reference any indexes you want as long as that number max are enabled are any
1688 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1689 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1690 but when recording, just build a chain pretty much of commands to be replayed. */
1692 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1693 float rho;
1694 PLIGHTINFOEL *object, *temp;
1696 ICOM_THIS(IDirect3DDevice8Impl,iface);
1697 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1699 /* If recording state block, just add to end of lights chain */
1700 if (This->isRecordingState) {
1701 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1702 if (NULL == object) {
1703 return D3DERR_OUTOFVIDEOMEMORY;
1705 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1706 object->OriginalIndex = Index;
1707 object->glIndex = -1;
1708 object->changed = TRUE;
1710 /* Add to the END of the chain of lights changes to be replayed */
1711 if (This->UpdateStateBlock->lights == NULL) {
1712 This->UpdateStateBlock->lights = object;
1713 } else {
1714 temp = This->UpdateStateBlock->lights;
1715 while (temp->next != NULL) temp=temp->next;
1716 temp->next = object;
1718 TRACE("Recording... not performing anything more\n");
1719 return D3D_OK;
1722 /* Ok, not recording any longer so do real work */
1723 object = This->StateBlock->lights;
1724 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1726 /* If we didnt find it in the list of lights, time to add it */
1727 if (object == NULL) {
1728 PLIGHTINFOEL *insertAt,*prevPos;
1730 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1731 if (NULL == object) {
1732 return D3DERR_OUTOFVIDEOMEMORY;
1734 object->OriginalIndex = Index;
1735 object->glIndex = -1;
1737 /* Add it to the front of list with the idea that lights will be changed as needed
1738 BUT after any lights currently assigned GL indexes */
1739 insertAt = This->StateBlock->lights;
1740 prevPos = NULL;
1741 while (insertAt != NULL && insertAt->glIndex != -1) {
1742 prevPos = insertAt;
1743 insertAt = insertAt->next;
1746 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1747 This->StateBlock->lights = object;
1748 } else if (insertAt == NULL) { /* End of list */
1749 prevPos->next = object;
1750 object->prev = prevPos;
1751 } else { /* Middle of chain */
1752 if (prevPos == NULL) {
1753 This->StateBlock->lights = object;
1754 } else {
1755 prevPos->next = object;
1757 object->prev = prevPos;
1758 object->next = insertAt;
1759 insertAt->prev = object;
1763 /* Initialze the object */
1764 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,
1765 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1766 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1767 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1768 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1769 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1770 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1772 /* Save away the information */
1773 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1775 switch (pLight->Type) {
1776 case D3DLIGHT_POINT:
1777 /* Position */
1778 object->lightPosn[0] = pLight->Position.x;
1779 object->lightPosn[1] = pLight->Position.y;
1780 object->lightPosn[2] = pLight->Position.z;
1781 object->lightPosn[3] = 1.0f;
1782 object->cutoff = 180.0f;
1783 /* FIXME: Range */
1784 break;
1786 case D3DLIGHT_SPOT:
1787 /* Position */
1788 object->lightPosn[0] = pLight->Position.x;
1789 object->lightPosn[1] = pLight->Position.y;
1790 object->lightPosn[2] = pLight->Position.z;
1791 object->lightPosn[3] = 1.0;
1793 /* Direction */
1794 object->lightDirn[0] = pLight->Direction.x;
1795 object->lightDirn[1] = pLight->Direction.y;
1796 object->lightDirn[2] = pLight->Direction.z;
1797 object->lightDirn[3] = 1.0;
1800 * opengl-ish and d3d-ish spot lights use too different models for the
1801 * light "intensity" as a function of the angle towards the main light direction,
1802 * so we only can approximate very roughly.
1803 * however spot lights are rather rarely used in games (if ever used at all).
1804 * furthermore if still used, probably nobody pays attention to such details.
1806 if (pLight->Falloff == 0) {
1807 rho = 6.28f;
1808 } else {
1809 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1811 if (rho < 0.0001) rho = 0.0001f;
1812 object->exponent = -0.3/log(cos(rho/2));
1813 object->cutoff = pLight->Phi*90/M_PI;
1815 /* FIXME: Range */
1816 break;
1818 case D3DLIGHT_DIRECTIONAL:
1819 /* Direction */
1820 object->lightPosn[0] = -pLight->Direction.x;
1821 object->lightPosn[1] = -pLight->Direction.y;
1822 object->lightPosn[2] = -pLight->Direction.z;
1823 object->lightPosn[3] = 0.0;
1824 object->exponent = 0.0f;
1825 object->cutoff = 180.0f;
1826 break;
1828 default:
1829 FIXME("Unrecognized light type %d\n", pLight->Type);
1832 /* Update the live definitions if the light is currently assigned a glIndex */
1833 if (object->glIndex != -1) {
1834 setup_light(iface, object->glIndex, object);
1836 return D3D_OK;
1838 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1839 PLIGHTINFOEL *lightInfo = NULL;
1840 ICOM_THIS(IDirect3DDevice8Impl,iface);
1841 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1843 /* Locate the light in the live lights */
1844 lightInfo = This->StateBlock->lights;
1845 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1847 if (lightInfo == NULL) {
1848 TRACE("Light information requested but light not defined\n");
1849 return D3DERR_INVALIDCALL;
1852 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1853 return D3D_OK;
1855 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1856 PLIGHTINFOEL *lightInfo = NULL;
1857 ICOM_THIS(IDirect3DDevice8Impl,iface);
1858 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1860 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1861 if (This->isRecordingState) {
1862 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1863 if (NULL == lightInfo) {
1864 return D3DERR_OUTOFVIDEOMEMORY;
1866 lightInfo->OriginalIndex = Index;
1867 lightInfo->glIndex = -1;
1868 lightInfo->enabledChanged = TRUE;
1870 /* Add to the END of the chain of lights changes to be replayed */
1871 if (This->UpdateStateBlock->lights == NULL) {
1872 This->UpdateStateBlock->lights = lightInfo;
1873 } else {
1874 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1875 while (temp->next != NULL) temp=temp->next;
1876 temp->next = lightInfo;
1878 TRACE("Recording... not performing anything more\n");
1879 return D3D_OK;
1882 /* Not recording... So, locate the light in the live lights */
1883 lightInfo = This->StateBlock->lights;
1884 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1886 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1887 if (lightInfo == NULL) {
1888 D3DLIGHT8 lightParms;
1889 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1890 wait until someone confirms it seems to work! */
1891 TRACE("Light enabled requested but light not defined, so defining one!\n");
1892 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1893 lightParms.Diffuse.r = 1.0;
1894 lightParms.Diffuse.g = 1.0;
1895 lightParms.Diffuse.b = 1.0;
1896 lightParms.Diffuse.a = 0.0;
1897 lightParms.Specular.r = 0.0;
1898 lightParms.Specular.g = 0.0;
1899 lightParms.Specular.b = 0.0;
1900 lightParms.Specular.a = 0.0;
1901 lightParms.Ambient.r = 0.0;
1902 lightParms.Ambient.g = 0.0;
1903 lightParms.Ambient.b = 0.0;
1904 lightParms.Ambient.a = 0.0;
1905 lightParms.Position.x = 0.0;
1906 lightParms.Position.y = 0.0;
1907 lightParms.Position.z = 0.0;
1908 lightParms.Direction.x = 0.0;
1909 lightParms.Direction.y = 0.0;
1910 lightParms.Direction.z = 1.0;
1911 lightParms.Range = 0.0;
1912 lightParms.Falloff = 0.0;
1913 lightParms.Attenuation0 = 0.0;
1914 lightParms.Attenuation1 = 0.0;
1915 lightParms.Attenuation2 = 0.0;
1916 lightParms.Theta = 0.0;
1917 lightParms.Phi = 0.0;
1918 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1920 /* Search for it again! Should be fairly quick as near head of list */
1921 lightInfo = This->StateBlock->lights;
1922 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1923 if (lightInfo == NULL) {
1924 FIXME("Adding default lights has failed dismally\n");
1925 return D3DERR_INVALIDCALL;
1929 /* OK, we now have a light... */
1930 if (Enable == FALSE) {
1932 /* If we are disabling it, check it was enabled, and
1933 still only do something if it has assigned a glIndex (which it should have!) */
1934 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1935 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1936 ENTER_GL();
1937 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1938 checkGLcall("glDisable GL_LIGHT0+Index");
1939 LEAVE_GL();
1940 } else {
1941 TRACE("Nothing to do as light was not enabled\n");
1943 lightInfo->lightEnabled = FALSE;
1944 } else {
1946 /* We are enabling it. If it is enabled, its really simple */
1947 if (lightInfo->lightEnabled == TRUE) {
1948 /* nop */
1949 TRACE("Nothing to do as light was enabled\n");
1951 /* If it already has a glIndex, its still simple */
1952 } else if (lightInfo->glIndex != -1) {
1953 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1954 lightInfo->lightEnabled = TRUE;
1955 ENTER_GL();
1956 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1957 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1958 LEAVE_GL();
1960 /* Otherwise got to find space - lights are ordered gl indexes first */
1961 } else {
1962 PLIGHTINFOEL *bsf = NULL;
1963 PLIGHTINFOEL *pos = This->StateBlock->lights;
1964 PLIGHTINFOEL *prev = NULL;
1965 int Index= 0;
1966 int glIndex = -1;
1968 /* Try to minimize changes as much as possible */
1969 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1971 /* Try to remember which index can be replaced if necessary */
1972 if (bsf==NULL && pos->lightEnabled == FALSE) {
1973 /* Found a light we can replace, save as best replacement */
1974 bsf = pos;
1977 /* Step to next space */
1978 prev = pos;
1979 pos = pos->next;
1980 Index ++;
1983 /* If we have too many active lights, fail the call */
1984 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1985 FIXME("Program requests too many concurrent lights\n");
1986 return D3DERR_INVALIDCALL;
1988 /* If we have allocated all lights, but not all are enabled,
1989 reuse one which is not enabled */
1990 } else if (Index == This->maxConcurrentLights) {
1991 /* use bsf - Simply swap the new light and the BSF one */
1992 PLIGHTINFOEL *bsfNext = bsf->next;
1993 PLIGHTINFOEL *bsfPrev = bsf->prev;
1995 /* Sort out ends */
1996 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1997 if (bsf->prev != NULL) {
1998 bsf->prev->next = lightInfo;
1999 } else {
2000 This->StateBlock->lights = lightInfo;
2003 /* If not side by side, lots of chains to update */
2004 if (bsf->next != lightInfo) {
2005 lightInfo->prev->next = bsf;
2006 bsf->next->prev = lightInfo;
2007 bsf->next = lightInfo->next;
2008 bsf->prev = lightInfo->prev;
2009 lightInfo->next = bsfNext;
2010 lightInfo->prev = bsfPrev;
2012 } else {
2013 /* Simple swaps */
2014 bsf->prev = lightInfo;
2015 bsf->next = lightInfo->next;
2016 lightInfo->next = bsf;
2017 lightInfo->prev = bsfPrev;
2021 /* Update states */
2022 glIndex = bsf->glIndex;
2023 bsf->glIndex = -1;
2024 lightInfo->glIndex = glIndex;
2025 lightInfo->lightEnabled = TRUE;
2027 /* Finally set up the light in gl itself */
2028 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2029 ENTER_GL();
2030 setup_light(iface, glIndex, lightInfo);
2031 glEnable(GL_LIGHT0 + glIndex);
2032 checkGLcall("glEnable GL_LIGHT0 new setup");
2033 LEAVE_GL();
2035 /* If we reached the end of the allocated lights, with space in the
2036 gl lights, setup a new light */
2037 } else if (pos->glIndex == -1) {
2039 /* We reached the end of the allocated gl lights, so already
2040 know the index of the next one! */
2041 glIndex = Index;
2042 lightInfo->glIndex = glIndex;
2043 lightInfo->lightEnabled = TRUE;
2045 /* In an ideal world, its already in the right place */
2046 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2047 /* No need to move it */
2048 } else {
2049 /* Remove this light from the list */
2050 lightInfo->prev->next = lightInfo->next;
2051 if (lightInfo->next != NULL) {
2052 lightInfo->next->prev = lightInfo->prev;
2055 /* Add in at appropriate place (inbetween prev and pos) */
2056 lightInfo->prev = prev;
2057 lightInfo->next = pos;
2058 if (prev == NULL) {
2059 This->StateBlock->lights = lightInfo;
2060 } else {
2061 prev->next = lightInfo;
2063 if (pos != NULL) {
2064 pos->prev = lightInfo;
2068 /* Finally set up the light in gl itself */
2069 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2070 ENTER_GL();
2071 setup_light(iface, glIndex, lightInfo);
2072 glEnable(GL_LIGHT0 + glIndex);
2073 checkGLcall("glEnable GL_LIGHT0 new setup");
2074 LEAVE_GL();
2079 return D3D_OK;
2081 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2083 PLIGHTINFOEL *lightInfo = NULL;
2084 ICOM_THIS(IDirect3DDevice8Impl,iface);
2085 TRACE("(%p) : for idx(%ld)\n", This, Index);
2087 /* Locate the light in the live lights */
2088 lightInfo = This->StateBlock->lights;
2089 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2091 if (lightInfo == NULL) {
2092 TRACE("Light enabled state requested but light not defined\n");
2093 return D3DERR_INVALIDCALL;
2095 *pEnable = lightInfo->lightEnabled;
2096 return D3D_OK;
2098 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2099 ICOM_THIS(IDirect3DDevice8Impl,iface);
2100 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2102 /* Validate Index */
2103 if (Index >= GL_LIMITS(clipplanes)) {
2104 TRACE("Application has requested clipplane this device doesnt support\n");
2105 return D3DERR_INVALIDCALL;
2108 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2109 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2110 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2111 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2112 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2113 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2115 /* Handle recording of state blocks */
2116 if (This->isRecordingState) {
2117 TRACE("Recording... not performing anything\n");
2118 return D3D_OK;
2121 /* Apply it */
2123 ENTER_GL();
2125 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2126 glMatrixMode(GL_MODELVIEW);
2127 glPushMatrix();
2128 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2130 TRACE("Clipplane [%f,%f,%f,%f]\n",
2131 This->UpdateStateBlock->clipplane[Index][0],
2132 This->UpdateStateBlock->clipplane[Index][1],
2133 This->UpdateStateBlock->clipplane[Index][2],
2134 This->UpdateStateBlock->clipplane[Index][3]);
2135 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2136 checkGLcall("glClipPlane");
2138 glPopMatrix();
2140 LEAVE_GL();
2142 return D3D_OK;
2144 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2145 ICOM_THIS(IDirect3DDevice8Impl,iface);
2146 TRACE("(%p) : for idx %ld\n", This, Index);
2148 /* Validate Index */
2149 if (Index >= GL_LIMITS(clipplanes)) {
2150 TRACE("Application has requested clipplane this device doesnt support\n");
2151 return D3DERR_INVALIDCALL;
2154 pPlane[0] = This->StateBlock->clipplane[Index][0];
2155 pPlane[1] = This->StateBlock->clipplane[Index][1];
2156 pPlane[2] = This->StateBlock->clipplane[Index][2];
2157 pPlane[3] = This->StateBlock->clipplane[Index][3];
2158 return D3D_OK;
2160 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2161 ICOM_THIS(IDirect3DDevice8Impl,iface);
2162 DWORD OldValue = This->StateBlock->renderstate[State];
2164 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2165 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2166 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2167 This->UpdateStateBlock->renderstate[State] = Value;
2169 /* Handle recording of state blocks */
2170 if (This->isRecordingState) {
2171 TRACE("Recording... not performing anything\n");
2172 return D3D_OK;
2175 ENTER_GL();
2177 switch (State) {
2178 case D3DRS_FILLMODE :
2179 switch ((D3DFILLMODE) Value) {
2180 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2181 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2182 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2183 default:
2184 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2186 checkGLcall("glPolygonMode (fillmode)");
2187 break;
2189 case D3DRS_LIGHTING :
2190 if (Value) {
2191 glEnable(GL_LIGHTING);
2192 checkGLcall("glEnable GL_LIGHTING");
2193 } else {
2194 glDisable(GL_LIGHTING);
2195 checkGLcall("glDisable GL_LIGHTING");
2197 break;
2199 case D3DRS_ZENABLE :
2200 switch ((D3DZBUFFERTYPE) Value) {
2201 case D3DZB_FALSE:
2202 glDisable(GL_DEPTH_TEST);
2203 checkGLcall("glDisable GL_DEPTH_TEST");
2204 break;
2205 case D3DZB_TRUE:
2206 glEnable(GL_DEPTH_TEST);
2207 checkGLcall("glEnable GL_DEPTH_TEST");
2208 break;
2210 case D3DZB_USEW:
2211 default:
2212 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2214 break;
2216 case D3DRS_CULLMODE :
2218 /* If we are culling "back faces with clockwise vertices" then
2219 set front faces to be counter clockwise and enable culling
2220 of back faces */
2221 switch ((D3DCULL) Value) {
2222 case D3DCULL_NONE:
2223 glDisable(GL_CULL_FACE);
2224 checkGLcall("glDisable GL_CULL_FACE");
2225 break;
2226 case D3DCULL_CW:
2227 glEnable(GL_CULL_FACE);
2228 checkGLcall("glEnable GL_CULL_FACE");
2229 glFrontFace(GL_CCW);
2230 checkGLcall("glFrontFace GL_CCW");
2231 glCullFace(GL_BACK);
2232 break;
2233 case D3DCULL_CCW:
2234 glEnable(GL_CULL_FACE);
2235 checkGLcall("glEnable GL_CULL_FACE");
2236 glFrontFace(GL_CW);
2237 checkGLcall("glFrontFace GL_CW");
2238 glCullFace(GL_BACK);
2239 break;
2240 default:
2241 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2243 break;
2245 case D3DRS_SHADEMODE :
2246 switch ((D3DSHADEMODE) Value) {
2247 case D3DSHADE_FLAT:
2248 glShadeModel(GL_FLAT);
2249 checkGLcall("glShadeModel");
2250 break;
2251 case D3DSHADE_GOURAUD:
2252 glShadeModel(GL_SMOOTH);
2253 checkGLcall("glShadeModel");
2254 break;
2255 case D3DSHADE_PHONG:
2256 FIXME("D3DSHADE_PHONG isnt supported?\n");
2258 LEAVE_GL();
2259 return D3DERR_INVALIDCALL;
2260 default:
2261 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2263 break;
2265 case D3DRS_DITHERENABLE :
2266 if (Value) {
2267 glEnable(GL_DITHER);
2268 checkGLcall("glEnable GL_DITHER");
2269 } else {
2270 glDisable(GL_DITHER);
2271 checkGLcall("glDisable GL_DITHER");
2273 break;
2275 case D3DRS_ZWRITEENABLE :
2276 if (Value) {
2277 glDepthMask(1);
2278 checkGLcall("glDepthMask");
2279 } else {
2280 glDepthMask(0);
2281 checkGLcall("glDepthMask");
2283 break;
2285 case D3DRS_ZFUNC :
2287 int glParm = GL_LESS;
2289 switch ((D3DCMPFUNC) Value) {
2290 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2291 case D3DCMP_LESS: glParm=GL_LESS; break;
2292 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2293 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2294 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2295 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2296 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2297 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2298 default:
2299 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2301 glDepthFunc(glParm);
2302 checkGLcall("glDepthFunc");
2304 break;
2306 case D3DRS_AMBIENT :
2308 float col[4];
2309 D3DCOLORTOGLFLOAT4(Value, col);
2310 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2311 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2312 checkGLcall("glLightModel for MODEL_AMBIENT");
2315 break;
2317 case D3DRS_ALPHABLENDENABLE :
2318 if (Value) {
2319 glEnable(GL_BLEND);
2320 checkGLcall("glEnable GL_BLEND");
2321 } else {
2322 glDisable(GL_BLEND);
2323 checkGLcall("glDisable GL_BLEND");
2325 break;
2327 case D3DRS_SRCBLEND :
2328 case D3DRS_DESTBLEND :
2330 int newVal = GL_ZERO;
2331 switch (Value) {
2332 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2333 case D3DBLEND_ONE : newVal = GL_ONE; break;
2334 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2335 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2336 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2337 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2338 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2339 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2340 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2341 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2342 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2344 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2345 This->srcBlend = newVal;
2346 This->dstBlend = newVal;
2347 break;
2349 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2350 This->srcBlend = newVal;
2351 This->dstBlend = newVal;
2352 break;
2353 default:
2354 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2357 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2358 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2359 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2360 glBlendFunc(This->srcBlend, This->dstBlend);
2362 checkGLcall("glBlendFunc");
2364 break;
2366 case D3DRS_ALPHATESTENABLE :
2367 if (Value) {
2368 glEnable(GL_ALPHA_TEST);
2369 checkGLcall("glEnable GL_ALPHA_TEST");
2370 } else {
2371 glDisable(GL_ALPHA_TEST);
2372 checkGLcall("glDisable GL_ALPHA_TEST");
2374 break;
2376 case D3DRS_ALPHAFUNC :
2378 int glParm = GL_LESS;
2379 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2381 switch ((D3DCMPFUNC) Value) {
2382 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2383 case D3DCMP_LESS: glParm = GL_LESS; break;
2384 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2385 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2386 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2387 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2388 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2389 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2390 default:
2391 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2393 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2394 glAlphaFunc(glParm, ref);
2395 This->alphafunc = glParm;
2396 checkGLcall("glAlphaFunc");
2398 break;
2400 case D3DRS_ALPHAREF :
2402 int glParm = This->alphafunc;
2403 float ref = 1.0f;
2405 ref = ((float) Value) / 255.0f;
2406 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2407 glAlphaFunc(glParm, ref);
2408 checkGLcall("glAlphaFunc");
2410 break;
2412 case D3DRS_CLIPPLANEENABLE :
2413 case D3DRS_CLIPPING :
2415 /* Ensure we only do the changed clip planes */
2416 DWORD enable = 0xFFFFFFFF;
2417 DWORD disable = 0x00000000;
2419 /* If enabling / disabling all */
2420 if (State == D3DRS_CLIPPING) {
2421 if (Value) {
2422 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2423 disable = 0x00;
2424 } else {
2425 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2426 enable = 0x00;
2428 } else {
2429 enable = Value & ~OldValue;
2430 disable = ~Value & OldValue;
2433 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2434 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2435 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2436 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2437 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2438 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2440 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2441 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2442 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2443 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2444 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2445 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2447 break;
2449 case D3DRS_BLENDOP :
2451 int glParm = GL_FUNC_ADD;
2453 switch ((D3DBLENDOP) Value) {
2454 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2455 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2456 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2457 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2458 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2459 default:
2460 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2462 TRACE("glBlendEquation(%x)\n", glParm);
2463 glBlendEquation(glParm);
2464 checkGLcall("glBlendEquation");
2466 break;
2468 case D3DRS_TEXTUREFACTOR :
2470 int i;
2472 /* Note the texture color applies to all textures whereas
2473 GL_TEXTURE_ENV_COLOR applies to active only */
2474 float col[4];
2475 D3DCOLORTOGLFLOAT4(Value, col);
2476 /* Set the default alpha blend color */
2477 glBlendColor(col[0], col[1], col[2], col[3]);
2478 checkGLcall("glBlendColor");
2480 /* And now the default texture color as well */
2481 for (i = 0; i < GL_LIMITS(textures); i++) {
2483 /* Note the D3DRS value applies to all textures, but GL has one
2484 per texture, so apply it now ready to be used! */
2485 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2486 #if defined(GL_VERSION_1_3)
2487 glActiveTexture(GL_TEXTURE0 + i);
2488 #else
2489 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2490 #endif
2491 checkGLcall("Activate texture.. to update const color");
2492 } else if (i>0) {
2493 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2496 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2497 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2500 break;
2502 case D3DRS_SPECULARENABLE :
2504 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2505 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2506 specular color. This is wrong:
2507 Separate specular color means the specular colour is maintained separately, whereas
2508 single color means it is merged in. However in both cases they are being used to
2509 some extent.
2510 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2511 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2512 yet running 1.4!
2514 if (Value) {
2515 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2516 checkGLcall("glMaterialfv");
2517 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2518 glEnable(GL_COLOR_SUM_EXT);
2519 } else {
2520 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2522 checkGLcall("glEnable(GL_COLOR_SUM)");
2523 } else {
2524 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2526 /* for the case of enabled lighting: */
2527 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2528 checkGLcall("glMaterialfv");
2530 /* for the case of disabled lighting: */
2531 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2532 glDisable(GL_COLOR_SUM_EXT);
2533 } else {
2534 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2536 checkGLcall("glDisable(GL_COLOR_SUM)");
2539 break;
2541 case D3DRS_STENCILENABLE :
2542 if (Value) {
2543 glEnable(GL_STENCIL_TEST);
2544 checkGLcall("glEnable GL_STENCIL_TEST");
2545 } else {
2546 glDisable(GL_STENCIL_TEST);
2547 checkGLcall("glDisable GL_STENCIL_TEST");
2549 break;
2551 case D3DRS_STENCILFUNC :
2553 int glParm = GL_ALWAYS;
2554 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2555 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2557 switch ((D3DCMPFUNC) Value) {
2558 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2559 case D3DCMP_LESS: glParm=GL_LESS; break;
2560 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2561 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2562 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2563 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2564 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2565 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2566 default:
2567 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2569 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2570 This->stencilfunc = glParm;
2571 glStencilFunc(glParm, ref, mask);
2572 checkGLcall("glStencilFunc");
2574 break;
2576 case D3DRS_STENCILREF :
2578 int glParm = This->stencilfunc;
2579 int ref = 0;
2580 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2582 ref = Value;
2583 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2584 glStencilFunc(glParm, ref, mask);
2585 checkGLcall("glStencilFunc");
2587 break;
2589 case D3DRS_STENCILMASK :
2591 int glParm = This->stencilfunc;
2592 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2593 GLuint mask = Value;
2595 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2596 glStencilFunc(glParm, ref, mask);
2597 checkGLcall("glStencilFunc");
2599 break;
2601 case D3DRS_STENCILFAIL :
2603 GLenum fail ;
2604 GLenum zpass ;
2605 GLenum zfail ;
2607 fail = StencilOp(Value);
2608 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2609 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2610 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2611 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2613 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2614 glStencilOp(fail, zfail, zpass);
2615 checkGLcall("glStencilOp(fail, zfail, zpass);");
2617 break;
2618 case D3DRS_STENCILZFAIL :
2620 GLenum fail ;
2621 GLenum zpass ;
2622 GLenum zfail ;
2624 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2625 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2626 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2627 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2628 zfail = StencilOp(Value);
2630 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2631 glStencilOp(fail, zfail, zpass);
2632 checkGLcall("glStencilOp(fail, zfail, zpass);");
2634 break;
2635 case D3DRS_STENCILPASS :
2637 GLenum fail ;
2638 GLenum zpass ;
2639 GLenum zfail ;
2641 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2642 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2643 zpass = StencilOp(Value);
2644 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2645 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2647 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2648 glStencilOp(fail, zfail, zpass);
2649 checkGLcall("glStencilOp(fail, zfail, zpass);");
2651 break;
2653 case D3DRS_STENCILWRITEMASK :
2655 glStencilMask(Value);
2656 TRACE("glStencilMask(%lu)\n", Value);
2657 checkGLcall("glStencilMask");
2659 break;
2661 case D3DRS_FOGENABLE :
2663 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2664 glEnable(GL_FOG);
2665 checkGLcall("glEnable GL_FOG");
2666 } else {
2667 glDisable(GL_FOG);
2668 checkGLcall("glDisable GL_FOG");
2671 break;
2673 case D3DRS_FOGCOLOR :
2675 float col[4];
2676 D3DCOLORTOGLFLOAT4(Value, col);
2677 /* Set the default alpha blend color */
2678 glFogfv(GL_FOG_COLOR, &col[0]);
2679 checkGLcall("glFog GL_FOG_COLOR");
2681 break;
2683 case D3DRS_FOGTABLEMODE :
2685 switch (Value) {
2686 case D3DFOG_NONE: /* I don't know what to do here */ break;
2687 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2688 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2689 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2690 default:
2691 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2694 break;
2696 case D3DRS_FOGSTART :
2698 float *f = (float*) &Value;
2699 glFogfv(GL_FOG_START, f);
2700 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2701 TRACE("Fog Start == %f\n", *f);
2703 break;
2705 case D3DRS_FOGEND :
2707 float *f = (float*) &Value;
2708 glFogfv(GL_FOG_END, f);
2709 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2710 TRACE("Fog End == %f\n", *f);
2712 break;
2714 case D3DRS_FOGDENSITY :
2716 float *f = (float*) &Value;
2717 glFogfv(GL_FOG_DENSITY, f);
2718 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2720 break;
2722 case D3DRS_VERTEXBLEND :
2724 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2725 TRACE("Vertex Blending state to %ld\n", Value);
2727 break;
2729 case D3DRS_TWEENFACTOR :
2731 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2732 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2734 break;
2736 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2738 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2740 break;
2742 case D3DRS_COLORVERTEX :
2743 case D3DRS_DIFFUSEMATERIALSOURCE :
2744 case D3DRS_SPECULARMATERIALSOURCE :
2745 case D3DRS_AMBIENTMATERIALSOURCE :
2746 case D3DRS_EMISSIVEMATERIALSOURCE :
2748 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2750 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2751 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2752 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2753 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2754 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2755 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2757 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2758 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2759 Parm = GL_AMBIENT_AND_DIFFUSE;
2760 } else {
2761 Parm = GL_DIFFUSE;
2763 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2764 Parm = GL_AMBIENT;
2765 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2766 Parm = GL_EMISSION;
2767 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2768 Parm = GL_SPECULAR;
2769 } else {
2770 Parm = -1;
2773 if (Parm == -1) {
2774 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2775 } else {
2776 This->tracking_color = NEEDS_TRACKING;
2777 This->tracking_parm = Parm;
2780 } else {
2781 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2784 break;
2786 case D3DRS_LINEPATTERN :
2788 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2789 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2791 if (pattern->wRepeatFactor) {
2792 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2793 checkGLcall("glLineStipple(repeat, linepattern)");
2794 glEnable(GL_LINE_STIPPLE);
2795 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2796 } else {
2797 glDisable(GL_LINE_STIPPLE);
2798 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2801 break;
2803 case D3DRS_ZBIAS :
2805 if (Value) {
2806 TRACE("ZBias value %f\n", *((float*)&Value));
2807 glPolygonOffset(0, -*((float*)&Value));
2808 checkGLcall("glPolygonOffset(0, -Value)");
2809 glEnable(GL_POLYGON_OFFSET_FILL);
2810 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2811 glEnable(GL_POLYGON_OFFSET_LINE);
2812 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2813 glEnable(GL_POLYGON_OFFSET_POINT);
2814 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2815 } else {
2816 glDisable(GL_POLYGON_OFFSET_FILL);
2817 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2818 glDisable(GL_POLYGON_OFFSET_LINE);
2819 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2820 glDisable(GL_POLYGON_OFFSET_POINT);
2821 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2824 break;
2826 case D3DRS_NORMALIZENORMALS :
2827 if (Value) {
2828 glEnable(GL_NORMALIZE);
2829 checkGLcall("glEnable(GL_NORMALIZE);");
2830 } else {
2831 glDisable(GL_NORMALIZE);
2832 checkGLcall("glDisable(GL_NORMALIZE);");
2834 break;
2836 case D3DRS_POINTSIZE :
2837 TRACE("Set point size to %f\n", *((float*)&Value));
2838 glPointSize(*((float*)&Value));
2839 checkGLcall("glPointSize(...);");
2840 break;
2842 case D3DRS_POINTSIZE_MIN :
2843 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2844 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2845 checkGLcall("glPointParameterfEXT(...);");
2846 } else {
2847 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2849 break;
2851 case D3DRS_POINTSIZE_MAX :
2852 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2853 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2854 checkGLcall("glPointParameterfEXT(...);");
2855 } else {
2856 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2858 break;
2860 case D3DRS_POINTSCALE_A :
2861 case D3DRS_POINTSCALE_B :
2862 case D3DRS_POINTSCALE_C :
2863 case D3DRS_POINTSCALEENABLE :
2865 /* If enabled, supply the parameters, otherwise fall back to defaults */
2866 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2867 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2868 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2869 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2870 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2872 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2873 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2874 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2875 } else {
2876 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2878 } else {
2879 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2880 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2881 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2882 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2883 } else {
2884 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2887 break;
2890 case D3DRS_COLORWRITEENABLE :
2891 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2892 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2893 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2894 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2895 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2896 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
2897 Value & D3DCOLORWRITEENABLE_GREEN,
2898 Value & D3DCOLORWRITEENABLE_BLUE,
2899 Value & D3DCOLORWRITEENABLE_ALPHA);
2900 checkGLcall("glColorMask(...)");
2901 break;
2903 /* Unhandled yet...! */
2904 case D3DRS_LASTPIXEL :
2905 case D3DRS_ZVISIBLE :
2906 case D3DRS_EDGEANTIALIAS :
2907 case D3DRS_RANGEFOGENABLE :
2908 case D3DRS_WRAP0 :
2909 case D3DRS_WRAP1 :
2910 case D3DRS_WRAP2 :
2911 case D3DRS_WRAP3 :
2912 case D3DRS_WRAP4 :
2913 case D3DRS_WRAP5 :
2914 case D3DRS_WRAP6 :
2915 case D3DRS_WRAP7 :
2916 case D3DRS_FOGVERTEXMODE :
2917 case D3DRS_LOCALVIEWER :
2918 case D3DRS_SOFTWAREVERTEXPROCESSING :
2919 case D3DRS_POINTSPRITEENABLE :
2920 case D3DRS_MULTISAMPLEANTIALIAS :
2921 case D3DRS_MULTISAMPLEMASK :
2922 case D3DRS_PATCHEDGESTYLE :
2923 case D3DRS_PATCHSEGMENTS :
2924 case D3DRS_DEBUGMONITORTOKEN :
2925 case D3DRS_POSITIONORDER :
2926 case D3DRS_NORMALORDER :
2927 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2928 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2929 break;
2930 default:
2931 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2934 LEAVE_GL();
2936 return D3D_OK;
2938 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2939 ICOM_THIS(IDirect3DDevice8Impl,iface);
2940 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2941 *pValue = This->StateBlock->renderstate[State];
2942 return D3D_OK;
2944 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2945 ICOM_THIS(IDirect3DDevice8Impl,iface);
2947 TRACE("(%p)\n", This);
2949 return IDirect3DDeviceImpl_BeginStateBlock(This);
2951 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2952 IDirect3DStateBlockImpl* pSB;
2953 ICOM_THIS(IDirect3DDevice8Impl,iface);
2954 HRESULT res;
2956 TRACE("(%p)\n", This);
2958 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2959 *pToken = (DWORD) pSB;
2960 return res;
2963 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2964 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2965 ICOM_THIS(IDirect3DDevice8Impl,iface);
2967 TRACE("(%p)\n", This);
2969 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2972 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2973 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2974 ICOM_THIS(IDirect3DDevice8Impl,iface);
2976 TRACE("(%p)\n", This);
2978 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2980 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2981 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2982 ICOM_THIS(IDirect3DDevice8Impl,iface);
2984 TRACE("(%p)\n", This);
2986 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2989 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2990 IDirect3DStateBlockImpl* pSB;
2991 ICOM_THIS(IDirect3DDevice8Impl,iface);
2992 HRESULT res;
2994 TRACE("(%p) : for type %d\n", This, Type);
2996 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
2997 *pToken = (DWORD) pSB;
2998 return res;
3001 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3002 ICOM_THIS(IDirect3DDevice8Impl,iface);
3003 FIXME("(%p) : stub\n", This); return D3D_OK;
3005 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3006 ICOM_THIS(IDirect3DDevice8Impl,iface);
3007 FIXME("(%p) : stub\n", This); return D3D_OK;
3009 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3010 ICOM_THIS(IDirect3DDevice8Impl,iface);
3011 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3012 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3013 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3014 return D3D_OK;
3016 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3018 IDirect3DBaseTexture8 *oldTxt;
3019 BOOL reapplyStates = TRUE;
3020 DWORD oldTextureDimensions = -1;
3021 DWORD reapplyFlags = 0;
3023 ICOM_THIS(IDirect3DDevice8Impl,iface);
3024 D3DRESOURCETYPE textureType;
3026 oldTxt = This->UpdateStateBlock->textures[Stage];
3027 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3029 /* Reject invalid texture units */
3030 if (Stage >= GL_LIMITS(textures)) {
3031 TRACE("Attempt to access invalid texture rejected\n");
3032 return D3DERR_INVALIDCALL;
3035 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3036 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3037 This->UpdateStateBlock->textures[Stage] = pTexture;
3039 /* Handle recording of state blocks */
3040 if (This->isRecordingState) {
3041 TRACE("Recording... not performing anything\n");
3042 return D3D_OK;
3045 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3046 ENTER_GL();
3048 /* Make appropriate texture active */
3049 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3050 #if defined(GL_VERSION_1_3)
3051 glActiveTexture(GL_TEXTURE0 + Stage);
3052 #else
3053 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3054 #endif
3055 checkGLcall("glActiveTextureARB");
3056 } else if (Stage>0) {
3057 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3060 /* Decrement the count of the previous texture */
3061 if (NULL != oldTxt) {
3062 IDirect3DBaseTexture8Impl_Release(oldTxt);
3065 if (NULL != pTexture) {
3066 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3068 /* Now setup the texture appropraitly */
3069 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3071 if (textureType == D3DRTYPE_TEXTURE) {
3072 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3073 TRACE("Skipping setting texture as old == new\n");
3074 reapplyStates = FALSE;
3075 } else {
3076 /* Standard 2D texture */
3077 TRACE("Standard 2d texture\n");
3078 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3080 /* Load up the texture now */
3081 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3083 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3084 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3085 TRACE("Skipping setting texture as old == new\n");
3086 reapplyStates = FALSE;
3087 } else {
3088 /* Standard 3D (volume) texture */
3089 TRACE("Standard 3d texture\n");
3090 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3092 /* Load up the texture now */
3093 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3095 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3096 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3097 TRACE("Skipping setting texture as old == new\n");
3098 reapplyStates = FALSE;
3099 } else {
3100 /* Standard Cube texture */
3101 TRACE("Standard Cube texture\n");
3102 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3104 /* Load up the texture now */
3105 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3107 } else {
3108 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3110 } else {
3111 TRACE("Setting to no texture (ie default texture)\n");
3112 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3113 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3114 checkGLcall("glBindTexture");
3115 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3118 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3119 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3120 glDisable(oldTextureDimensions);
3121 checkGLcall("Disable oldTextureDimensions");
3122 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3123 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3124 checkGLcall("Disable new texture dimensions");
3127 /* If Alpha arg1 is texture then handle the special case when there changes between a
3128 texture and no texture - See comments in set_tex_op */
3129 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3130 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3132 reapplyFlags |= REAPPLY_ALPHAOP;
3137 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3138 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3139 if (reapplyStates) {
3140 setupTextureStates(iface, Stage, reapplyFlags);
3143 LEAVE_GL();
3145 return D3D_OK;
3148 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3149 ICOM_THIS(IDirect3DDevice8Impl,iface);
3150 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3151 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3152 return D3D_OK;
3155 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3156 ICOM_THIS(IDirect3DDevice8Impl,iface);
3158 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3160 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3162 /* Reject invalid texture units */
3163 if (Stage >= GL_LIMITS(textures)) {
3164 TRACE("Attempt to access invalid texture rejected\n");
3165 return D3DERR_INVALIDCALL;
3168 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3169 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3170 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3172 /* Handle recording of state blocks */
3173 if (This->isRecordingState) {
3174 TRACE("Recording... not performing anything\n");
3175 return D3D_OK;
3178 ENTER_GL();
3180 /* Make appropriate texture active */
3181 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3182 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3183 #if defined(GL_VERSION_1_3)
3184 glActiveTexture(GL_TEXTURE0 + Stage);
3185 vcheckGLcall("glActiveTexture");
3186 #else
3187 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3188 vcheckGLcall("glActiveTextureARB");
3189 #endif
3190 } else if (Stage > 0) {
3191 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3194 switch (Type) {
3196 case D3DTSS_MINFILTER :
3197 case D3DTSS_MIPFILTER :
3199 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3200 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3201 GLint realVal = GL_LINEAR;
3203 if (ValueMIN == D3DTEXF_POINT) {
3204 /* GL_NEAREST_* */
3205 if (ValueMIP == D3DTEXF_POINT) {
3206 realVal = GL_NEAREST_MIPMAP_NEAREST;
3207 } else if (ValueMIP == D3DTEXF_LINEAR) {
3208 realVal = GL_NEAREST_MIPMAP_LINEAR;
3209 } else if (ValueMIP == D3DTEXF_NONE) {
3210 realVal = GL_NEAREST;
3211 } else {
3212 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3213 realVal = GL_NEAREST_MIPMAP_LINEAR;
3215 } else if (ValueMIN == D3DTEXF_LINEAR) {
3216 /* GL_LINEAR_* */
3217 if (ValueMIP == D3DTEXF_POINT) {
3218 realVal = GL_LINEAR_MIPMAP_NEAREST;
3219 } else if (ValueMIP == D3DTEXF_LINEAR) {
3220 realVal = GL_LINEAR_MIPMAP_LINEAR;
3221 } else if (ValueMIP == D3DTEXF_NONE) {
3222 realVal = GL_LINEAR;
3223 } else {
3224 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3225 realVal = GL_LINEAR_MIPMAP_LINEAR;
3227 } else if (ValueMIN == D3DTEXF_NONE) {
3228 /* Doesnt really make sense - Windows just seems to disable
3229 mipmapping when this occurs */
3230 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3231 realVal = GL_LINEAR;
3233 } else {
3234 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3235 realVal = GL_LINEAR_MIPMAP_LINEAR;
3238 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3239 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3240 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3242 break;
3244 case D3DTSS_MAXANISOTROPY :
3246 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3247 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3248 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3251 break;
3253 case D3DTSS_MAGFILTER :
3254 if (Value == D3DTEXF_POINT) {
3255 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3256 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3257 } else if (Value == D3DTEXF_LINEAR) {
3258 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3259 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3260 } else {
3261 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3263 break;
3265 case D3DTSS_ALPHAOP :
3266 case D3DTSS_COLOROP :
3269 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3270 /* TODO: Disable by making this and all later levels disabled */
3271 glDisable(GL_TEXTURE_1D);
3272 checkGLcall("Disable GL_TEXTURE_1D");
3273 glDisable(GL_TEXTURE_2D);
3274 checkGLcall("Disable GL_TEXTURE_2D");
3275 glDisable(GL_TEXTURE_3D);
3276 checkGLcall("Disable GL_TEXTURE_3D");
3277 break; /* Dont bother setting the texture operations */
3278 } else {
3279 /* Enable only the appropriate texture dimension */
3280 if (Type == D3DTSS_COLOROP) {
3281 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3282 glEnable(GL_TEXTURE_1D);
3283 checkGLcall("Enable GL_TEXTURE_1D");
3284 } else {
3285 glDisable(GL_TEXTURE_1D);
3286 checkGLcall("Disable GL_TEXTURE_1D");
3288 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3289 glEnable(GL_TEXTURE_2D);
3290 checkGLcall("Enable GL_TEXTURE_2D");
3291 } else {
3292 glDisable(GL_TEXTURE_2D);
3293 checkGLcall("Disable GL_TEXTURE_2D");
3295 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3296 glEnable(GL_TEXTURE_3D);
3297 checkGLcall("Enable GL_TEXTURE_3D");
3298 } else {
3299 glDisable(GL_TEXTURE_3D);
3300 checkGLcall("Disable GL_TEXTURE_3D");
3302 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3303 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3304 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3305 } else {
3306 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3307 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3311 /* Drop through... (Except disable case) */
3312 case D3DTSS_COLORARG0 :
3313 case D3DTSS_COLORARG1 :
3314 case D3DTSS_COLORARG2 :
3315 case D3DTSS_ALPHAARG0 :
3316 case D3DTSS_ALPHAARG1 :
3317 case D3DTSS_ALPHAARG2 :
3319 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3320 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3321 if (isAlphaArg) {
3322 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3323 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3324 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3325 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3326 } else {
3327 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3328 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3329 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3330 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3333 break;
3336 case D3DTSS_ADDRESSU :
3337 case D3DTSS_ADDRESSV :
3338 case D3DTSS_ADDRESSW :
3340 GLint wrapParm = GL_REPEAT;
3341 switch (Value) {
3342 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3343 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3344 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3345 #if defined(GL_VERSION_1_4)
3346 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3347 #elif defined(GL_ARB_texture_mirrored_repeat)
3348 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3349 #else
3350 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3351 #endif
3352 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3353 default:
3354 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3355 wrapParm = GL_REPEAT;
3358 switch (Type) {
3359 case D3DTSS_ADDRESSU:
3360 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3361 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3362 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3363 break;
3364 case D3DTSS_ADDRESSV:
3365 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3366 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3367 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3368 break;
3369 case D3DTSS_ADDRESSW:
3370 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3371 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3372 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3373 break;
3374 default: /* nop */
3375 break; /** stupic compilator */
3378 break;
3380 case D3DTSS_BORDERCOLOR :
3382 float col[4];
3383 D3DCOLORTOGLFLOAT4(Value, col);
3384 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3385 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3386 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3388 break;
3390 case D3DTSS_TEXCOORDINDEX :
3392 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3394 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3395 one flag, you can still specify an index value, which the system uses to
3396 determine the texture wrapping mode.
3397 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3398 means use the vertex position (camera-space) as the input texture coordinates
3399 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3400 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3401 to the TEXCOORDINDEX value */
3403 /**
3404 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3406 switch (Value & 0xFFFF0000) {
3407 case D3DTSS_TCI_PASSTHRU:
3408 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3409 glDisable(GL_TEXTURE_GEN_S);
3410 glDisable(GL_TEXTURE_GEN_T);
3411 glDisable(GL_TEXTURE_GEN_R);
3412 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3413 break;
3415 case D3DTSS_TCI_CAMERASPACEPOSITION:
3416 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3417 as the input texture coordinates for this stage's texture transformation. This
3418 equates roughly to EYE_LINEAR */
3420 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3421 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3422 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3423 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3424 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3426 glMatrixMode(GL_MODELVIEW);
3427 glPushMatrix();
3428 glLoadIdentity();
3429 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3430 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3431 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3432 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3433 glPopMatrix();
3435 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3436 glEnable(GL_TEXTURE_GEN_S);
3437 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3438 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3439 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3440 glEnable(GL_TEXTURE_GEN_T);
3441 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3442 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3443 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3444 glEnable(GL_TEXTURE_GEN_R);
3445 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3446 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3447 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3449 break;
3451 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3452 case D3DTSS_TCI_CAMERASPACENORMAL:
3454 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3455 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3456 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3457 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3458 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3460 glMatrixMode(GL_MODELVIEW);
3461 glPushMatrix();
3462 glLoadIdentity();
3463 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3464 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3465 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3466 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3467 glPopMatrix();
3469 glEnable(GL_TEXTURE_GEN_S);
3470 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3471 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3472 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3473 glEnable(GL_TEXTURE_GEN_T);
3474 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3475 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3476 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3477 glEnable(GL_TEXTURE_GEN_R);
3478 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3479 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3480 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3482 break;
3483 #endif
3485 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3486 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3489 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3490 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3491 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3492 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3493 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3495 glMatrixMode(GL_MODELVIEW);
3496 glPushMatrix();
3497 glLoadIdentity();
3498 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3499 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3500 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3501 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3502 glPopMatrix();
3504 glEnable(GL_TEXTURE_GEN_S);
3505 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3506 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3507 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3508 glEnable(GL_TEXTURE_GEN_T);
3509 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3510 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3511 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3512 glEnable(GL_TEXTURE_GEN_R);
3513 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3514 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3515 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3517 break;
3518 #endif
3520 /* Unhandled types: */
3521 default:
3522 /* Todo: */
3523 /* ? disable GL_TEXTURE_GEN_n ? */
3524 glDisable(GL_TEXTURE_GEN_S);
3525 glDisable(GL_TEXTURE_GEN_T);
3526 glDisable(GL_TEXTURE_GEN_R);
3527 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3528 break;
3531 break;
3533 /* Unhandled */
3534 case D3DTSS_BUMPENVMAT00 :
3535 case D3DTSS_BUMPENVMAT01 :
3536 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3537 break;
3538 case D3DTSS_BUMPENVMAT10 :
3539 case D3DTSS_BUMPENVMAT11 :
3540 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3541 break;
3543 case D3DTSS_TEXTURETRANSFORMFLAGS :
3544 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3545 break;
3547 case D3DTSS_MIPMAPLODBIAS :
3548 case D3DTSS_MAXMIPLEVEL :
3549 case D3DTSS_BUMPENVLSCALE :
3550 case D3DTSS_BUMPENVLOFFSET :
3551 case D3DTSS_RESULTARG :
3552 default:
3553 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3554 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3557 LEAVE_GL();
3559 return D3D_OK;
3561 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3562 ICOM_THIS(IDirect3DDevice8Impl,iface);
3563 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3564 return D3D_OK;
3566 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3567 ICOM_THIS(IDirect3DDevice8Impl,iface);
3568 FIXME("(%p) : stub\n", This);
3569 return D3D_OK;
3571 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3572 ICOM_THIS(IDirect3DDevice8Impl,iface);
3573 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3574 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3575 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3576 return D3D_OK;
3578 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3579 ICOM_THIS(IDirect3DDevice8Impl,iface);
3580 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3581 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3582 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3583 return D3D_OK;
3585 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3586 ICOM_THIS(IDirect3DDevice8Impl,iface);
3587 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3588 This->currentPalette = PaletteNumber;
3590 #if defined(GL_EXT_paletted_texture)
3591 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3593 ENTER_GL();
3595 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3596 GL_RGBA, /* internal format */
3597 256, /* table size */
3598 GL_RGBA, /* table format */
3599 GL_UNSIGNED_BYTE, /* table type */
3600 This->palettes[PaletteNumber]);
3601 checkGLcall("glColorTableEXT");
3603 LEAVE_GL();
3605 } else {
3606 /* Delayed palette handling ... waiting for software emulation into preload code */
3608 #endif
3609 return D3D_OK;
3611 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3612 ICOM_THIS(IDirect3DDevice8Impl,iface);
3613 *PaletteNumber = This->currentPalette;
3614 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3615 return D3D_OK;
3617 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3619 ICOM_THIS(IDirect3DDevice8Impl,iface);
3620 This->StateBlock->streamIsUP = FALSE;
3622 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3623 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3625 return D3D_OK;
3627 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3628 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3629 UINT idxStride = 2;
3630 IDirect3DIndexBuffer8 *pIB;
3631 D3DINDEXBUFFER_DESC IdxBufDsc;
3633 ICOM_THIS(IDirect3DDevice8Impl,iface);
3634 pIB = This->StateBlock->pIndexData;
3635 This->StateBlock->streamIsUP = FALSE;
3637 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3638 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3639 minIndex, NumVertices, startIndex, primCount);
3641 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3642 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3643 idxStride = 2;
3644 } else {
3645 idxStride = 4;
3648 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3649 minIndex);
3651 return D3D_OK;
3653 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3654 ICOM_THIS(IDirect3DDevice8Impl,iface);
3656 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3657 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3659 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3661 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3662 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3663 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3664 This->StateBlock->streamIsUP = TRUE;
3665 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3666 This->StateBlock->stream_stride[0] = 0;
3667 This->StateBlock->stream_source[0] = NULL;
3669 /*stream zero settings set to null at end */
3670 return D3D_OK;
3672 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3673 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3674 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3675 UINT VertexStreamZeroStride) {
3676 int idxStride;
3677 ICOM_THIS(IDirect3DDevice8Impl,iface);
3678 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3679 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3681 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3682 if (IndexDataFormat == D3DFMT_INDEX16) {
3683 idxStride = 2;
3684 } else {
3685 idxStride = 4;
3688 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3689 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3690 This->StateBlock->streamIsUP = TRUE;
3691 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3692 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3694 /*stream zero settings set to null at end */
3695 This->StateBlock->stream_source[0] = NULL;
3696 This->StateBlock->stream_stride[0] = 0;
3697 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3699 return D3D_OK;
3701 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3702 ICOM_THIS(IDirect3DDevice8Impl,iface);
3703 FIXME("(%p) : stub\n", This); return D3D_OK;
3705 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3706 ICOM_THIS(IDirect3DDevice8Impl,iface);
3707 IDirect3DVertexShaderImpl* object;
3708 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3709 HRESULT res;
3710 UINT i;
3712 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3713 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3714 return D3DERR_INVALIDCALL;
3716 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3717 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3718 return D3DERR_OUTOFVIDEOMEMORY;
3721 /** Create the Vertex Shader */
3722 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3723 /** TODO: check FAILED(res) */
3725 /** Create and Bind the Vertex Shader Declaration */
3726 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3727 /** TODO: check FAILED(res) */
3729 VertexShaders[i] = object;
3730 VertexShaderDeclarations[i] = attached_decl;
3731 *pHandle = VS_HIGHESTFIXEDFXF + i;
3732 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3734 return D3D_OK;
3736 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3737 ICOM_THIS(IDirect3DDevice8Impl,iface);
3739 This->UpdateStateBlock->VertexShader = Handle;
3740 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3741 This->UpdateStateBlock->Set.vertexShader = TRUE;
3743 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3744 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3745 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3746 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3747 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3748 } else { /* use a fvf, so desactivate the vshader decl */
3749 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3750 This->UpdateStateBlock->vertexShaderDecl = NULL;
3751 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3752 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3754 /* Handle recording of state blocks */
3755 if (This->isRecordingState) {
3756 TRACE("Recording... not performing anything\n");
3757 return D3D_OK;
3760 * TODO: merge HAL shaders context switching from prototype
3762 return D3D_OK;
3764 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3765 ICOM_THIS(IDirect3DDevice8Impl,iface);
3766 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3767 *pHandle = This->StateBlock->VertexShader;
3768 return D3D_OK;
3771 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3772 ICOM_THIS(IDirect3DDevice8Impl,iface);
3773 IDirect3DVertexShaderImpl* object;
3774 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3776 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3777 return D3DERR_INVALIDCALL;
3781 * Delete Vertex Shader
3783 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3784 if (NULL == object) {
3785 return D3DERR_INVALIDCALL;
3787 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3788 /* TODO: check validity of object */
3789 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3790 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3791 HeapFree(GetProcessHeap(), 0, (void *)object);
3792 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3795 * Delete Vertex Shader Declaration
3797 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3798 if (NULL == attached_decl) {
3799 return D3DERR_INVALIDCALL;
3801 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3802 /* TODO: check validity of object */
3803 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3804 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3805 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3807 return D3D_OK;
3810 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3811 ICOM_THIS(IDirect3DDevice8Impl,iface);
3813 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3814 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3815 return D3DERR_INVALIDCALL;
3817 if (NULL == pConstantData) {
3818 return D3DERR_INVALIDCALL;
3820 if (ConstantCount > 1) {
3821 FLOAT* f = (FLOAT*)pConstantData;
3822 UINT i;
3823 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3824 for (i = 0; i < ConstantCount; ++i) {
3825 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3826 f += 4;
3828 } else {
3829 FLOAT* f = (FLOAT*) pConstantData;
3830 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3832 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3833 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3834 return D3D_OK;
3836 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3837 ICOM_THIS(IDirect3DDevice8Impl,iface);
3839 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3840 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3841 return D3DERR_INVALIDCALL;
3843 if (NULL == pConstantData) {
3844 return D3DERR_INVALIDCALL;
3846 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3847 return D3D_OK;
3849 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3850 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3851 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3853 attached_decl = VERTEX_SHADER_DECL(Handle);
3854 if (NULL == attached_decl) {
3855 return D3DERR_INVALIDCALL;
3857 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3859 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3860 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3861 IDirect3DVertexShaderImpl* object;
3863 object = VERTEX_SHADER(Handle);
3864 if (NULL == object) {
3865 return D3DERR_INVALIDCALL;
3867 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3870 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3871 ICOM_THIS(IDirect3DDevice8Impl,iface);
3872 IDirect3DIndexBuffer8 *oldIdxs;
3874 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3875 oldIdxs = This->StateBlock->pIndexData;
3877 This->UpdateStateBlock->Changed.Indices = TRUE;
3878 This->UpdateStateBlock->Set.Indices = TRUE;
3879 This->UpdateStateBlock->pIndexData = pIndexData;
3880 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3882 /* Handle recording of state blocks */
3883 if (This->isRecordingState) {
3884 TRACE("Recording... not performing anything\n");
3885 return D3D_OK;
3888 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3889 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3890 return D3D_OK;
3892 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3893 ICOM_THIS(IDirect3DDevice8Impl,iface);
3894 FIXME("(%p) : stub\n", This);
3896 *ppIndexData = This->StateBlock->pIndexData;
3897 /* up ref count on ppindexdata */
3898 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3899 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3901 return D3D_OK;
3903 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3904 ICOM_THIS(IDirect3DDevice8Impl,iface);
3905 IDirect3DPixelShaderImpl* object;
3906 HRESULT res;
3907 UINT i;
3909 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3910 if (NULL == pFunction || NULL == pHandle) {
3911 return D3DERR_INVALIDCALL;
3913 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3914 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3915 return D3DERR_OUTOFVIDEOMEMORY;
3918 /** Create the Pixel Shader */
3919 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3920 if (SUCCEEDED(res)) {
3921 PixelShaders[i] = object;
3922 *pHandle = VS_HIGHESTFIXEDFXF + i;
3923 return D3D_OK;
3925 *pHandle = 0xFFFFFFFF;
3926 return res;
3928 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3929 ICOM_THIS(IDirect3DDevice8Impl,iface);
3931 This->UpdateStateBlock->PixelShader = Handle;
3932 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3933 This->UpdateStateBlock->Set.pixelShader = TRUE;
3935 /* Handle recording of state blocks */
3936 if (This->isRecordingState) {
3937 TRACE_(d3d_shader)("Recording... not performing anything\n");
3938 return D3D_OK;
3941 /* FIXME: Quieten when not being used */
3942 if (Handle != 0) {
3943 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3944 } else {
3945 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3948 return D3D_OK;
3950 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3951 ICOM_THIS(IDirect3DDevice8Impl,iface);
3952 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3953 *pHandle = This->StateBlock->PixelShader;
3954 return D3D_OK;
3957 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3958 ICOM_THIS(IDirect3DDevice8Impl,iface);
3959 IDirect3DPixelShaderImpl* object;
3961 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3962 return D3DERR_INVALIDCALL;
3964 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3965 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3966 /* TODO: check validity of object before free */
3967 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3968 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3969 HeapFree(GetProcessHeap(), 0, (void *)object);
3970 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3972 return D3D_OK;
3975 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3976 ICOM_THIS(IDirect3DDevice8Impl,iface);
3978 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3979 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3980 return D3DERR_INVALIDCALL;
3982 if (NULL == pConstantData) {
3983 return D3DERR_INVALIDCALL;
3985 if (ConstantCount > 1) {
3986 FLOAT* f = (FLOAT*)pConstantData;
3987 UINT i;
3988 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3989 for (i = 0; i < ConstantCount; ++i) {
3990 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3991 f += 4;
3993 } else {
3994 FLOAT* f = (FLOAT*) pConstantData;
3995 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3997 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
3998 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3999 return D3D_OK;
4001 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4002 ICOM_THIS(IDirect3DDevice8Impl,iface);
4004 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4005 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4006 return D3DERR_INVALIDCALL;
4008 if (NULL == pConstantData) {
4009 return D3DERR_INVALIDCALL;
4011 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4012 return D3D_OK;
4014 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4015 IDirect3DPixelShaderImpl* object;
4017 object = PIXEL_SHADER(Handle);
4018 if (NULL == object) {
4019 return D3DERR_INVALIDCALL;
4021 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4023 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4024 ICOM_THIS(IDirect3DDevice8Impl,iface);
4025 FIXME("(%p) : stub\n", This); return D3D_OK;
4027 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4028 ICOM_THIS(IDirect3DDevice8Impl,iface);
4029 FIXME("(%p) : stub\n", This); return D3D_OK;
4031 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4032 ICOM_THIS(IDirect3DDevice8Impl,iface);
4033 FIXME("(%p) : stub\n", This); return D3D_OK;
4036 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4037 IDirect3DVertexBuffer8 *oldSrc;
4038 ICOM_THIS(IDirect3DDevice8Impl,iface);
4040 oldSrc = This->StateBlock->stream_source[StreamNumber];
4041 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4043 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4044 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4045 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4046 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4048 /* Handle recording of state blocks */
4049 if (This->isRecordingState) {
4050 TRACE("Recording... not performing anything\n");
4051 return D3D_OK;
4054 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4055 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4056 return D3D_OK;
4058 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4059 ICOM_THIS(IDirect3DDevice8Impl,iface);
4060 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4061 *pStream = This->StateBlock->stream_source[StreamNumber];
4062 *pStride = This->StateBlock->stream_stride[StreamNumber];
4063 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4064 return D3D_OK;
4068 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4070 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4071 IDirect3DDevice8Impl_QueryInterface,
4072 IDirect3DDevice8Impl_AddRef,
4073 IDirect3DDevice8Impl_Release,
4074 IDirect3DDevice8Impl_TestCooperativeLevel,
4075 IDirect3DDevice8Impl_GetAvailableTextureMem,
4076 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4077 IDirect3DDevice8Impl_GetDirect3D,
4078 IDirect3DDevice8Impl_GetDeviceCaps,
4079 IDirect3DDevice8Impl_GetDisplayMode,
4080 IDirect3DDevice8Impl_GetCreationParameters,
4081 IDirect3DDevice8Impl_SetCursorProperties,
4082 IDirect3DDevice8Impl_SetCursorPosition,
4083 IDirect3DDevice8Impl_ShowCursor,
4084 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4085 IDirect3DDevice8Impl_Reset,
4086 IDirect3DDevice8Impl_Present,
4087 IDirect3DDevice8Impl_GetBackBuffer,
4088 IDirect3DDevice8Impl_GetRasterStatus,
4089 IDirect3DDevice8Impl_SetGammaRamp,
4090 IDirect3DDevice8Impl_GetGammaRamp,
4091 IDirect3DDevice8Impl_CreateTexture,
4092 IDirect3DDevice8Impl_CreateVolumeTexture,
4093 IDirect3DDevice8Impl_CreateCubeTexture,
4094 IDirect3DDevice8Impl_CreateVertexBuffer,
4095 IDirect3DDevice8Impl_CreateIndexBuffer,
4096 IDirect3DDevice8Impl_CreateRenderTarget,
4097 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4098 IDirect3DDevice8Impl_CreateImageSurface,
4099 IDirect3DDevice8Impl_CopyRects,
4100 IDirect3DDevice8Impl_UpdateTexture,
4101 IDirect3DDevice8Impl_GetFrontBuffer,
4102 IDirect3DDevice8Impl_SetRenderTarget,
4103 IDirect3DDevice8Impl_GetRenderTarget,
4104 IDirect3DDevice8Impl_GetDepthStencilSurface,
4105 IDirect3DDevice8Impl_BeginScene,
4106 IDirect3DDevice8Impl_EndScene,
4107 IDirect3DDevice8Impl_Clear,
4108 IDirect3DDevice8Impl_SetTransform,
4109 IDirect3DDevice8Impl_GetTransform,
4110 IDirect3DDevice8Impl_MultiplyTransform,
4111 IDirect3DDevice8Impl_SetViewport,
4112 IDirect3DDevice8Impl_GetViewport,
4113 IDirect3DDevice8Impl_SetMaterial,
4114 IDirect3DDevice8Impl_GetMaterial,
4115 IDirect3DDevice8Impl_SetLight,
4116 IDirect3DDevice8Impl_GetLight,
4117 IDirect3DDevice8Impl_LightEnable,
4118 IDirect3DDevice8Impl_GetLightEnable,
4119 IDirect3DDevice8Impl_SetClipPlane,
4120 IDirect3DDevice8Impl_GetClipPlane,
4121 IDirect3DDevice8Impl_SetRenderState,
4122 IDirect3DDevice8Impl_GetRenderState,
4123 IDirect3DDevice8Impl_BeginStateBlock,
4124 IDirect3DDevice8Impl_EndStateBlock,
4125 IDirect3DDevice8Impl_ApplyStateBlock,
4126 IDirect3DDevice8Impl_CaptureStateBlock,
4127 IDirect3DDevice8Impl_DeleteStateBlock,
4128 IDirect3DDevice8Impl_CreateStateBlock,
4129 IDirect3DDevice8Impl_SetClipStatus,
4130 IDirect3DDevice8Impl_GetClipStatus,
4131 IDirect3DDevice8Impl_GetTexture,
4132 IDirect3DDevice8Impl_SetTexture,
4133 IDirect3DDevice8Impl_GetTextureStageState,
4134 IDirect3DDevice8Impl_SetTextureStageState,
4135 IDirect3DDevice8Impl_ValidateDevice,
4136 IDirect3DDevice8Impl_GetInfo,
4137 IDirect3DDevice8Impl_SetPaletteEntries,
4138 IDirect3DDevice8Impl_GetPaletteEntries,
4139 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4140 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4141 IDirect3DDevice8Impl_DrawPrimitive,
4142 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4143 IDirect3DDevice8Impl_DrawPrimitiveUP,
4144 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4145 IDirect3DDevice8Impl_ProcessVertices,
4146 IDirect3DDevice8Impl_CreateVertexShader,
4147 IDirect3DDevice8Impl_SetVertexShader,
4148 IDirect3DDevice8Impl_GetVertexShader,
4149 IDirect3DDevice8Impl_DeleteVertexShader,
4150 IDirect3DDevice8Impl_SetVertexShaderConstant,
4151 IDirect3DDevice8Impl_GetVertexShaderConstant,
4152 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4153 IDirect3DDevice8Impl_GetVertexShaderFunction,
4154 IDirect3DDevice8Impl_SetStreamSource,
4155 IDirect3DDevice8Impl_GetStreamSource,
4156 IDirect3DDevice8Impl_SetIndices,
4157 IDirect3DDevice8Impl_GetIndices,
4158 IDirect3DDevice8Impl_CreatePixelShader,
4159 IDirect3DDevice8Impl_SetPixelShader,
4160 IDirect3DDevice8Impl_GetPixelShader,
4161 IDirect3DDevice8Impl_DeletePixelShader,
4162 IDirect3DDevice8Impl_SetPixelShaderConstant,
4163 IDirect3DDevice8Impl_GetPixelShaderConstant,
4164 IDirect3DDevice8Impl_GetPixelShaderFunction,
4165 IDirect3DDevice8Impl_DrawRectPatch,
4166 IDirect3DDevice8Impl_DrawTriPatch,
4167 IDirect3DDevice8Impl_DeletePatch
4170 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4172 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4173 ICOM_THIS(IDirect3DDevice8Impl,iface);
4175 ENTER_GL();
4177 #if 0
4178 if (This->glCtx != This->render_ctx) {
4179 glXDestroyContext(This->display, This->render_ctx);
4180 This->render_ctx = This->glCtx;
4182 #endif
4183 if (This->win != This->drawable) {
4184 glXDestroyPbuffer(This->display, This->drawable);
4185 This->drawable = This->win;
4188 LEAVE_GL();
4190 #endif
4191 return D3D_OK;
4194 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4195 IDirect3DSurface8* RenderSurface,
4196 IDirect3DSurface8* StencilSurface) {
4198 HRESULT ret = D3DERR_INVALIDCALL;
4200 * Currently only active for GLX >= 1.3
4201 * for others versions we'll have to use GLXPixmaps
4203 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4204 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4205 * so only check OpenGL version
4207 #if defined(GL_VERSION_1_3)
4208 GLXFBConfig* cfgs = NULL;
4209 int nCfgs = 0;
4210 int attribs[256];
4211 int nAttribs = 0;
4212 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4213 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4214 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4215 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4216 IDirect3DSurface8Impl* tmp;
4218 ICOM_THIS(IDirect3DDevice8Impl,iface);
4220 #define PUSH1(att) attribs[nAttribs++] = (att);
4221 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4223 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4224 PUSH2(GLX_X_RENDERABLE, TRUE);
4225 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4227 switch (BackBufferFormat) {
4228 /* color buffer */
4229 case D3DFMT_P8:
4230 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4231 PUSH2(GLX_BUFFER_SIZE, 8);
4232 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4233 break;
4235 case D3DFMT_R3G3B2:
4236 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4237 PUSH2(GLX_RED_SIZE, 3);
4238 PUSH2(GLX_GREEN_SIZE, 3);
4239 PUSH2(GLX_BLUE_SIZE, 2);
4240 break;
4242 case D3DFMT_A1R5G5B5:
4243 PUSH2(GLX_ALPHA_SIZE, 1);
4244 case D3DFMT_X1R5G5B5:
4245 PUSH2(GLX_RED_SIZE, 5);
4246 PUSH2(GLX_GREEN_SIZE, 5);
4247 PUSH2(GLX_BLUE_SIZE, 5);
4248 break;
4250 case D3DFMT_R5G6B5:
4251 PUSH2(GLX_RED_SIZE, 5);
4252 PUSH2(GLX_GREEN_SIZE, 6);
4253 PUSH2(GLX_BLUE_SIZE, 5);
4254 break;
4256 case D3DFMT_A4R4G4B4:
4257 PUSH2(GLX_ALPHA_SIZE, 4);
4258 case D3DFMT_X4R4G4B4:
4259 PUSH2(GLX_RED_SIZE, 4);
4260 PUSH2(GLX_GREEN_SIZE, 4);
4261 PUSH2(GLX_BLUE_SIZE, 4);
4262 break;
4264 case D3DFMT_A8R8G8B8:
4265 PUSH2(GLX_ALPHA_SIZE, 8);
4266 case D3DFMT_R8G8B8:
4267 case D3DFMT_X8R8G8B8:
4268 PUSH2(GLX_RED_SIZE, 8);
4269 PUSH2(GLX_GREEN_SIZE, 8);
4270 PUSH2(GLX_BLUE_SIZE, 8);
4271 break;
4273 default:
4274 break;
4277 switch (StencilBufferFormat) {
4278 case D3DFMT_D16_LOCKABLE:
4279 case D3DFMT_D16:
4280 PUSH2(GLX_DEPTH_SIZE, 16);
4281 break;
4283 case D3DFMT_D15S1:
4284 PUSH2(GLX_DEPTH_SIZE, 15);
4285 break;
4287 case D3DFMT_D24X8:
4288 PUSH2(GLX_DEPTH_SIZE, 24);
4289 break;
4291 case D3DFMT_D24X4S4:
4292 PUSH2(GLX_DEPTH_SIZE, 24);
4293 PUSH2(GLX_STENCIL_SIZE, 4);
4294 break;
4296 case D3DFMT_D24S8:
4297 PUSH2(GLX_DEPTH_SIZE, 24);
4298 PUSH2(GLX_STENCIL_SIZE, 8);
4299 break;
4301 case D3DFMT_D32:
4302 PUSH2(GLX_DEPTH_SIZE, 32);
4303 break;
4305 default:
4306 break;
4309 PUSH1(None);
4311 ENTER_GL();
4313 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4314 if (NULL != cfgs) {
4315 #if 0
4316 int i;
4317 for (i = 0; i < nCfgs; ++i) {
4318 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4320 #endif
4322 if (NULL != This->renderTarget) {
4323 GLenum prev_read;
4324 glFlush();
4325 vcheckGLcall("glFlush");
4327 #if 0
4328 /** very very usefull debug code */
4329 glXSwapBuffers(This->display, This->drawable);
4330 printf("Hit Enter to get next frame ...\n");
4331 getchar();
4332 #endif
4334 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4335 vcheckGLcall("glIntegerv");
4336 glReadBuffer(GL_BACK);
4337 vcheckGLcall("glReadBuffer");
4339 long j;
4340 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4342 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4343 pitch = pitch / 2;
4345 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4346 glReadPixels(0,
4347 This->renderTarget->myDesc.Height - j - 1,
4348 This->renderTarget->myDesc.Width,
4350 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4351 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4352 This->renderTarget->allocatedMemory + j * pitch);
4353 vcheckGLcall("glReadPixels");
4356 glReadBuffer(prev_read);
4357 vcheckGLcall("glReadBuffer");
4360 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4361 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4362 nAttribs = 0;
4363 PUSH2(GLX_PBUFFER_WIDTH, Width);
4364 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4365 PUSH1(None);
4366 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4368 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4369 if (NULL == This->render_ctx) {
4370 ERR("cannot create glxContext\n");
4373 glFlush();
4374 glXSwapBuffers(This->display, This->drawable);
4375 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4376 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4378 checkGLcall("glXMakeContextCurrent");
4381 tmp = This->renderTarget;
4382 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4383 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4384 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4386 tmp = This->stencilBufferTarget;
4387 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4388 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4389 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4391 ret = D3D_OK;
4393 } else {
4394 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4397 #undef PUSH1
4398 #undef PUSH2
4400 LEAVE_GL();
4402 #endif
4404 return ret;