Culling to different viewports failed as clearing the whole viewport
[wine/wine-gecko.git] / dlls / d3d8 / device.c
blob75f3b414668ab4f1cd4cd308d16cc888e6ac6cf2
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 glEnable(GL_SCISSOR_TEST);
1353 checkGLcall("glEnable GL_SCISSOR_TEST");
1354 if (Count > 0 && pRects) {
1355 glEnable(GL_SCISSOR_TEST);
1356 checkGLcall("glEnable GL_SCISSOR_TEST");
1357 curRect = pRects;
1358 } else {
1359 curRect = NULL;
1362 /* Only set the values up once, as they are not changing */
1363 if (Flags & D3DCLEAR_STENCIL) {
1364 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1365 glClearStencil(Stencil);
1366 checkGLcall("glClearStencil");
1367 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1370 if (Flags & D3DCLEAR_ZBUFFER) {
1371 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1372 glDepthMask(GL_TRUE);
1373 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1374 glClearDepth(Z);
1375 checkGLcall("glClearDepth");
1376 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1379 if (Flags & D3DCLEAR_TARGET) {
1380 TRACE("Clearing screen with glClear to color %lx\n", Color);
1381 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1382 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1383 ((Color >> 8) & 0xFF) / 255.0f,
1384 ((Color >> 0) & 0xFF) / 255.0f,
1385 ((Color >> 24) & 0xFF) / 255.0f);
1386 checkGLcall("glClearColor");
1387 glMask = glMask | GL_COLOR_BUFFER_BIT;
1390 /* Now process each rect in turn */
1391 for (i = 0; i < Count || i == 0; i++) {
1393 if (curRect) {
1394 /* Note gl uses lower left, width/height */
1395 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1396 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1397 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1398 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1399 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1400 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1401 checkGLcall("glScissor");
1402 } else {
1403 glScissor(This->StateBlock->viewport.X,
1404 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1405 This->StateBlock->viewport.Width,
1406 This->StateBlock->viewport.Height);
1407 checkGLcall("glScissor");
1410 /* Clear the selected rectangle (or full screen) */
1411 glClear(glMask);
1412 checkGLcall("glClear");
1414 /* Step to the next rectangle */
1415 if (curRect) curRect = curRect + sizeof(D3DRECT);
1418 /* Restore the old values (why..?) */
1419 if (Flags & D3DCLEAR_STENCIL) {
1420 glClearStencil(old_stencil_clear_value);
1422 if (Flags & D3DCLEAR_ZBUFFER) {
1423 glDepthMask(old_ztest);
1424 glClearDepth(old_z_clear_value);
1426 if (Flags & D3DCLEAR_TARGET) {
1427 glClearColor(old_color_clear_value[0],
1428 old_color_clear_value[1],
1429 old_color_clear_value[2],
1430 old_color_clear_value[3]);
1433 if (Count > 0 && pRects) {
1434 glDisable(GL_SCISSOR_TEST);
1435 checkGLcall("glDisable");
1437 LEAVE_GL();
1439 return D3D_OK;
1441 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1442 ICOM_THIS(IDirect3DDevice8Impl,iface);
1443 int k;
1445 /* Most of this routine, comments included copied from ddraw tree initially: */
1446 TRACE("(%p) : State=%d\n", This, d3dts);
1448 /* Handle recording of state blocks */
1449 if (This->isRecordingState) {
1450 TRACE("Recording... not performing anything\n");
1451 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1452 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1453 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1454 return D3D_OK;
1458 * if the new matrix is the same as the current one,
1459 * we cut off any further processing. this seems to be a reasonable
1460 * optimization because as was noticed, some apps (warcraft3 for example)
1461 * tend towards setting the same matrix repeatedly for some dumb reason.
1463 * From here on we assume that the new matrix is different, wherever it matters
1464 * but note
1466 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1467 TRACE("The app is setting the same matrix over again\n");
1468 return D3D_OK;
1469 } else {
1470 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1474 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1475 where ViewMat = Camera space, WorldMat = world space.
1477 In OpenGL, camera and world space is combined into GL_MODELVIEW
1478 matrix. The Projection matrix stay projection matrix.
1481 /* Capture the times we can just ignore the change */
1482 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1483 This->modelview_valid = FALSE;
1484 return D3D_OK;
1486 } else if (d3dts == D3DTS_PROJECTION) {
1487 This->proj_valid = FALSE;
1488 return D3D_OK;
1490 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1491 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1492 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1493 return D3D_OK;
1496 /* Chances are we really are going to have to change a matrix */
1497 ENTER_GL();
1499 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1500 if (d3dts < GL_LIMITS(textures)) {
1501 int tex = d3dts - D3DTS_TEXTURE0;
1502 #if defined(GL_VERSION_1_3)
1503 glActiveTexture(GL_TEXTURE0 + tex);
1504 #else
1505 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1506 #endif
1507 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1510 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1512 PLIGHTINFOEL *lightChain = NULL;
1513 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1514 This->modelview_valid = FALSE;
1515 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1516 glMatrixMode(GL_MODELVIEW);
1517 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1518 glPushMatrix();
1519 glLoadMatrixf((float *)lpmatrix);
1520 checkGLcall("glLoadMatrixf(...)");
1522 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1523 * NOTE: We have to reset the positions even if the light/plane is not currently
1524 * enabled, since the call to enable it will not reset the position.
1525 * NOTE2: Apparently texture transforms do NOT need reapplying
1528 /* Reset lights */
1529 lightChain = This->StateBlock->lights;
1530 while (lightChain && lightChain->glIndex != -1) {
1531 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1532 checkGLcall("glLightfv posn");
1533 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1534 checkGLcall("glLightfv dirn");
1535 lightChain = lightChain->next;
1537 /* Reset Clipping Planes if clipping is enabled */
1538 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1539 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1540 checkGLcall("glClipPlane");
1542 glPopMatrix();
1544 } else { /* What was requested!?? */
1545 WARN("invalid matrix specified: %i\n", d3dts);
1549 /* Release lock, all done */
1550 LEAVE_GL();
1551 return D3D_OK;
1554 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1555 ICOM_THIS(IDirect3DDevice8Impl,iface);
1556 TRACE("(%p) : for State %d\n", This, State);
1557 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1558 return D3D_OK;
1561 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1562 D3DMATRIX *mat = NULL;
1563 D3DMATRIX temp;
1565 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1566 but works regardless of recording being on.
1567 If this is found to be wrong, change to StateBlock. */
1568 ICOM_THIS(IDirect3DDevice8Impl,iface);
1569 TRACE("(%p) : For state %u\n", This, State);
1571 if (State < HIGHEST_TRANSFORMSTATE)
1573 mat = &This->UpdateStateBlock->transforms[State];
1574 } else {
1575 FIXME("Unhandled transform state!!\n");
1578 /* Copied from ddraw code: */
1579 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);
1580 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);
1581 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);
1582 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);
1584 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);
1585 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);
1586 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);
1587 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);
1589 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);
1590 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);
1591 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);
1592 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);
1594 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);
1595 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);
1596 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);
1597 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);
1599 /* Apply change via set transform - will reapply to eg. lights this way */
1600 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1601 return D3D_OK;
1603 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1604 ICOM_THIS(IDirect3DDevice8Impl,iface);
1606 TRACE("(%p)\n", This);
1607 This->UpdateStateBlock->Changed.viewport = TRUE;
1608 This->UpdateStateBlock->Set.viewport = TRUE;
1609 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1611 /* Handle recording of state blocks */
1612 if (This->isRecordingState) {
1613 TRACE("Recording... not performing anything\n");
1614 return D3D_OK;
1617 ENTER_GL();
1619 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1620 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1622 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1623 checkGLcall("glDepthRange");
1624 /* Note: GL requires lower left, DirectX supplies upper left */
1625 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1626 pViewport->Width, pViewport->Height);
1627 checkGLcall("glViewport");
1629 LEAVE_GL();
1631 return D3D_OK;
1634 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1635 ICOM_THIS(IDirect3DDevice8Impl,iface);
1636 TRACE("(%p)\n", This);
1637 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1638 return D3D_OK;
1641 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1642 ICOM_THIS(IDirect3DDevice8Impl,iface);
1644 This->UpdateStateBlock->Changed.material = TRUE;
1645 This->UpdateStateBlock->Set.material = TRUE;
1646 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1648 /* Handle recording of state blocks */
1649 if (This->isRecordingState) {
1650 TRACE("Recording... not performing anything\n");
1651 return D3D_OK;
1654 ENTER_GL();
1655 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1656 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1657 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1658 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1659 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1661 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1662 checkGLcall("glMaterialfv");
1663 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1664 checkGLcall("glMaterialfv");
1666 /* Only change material color if specular is enabled, otherwise it is set to black */
1667 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1668 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1669 checkGLcall("glMaterialfv");
1670 } else {
1671 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1672 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1673 checkGLcall("glMaterialfv");
1675 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1676 checkGLcall("glMaterialfv");
1677 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1678 checkGLcall("glMaterialf");
1680 LEAVE_GL();
1681 return D3D_OK;
1683 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1684 ICOM_THIS(IDirect3DDevice8Impl,iface);
1685 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1686 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1687 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1688 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1689 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1690 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1691 return D3D_OK;
1694 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1695 you can reference any indexes you want as long as that number max are enabled are any
1696 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1697 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1698 but when recording, just build a chain pretty much of commands to be replayed. */
1700 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1701 float rho;
1702 PLIGHTINFOEL *object, *temp;
1704 ICOM_THIS(IDirect3DDevice8Impl,iface);
1705 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1707 /* If recording state block, just add to end of lights chain */
1708 if (This->isRecordingState) {
1709 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1710 if (NULL == object) {
1711 return D3DERR_OUTOFVIDEOMEMORY;
1713 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1714 object->OriginalIndex = Index;
1715 object->glIndex = -1;
1716 object->changed = TRUE;
1718 /* Add to the END of the chain of lights changes to be replayed */
1719 if (This->UpdateStateBlock->lights == NULL) {
1720 This->UpdateStateBlock->lights = object;
1721 } else {
1722 temp = This->UpdateStateBlock->lights;
1723 while (temp->next != NULL) temp=temp->next;
1724 temp->next = object;
1726 TRACE("Recording... not performing anything more\n");
1727 return D3D_OK;
1730 /* Ok, not recording any longer so do real work */
1731 object = This->StateBlock->lights;
1732 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1734 /* If we didnt find it in the list of lights, time to add it */
1735 if (object == NULL) {
1736 PLIGHTINFOEL *insertAt,*prevPos;
1738 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1739 if (NULL == object) {
1740 return D3DERR_OUTOFVIDEOMEMORY;
1742 object->OriginalIndex = Index;
1743 object->glIndex = -1;
1745 /* Add it to the front of list with the idea that lights will be changed as needed
1746 BUT after any lights currently assigned GL indexes */
1747 insertAt = This->StateBlock->lights;
1748 prevPos = NULL;
1749 while (insertAt != NULL && insertAt->glIndex != -1) {
1750 prevPos = insertAt;
1751 insertAt = insertAt->next;
1754 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1755 This->StateBlock->lights = object;
1756 } else if (insertAt == NULL) { /* End of list */
1757 prevPos->next = object;
1758 object->prev = prevPos;
1759 } else { /* Middle of chain */
1760 if (prevPos == NULL) {
1761 This->StateBlock->lights = object;
1762 } else {
1763 prevPos->next = object;
1765 object->prev = prevPos;
1766 object->next = insertAt;
1767 insertAt->prev = object;
1771 /* Initialze the object */
1772 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,
1773 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1774 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1775 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1776 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1777 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1778 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1780 /* Save away the information */
1781 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1783 switch (pLight->Type) {
1784 case D3DLIGHT_POINT:
1785 /* Position */
1786 object->lightPosn[0] = pLight->Position.x;
1787 object->lightPosn[1] = pLight->Position.y;
1788 object->lightPosn[2] = pLight->Position.z;
1789 object->lightPosn[3] = 1.0f;
1790 object->cutoff = 180.0f;
1791 /* FIXME: Range */
1792 break;
1794 case D3DLIGHT_SPOT:
1795 /* Position */
1796 object->lightPosn[0] = pLight->Position.x;
1797 object->lightPosn[1] = pLight->Position.y;
1798 object->lightPosn[2] = pLight->Position.z;
1799 object->lightPosn[3] = 1.0;
1801 /* Direction */
1802 object->lightDirn[0] = pLight->Direction.x;
1803 object->lightDirn[1] = pLight->Direction.y;
1804 object->lightDirn[2] = pLight->Direction.z;
1805 object->lightDirn[3] = 1.0;
1808 * opengl-ish and d3d-ish spot lights use too different models for the
1809 * light "intensity" as a function of the angle towards the main light direction,
1810 * so we only can approximate very roughly.
1811 * however spot lights are rather rarely used in games (if ever used at all).
1812 * furthermore if still used, probably nobody pays attention to such details.
1814 if (pLight->Falloff == 0) {
1815 rho = 6.28f;
1816 } else {
1817 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1819 if (rho < 0.0001) rho = 0.0001f;
1820 object->exponent = -0.3/log(cos(rho/2));
1821 object->cutoff = pLight->Phi*90/M_PI;
1823 /* FIXME: Range */
1824 break;
1826 case D3DLIGHT_DIRECTIONAL:
1827 /* Direction */
1828 object->lightPosn[0] = -pLight->Direction.x;
1829 object->lightPosn[1] = -pLight->Direction.y;
1830 object->lightPosn[2] = -pLight->Direction.z;
1831 object->lightPosn[3] = 0.0;
1832 object->exponent = 0.0f;
1833 object->cutoff = 180.0f;
1834 break;
1836 default:
1837 FIXME("Unrecognized light type %d\n", pLight->Type);
1840 /* Update the live definitions if the light is currently assigned a glIndex */
1841 if (object->glIndex != -1) {
1842 setup_light(iface, object->glIndex, object);
1844 return D3D_OK;
1846 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1847 PLIGHTINFOEL *lightInfo = NULL;
1848 ICOM_THIS(IDirect3DDevice8Impl,iface);
1849 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1851 /* Locate the light in the live lights */
1852 lightInfo = This->StateBlock->lights;
1853 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1855 if (lightInfo == NULL) {
1856 TRACE("Light information requested but light not defined\n");
1857 return D3DERR_INVALIDCALL;
1860 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1861 return D3D_OK;
1863 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1864 PLIGHTINFOEL *lightInfo = NULL;
1865 ICOM_THIS(IDirect3DDevice8Impl,iface);
1866 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1868 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1869 if (This->isRecordingState) {
1870 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1871 if (NULL == lightInfo) {
1872 return D3DERR_OUTOFVIDEOMEMORY;
1874 lightInfo->OriginalIndex = Index;
1875 lightInfo->glIndex = -1;
1876 lightInfo->enabledChanged = TRUE;
1878 /* Add to the END of the chain of lights changes to be replayed */
1879 if (This->UpdateStateBlock->lights == NULL) {
1880 This->UpdateStateBlock->lights = lightInfo;
1881 } else {
1882 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1883 while (temp->next != NULL) temp=temp->next;
1884 temp->next = lightInfo;
1886 TRACE("Recording... not performing anything more\n");
1887 return D3D_OK;
1890 /* Not recording... So, locate the light in the live lights */
1891 lightInfo = This->StateBlock->lights;
1892 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1894 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1895 if (lightInfo == NULL) {
1896 D3DLIGHT8 lightParms;
1897 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1898 wait until someone confirms it seems to work! */
1899 TRACE("Light enabled requested but light not defined, so defining one!\n");
1900 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1901 lightParms.Diffuse.r = 1.0;
1902 lightParms.Diffuse.g = 1.0;
1903 lightParms.Diffuse.b = 1.0;
1904 lightParms.Diffuse.a = 0.0;
1905 lightParms.Specular.r = 0.0;
1906 lightParms.Specular.g = 0.0;
1907 lightParms.Specular.b = 0.0;
1908 lightParms.Specular.a = 0.0;
1909 lightParms.Ambient.r = 0.0;
1910 lightParms.Ambient.g = 0.0;
1911 lightParms.Ambient.b = 0.0;
1912 lightParms.Ambient.a = 0.0;
1913 lightParms.Position.x = 0.0;
1914 lightParms.Position.y = 0.0;
1915 lightParms.Position.z = 0.0;
1916 lightParms.Direction.x = 0.0;
1917 lightParms.Direction.y = 0.0;
1918 lightParms.Direction.z = 1.0;
1919 lightParms.Range = 0.0;
1920 lightParms.Falloff = 0.0;
1921 lightParms.Attenuation0 = 0.0;
1922 lightParms.Attenuation1 = 0.0;
1923 lightParms.Attenuation2 = 0.0;
1924 lightParms.Theta = 0.0;
1925 lightParms.Phi = 0.0;
1926 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1928 /* Search for it again! Should be fairly quick as near head of list */
1929 lightInfo = This->StateBlock->lights;
1930 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1931 if (lightInfo == NULL) {
1932 FIXME("Adding default lights has failed dismally\n");
1933 return D3DERR_INVALIDCALL;
1937 /* OK, we now have a light... */
1938 if (Enable == FALSE) {
1940 /* If we are disabling it, check it was enabled, and
1941 still only do something if it has assigned a glIndex (which it should have!) */
1942 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1943 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1944 ENTER_GL();
1945 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1946 checkGLcall("glDisable GL_LIGHT0+Index");
1947 LEAVE_GL();
1948 } else {
1949 TRACE("Nothing to do as light was not enabled\n");
1951 lightInfo->lightEnabled = FALSE;
1952 } else {
1954 /* We are enabling it. If it is enabled, its really simple */
1955 if (lightInfo->lightEnabled == TRUE) {
1956 /* nop */
1957 TRACE("Nothing to do as light was enabled\n");
1959 /* If it already has a glIndex, its still simple */
1960 } else if (lightInfo->glIndex != -1) {
1961 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1962 lightInfo->lightEnabled = TRUE;
1963 ENTER_GL();
1964 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1965 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1966 LEAVE_GL();
1968 /* Otherwise got to find space - lights are ordered gl indexes first */
1969 } else {
1970 PLIGHTINFOEL *bsf = NULL;
1971 PLIGHTINFOEL *pos = This->StateBlock->lights;
1972 PLIGHTINFOEL *prev = NULL;
1973 int Index= 0;
1974 int glIndex = -1;
1976 /* Try to minimize changes as much as possible */
1977 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1979 /* Try to remember which index can be replaced if necessary */
1980 if (bsf==NULL && pos->lightEnabled == FALSE) {
1981 /* Found a light we can replace, save as best replacement */
1982 bsf = pos;
1985 /* Step to next space */
1986 prev = pos;
1987 pos = pos->next;
1988 Index ++;
1991 /* If we have too many active lights, fail the call */
1992 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1993 FIXME("Program requests too many concurrent lights\n");
1994 return D3DERR_INVALIDCALL;
1996 /* If we have allocated all lights, but not all are enabled,
1997 reuse one which is not enabled */
1998 } else if (Index == This->maxConcurrentLights) {
1999 /* use bsf - Simply swap the new light and the BSF one */
2000 PLIGHTINFOEL *bsfNext = bsf->next;
2001 PLIGHTINFOEL *bsfPrev = bsf->prev;
2003 /* Sort out ends */
2004 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2005 if (bsf->prev != NULL) {
2006 bsf->prev->next = lightInfo;
2007 } else {
2008 This->StateBlock->lights = lightInfo;
2011 /* If not side by side, lots of chains to update */
2012 if (bsf->next != lightInfo) {
2013 lightInfo->prev->next = bsf;
2014 bsf->next->prev = lightInfo;
2015 bsf->next = lightInfo->next;
2016 bsf->prev = lightInfo->prev;
2017 lightInfo->next = bsfNext;
2018 lightInfo->prev = bsfPrev;
2020 } else {
2021 /* Simple swaps */
2022 bsf->prev = lightInfo;
2023 bsf->next = lightInfo->next;
2024 lightInfo->next = bsf;
2025 lightInfo->prev = bsfPrev;
2029 /* Update states */
2030 glIndex = bsf->glIndex;
2031 bsf->glIndex = -1;
2032 lightInfo->glIndex = glIndex;
2033 lightInfo->lightEnabled = TRUE;
2035 /* Finally set up the light in gl itself */
2036 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2037 ENTER_GL();
2038 setup_light(iface, glIndex, lightInfo);
2039 glEnable(GL_LIGHT0 + glIndex);
2040 checkGLcall("glEnable GL_LIGHT0 new setup");
2041 LEAVE_GL();
2043 /* If we reached the end of the allocated lights, with space in the
2044 gl lights, setup a new light */
2045 } else if (pos->glIndex == -1) {
2047 /* We reached the end of the allocated gl lights, so already
2048 know the index of the next one! */
2049 glIndex = Index;
2050 lightInfo->glIndex = glIndex;
2051 lightInfo->lightEnabled = TRUE;
2053 /* In an ideal world, its already in the right place */
2054 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2055 /* No need to move it */
2056 } else {
2057 /* Remove this light from the list */
2058 lightInfo->prev->next = lightInfo->next;
2059 if (lightInfo->next != NULL) {
2060 lightInfo->next->prev = lightInfo->prev;
2063 /* Add in at appropriate place (inbetween prev and pos) */
2064 lightInfo->prev = prev;
2065 lightInfo->next = pos;
2066 if (prev == NULL) {
2067 This->StateBlock->lights = lightInfo;
2068 } else {
2069 prev->next = lightInfo;
2071 if (pos != NULL) {
2072 pos->prev = lightInfo;
2076 /* Finally set up the light in gl itself */
2077 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2078 ENTER_GL();
2079 setup_light(iface, glIndex, lightInfo);
2080 glEnable(GL_LIGHT0 + glIndex);
2081 checkGLcall("glEnable GL_LIGHT0 new setup");
2082 LEAVE_GL();
2087 return D3D_OK;
2089 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2091 PLIGHTINFOEL *lightInfo = NULL;
2092 ICOM_THIS(IDirect3DDevice8Impl,iface);
2093 TRACE("(%p) : for idx(%ld)\n", This, Index);
2095 /* Locate the light in the live lights */
2096 lightInfo = This->StateBlock->lights;
2097 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2099 if (lightInfo == NULL) {
2100 TRACE("Light enabled state requested but light not defined\n");
2101 return D3DERR_INVALIDCALL;
2103 *pEnable = lightInfo->lightEnabled;
2104 return D3D_OK;
2106 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2107 ICOM_THIS(IDirect3DDevice8Impl,iface);
2108 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2110 /* Validate Index */
2111 if (Index >= GL_LIMITS(clipplanes)) {
2112 TRACE("Application has requested clipplane this device doesnt support\n");
2113 return D3DERR_INVALIDCALL;
2116 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2117 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2118 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2119 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2120 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2121 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2123 /* Handle recording of state blocks */
2124 if (This->isRecordingState) {
2125 TRACE("Recording... not performing anything\n");
2126 return D3D_OK;
2129 /* Apply it */
2131 ENTER_GL();
2133 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2134 glMatrixMode(GL_MODELVIEW);
2135 glPushMatrix();
2136 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2138 TRACE("Clipplane [%f,%f,%f,%f]\n",
2139 This->UpdateStateBlock->clipplane[Index][0],
2140 This->UpdateStateBlock->clipplane[Index][1],
2141 This->UpdateStateBlock->clipplane[Index][2],
2142 This->UpdateStateBlock->clipplane[Index][3]);
2143 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2144 checkGLcall("glClipPlane");
2146 glPopMatrix();
2148 LEAVE_GL();
2150 return D3D_OK;
2152 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2153 ICOM_THIS(IDirect3DDevice8Impl,iface);
2154 TRACE("(%p) : for idx %ld\n", This, Index);
2156 /* Validate Index */
2157 if (Index >= GL_LIMITS(clipplanes)) {
2158 TRACE("Application has requested clipplane this device doesnt support\n");
2159 return D3DERR_INVALIDCALL;
2162 pPlane[0] = This->StateBlock->clipplane[Index][0];
2163 pPlane[1] = This->StateBlock->clipplane[Index][1];
2164 pPlane[2] = This->StateBlock->clipplane[Index][2];
2165 pPlane[3] = This->StateBlock->clipplane[Index][3];
2166 return D3D_OK;
2168 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2169 ICOM_THIS(IDirect3DDevice8Impl,iface);
2170 DWORD OldValue = This->StateBlock->renderstate[State];
2172 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2173 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2174 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2175 This->UpdateStateBlock->renderstate[State] = Value;
2177 /* Handle recording of state blocks */
2178 if (This->isRecordingState) {
2179 TRACE("Recording... not performing anything\n");
2180 return D3D_OK;
2183 ENTER_GL();
2185 switch (State) {
2186 case D3DRS_FILLMODE :
2187 switch ((D3DFILLMODE) Value) {
2188 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2189 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2190 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2191 default:
2192 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2194 checkGLcall("glPolygonMode (fillmode)");
2195 break;
2197 case D3DRS_LIGHTING :
2198 if (Value) {
2199 glEnable(GL_LIGHTING);
2200 checkGLcall("glEnable GL_LIGHTING");
2201 } else {
2202 glDisable(GL_LIGHTING);
2203 checkGLcall("glDisable GL_LIGHTING");
2205 break;
2207 case D3DRS_ZENABLE :
2208 switch ((D3DZBUFFERTYPE) Value) {
2209 case D3DZB_FALSE:
2210 glDisable(GL_DEPTH_TEST);
2211 checkGLcall("glDisable GL_DEPTH_TEST");
2212 break;
2213 case D3DZB_TRUE:
2214 glEnable(GL_DEPTH_TEST);
2215 checkGLcall("glEnable GL_DEPTH_TEST");
2216 break;
2218 case D3DZB_USEW:
2219 default:
2220 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2222 break;
2224 case D3DRS_CULLMODE :
2226 /* If we are culling "back faces with clockwise vertices" then
2227 set front faces to be counter clockwise and enable culling
2228 of back faces */
2229 switch ((D3DCULL) Value) {
2230 case D3DCULL_NONE:
2231 glDisable(GL_CULL_FACE);
2232 checkGLcall("glDisable GL_CULL_FACE");
2233 break;
2234 case D3DCULL_CW:
2235 glEnable(GL_CULL_FACE);
2236 checkGLcall("glEnable GL_CULL_FACE");
2237 glFrontFace(GL_CCW);
2238 checkGLcall("glFrontFace GL_CCW");
2239 glCullFace(GL_BACK);
2240 break;
2241 case D3DCULL_CCW:
2242 glEnable(GL_CULL_FACE);
2243 checkGLcall("glEnable GL_CULL_FACE");
2244 glFrontFace(GL_CW);
2245 checkGLcall("glFrontFace GL_CW");
2246 glCullFace(GL_BACK);
2247 break;
2248 default:
2249 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2251 break;
2253 case D3DRS_SHADEMODE :
2254 switch ((D3DSHADEMODE) Value) {
2255 case D3DSHADE_FLAT:
2256 glShadeModel(GL_FLAT);
2257 checkGLcall("glShadeModel");
2258 break;
2259 case D3DSHADE_GOURAUD:
2260 glShadeModel(GL_SMOOTH);
2261 checkGLcall("glShadeModel");
2262 break;
2263 case D3DSHADE_PHONG:
2264 FIXME("D3DSHADE_PHONG isnt supported?\n");
2266 LEAVE_GL();
2267 return D3DERR_INVALIDCALL;
2268 default:
2269 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2271 break;
2273 case D3DRS_DITHERENABLE :
2274 if (Value) {
2275 glEnable(GL_DITHER);
2276 checkGLcall("glEnable GL_DITHER");
2277 } else {
2278 glDisable(GL_DITHER);
2279 checkGLcall("glDisable GL_DITHER");
2281 break;
2283 case D3DRS_ZWRITEENABLE :
2284 if (Value) {
2285 glDepthMask(1);
2286 checkGLcall("glDepthMask");
2287 } else {
2288 glDepthMask(0);
2289 checkGLcall("glDepthMask");
2291 break;
2293 case D3DRS_ZFUNC :
2295 int glParm = GL_LESS;
2297 switch ((D3DCMPFUNC) Value) {
2298 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2299 case D3DCMP_LESS: glParm=GL_LESS; break;
2300 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2301 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2302 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2303 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2304 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2305 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2306 default:
2307 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2309 glDepthFunc(glParm);
2310 checkGLcall("glDepthFunc");
2312 break;
2314 case D3DRS_AMBIENT :
2316 float col[4];
2317 D3DCOLORTOGLFLOAT4(Value, col);
2318 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2319 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2320 checkGLcall("glLightModel for MODEL_AMBIENT");
2323 break;
2325 case D3DRS_ALPHABLENDENABLE :
2326 if (Value) {
2327 glEnable(GL_BLEND);
2328 checkGLcall("glEnable GL_BLEND");
2329 } else {
2330 glDisable(GL_BLEND);
2331 checkGLcall("glDisable GL_BLEND");
2333 break;
2335 case D3DRS_SRCBLEND :
2336 case D3DRS_DESTBLEND :
2338 int newVal = GL_ZERO;
2339 switch (Value) {
2340 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2341 case D3DBLEND_ONE : newVal = GL_ONE; break;
2342 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2343 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2344 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2345 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2346 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2347 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2348 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2349 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2350 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2352 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2353 This->srcBlend = newVal;
2354 This->dstBlend = newVal;
2355 break;
2357 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2358 This->srcBlend = newVal;
2359 This->dstBlend = newVal;
2360 break;
2361 default:
2362 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2365 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2366 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2367 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2368 glBlendFunc(This->srcBlend, This->dstBlend);
2370 checkGLcall("glBlendFunc");
2372 break;
2374 case D3DRS_ALPHATESTENABLE :
2375 if (Value) {
2376 glEnable(GL_ALPHA_TEST);
2377 checkGLcall("glEnable GL_ALPHA_TEST");
2378 } else {
2379 glDisable(GL_ALPHA_TEST);
2380 checkGLcall("glDisable GL_ALPHA_TEST");
2382 break;
2384 case D3DRS_ALPHAFUNC :
2386 int glParm = GL_LESS;
2387 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2389 switch ((D3DCMPFUNC) Value) {
2390 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2391 case D3DCMP_LESS: glParm = GL_LESS; break;
2392 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2393 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2394 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2395 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2396 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2397 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2398 default:
2399 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2401 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2402 glAlphaFunc(glParm, ref);
2403 This->alphafunc = glParm;
2404 checkGLcall("glAlphaFunc");
2406 break;
2408 case D3DRS_ALPHAREF :
2410 int glParm = This->alphafunc;
2411 float ref = 1.0f;
2413 ref = ((float) Value) / 255.0f;
2414 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2415 glAlphaFunc(glParm, ref);
2416 checkGLcall("glAlphaFunc");
2418 break;
2420 case D3DRS_CLIPPLANEENABLE :
2421 case D3DRS_CLIPPING :
2423 /* Ensure we only do the changed clip planes */
2424 DWORD enable = 0xFFFFFFFF;
2425 DWORD disable = 0x00000000;
2427 /* If enabling / disabling all */
2428 if (State == D3DRS_CLIPPING) {
2429 if (Value) {
2430 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2431 disable = 0x00;
2432 } else {
2433 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2434 enable = 0x00;
2436 } else {
2437 enable = Value & ~OldValue;
2438 disable = ~Value & OldValue;
2441 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2442 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2443 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2444 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2445 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2446 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2448 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2449 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2450 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2451 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2452 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2453 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2455 break;
2457 case D3DRS_BLENDOP :
2459 int glParm = GL_FUNC_ADD;
2461 switch ((D3DBLENDOP) Value) {
2462 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2463 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2464 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2465 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2466 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2467 default:
2468 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2470 TRACE("glBlendEquation(%x)\n", glParm);
2471 glBlendEquation(glParm);
2472 checkGLcall("glBlendEquation");
2474 break;
2476 case D3DRS_TEXTUREFACTOR :
2478 int i;
2480 /* Note the texture color applies to all textures whereas
2481 GL_TEXTURE_ENV_COLOR applies to active only */
2482 float col[4];
2483 D3DCOLORTOGLFLOAT4(Value, col);
2484 /* Set the default alpha blend color */
2485 glBlendColor(col[0], col[1], col[2], col[3]);
2486 checkGLcall("glBlendColor");
2488 /* And now the default texture color as well */
2489 for (i = 0; i < GL_LIMITS(textures); i++) {
2491 /* Note the D3DRS value applies to all textures, but GL has one
2492 per texture, so apply it now ready to be used! */
2493 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2494 #if defined(GL_VERSION_1_3)
2495 glActiveTexture(GL_TEXTURE0 + i);
2496 #else
2497 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2498 #endif
2499 checkGLcall("Activate texture.. to update const color");
2500 } else if (i>0) {
2501 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2504 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2505 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2508 break;
2510 case D3DRS_SPECULARENABLE :
2512 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2513 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2514 specular color. This is wrong:
2515 Separate specular color means the specular colour is maintained separately, whereas
2516 single color means it is merged in. However in both cases they are being used to
2517 some extent.
2518 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2519 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2520 yet running 1.4!
2522 if (Value) {
2523 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2524 checkGLcall("glMaterialfv");
2525 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2526 glEnable(GL_COLOR_SUM_EXT);
2527 } else {
2528 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2530 checkGLcall("glEnable(GL_COLOR_SUM)");
2531 } else {
2532 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2534 /* for the case of enabled lighting: */
2535 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2536 checkGLcall("glMaterialfv");
2538 /* for the case of disabled lighting: */
2539 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2540 glDisable(GL_COLOR_SUM_EXT);
2541 } else {
2542 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2544 checkGLcall("glDisable(GL_COLOR_SUM)");
2547 break;
2549 case D3DRS_STENCILENABLE :
2550 if (Value) {
2551 glEnable(GL_STENCIL_TEST);
2552 checkGLcall("glEnable GL_STENCIL_TEST");
2553 } else {
2554 glDisable(GL_STENCIL_TEST);
2555 checkGLcall("glDisable GL_STENCIL_TEST");
2557 break;
2559 case D3DRS_STENCILFUNC :
2561 int glParm = GL_ALWAYS;
2562 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2563 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2565 switch ((D3DCMPFUNC) Value) {
2566 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2567 case D3DCMP_LESS: glParm=GL_LESS; break;
2568 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2569 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2570 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2571 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2572 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2573 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2574 default:
2575 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2577 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2578 This->stencilfunc = glParm;
2579 glStencilFunc(glParm, ref, mask);
2580 checkGLcall("glStencilFunc");
2582 break;
2584 case D3DRS_STENCILREF :
2586 int glParm = This->stencilfunc;
2587 int ref = 0;
2588 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2590 ref = Value;
2591 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2592 glStencilFunc(glParm, ref, mask);
2593 checkGLcall("glStencilFunc");
2595 break;
2597 case D3DRS_STENCILMASK :
2599 int glParm = This->stencilfunc;
2600 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2601 GLuint mask = Value;
2603 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2604 glStencilFunc(glParm, ref, mask);
2605 checkGLcall("glStencilFunc");
2607 break;
2609 case D3DRS_STENCILFAIL :
2611 GLenum fail ;
2612 GLenum zpass ;
2613 GLenum zfail ;
2615 fail = StencilOp(Value);
2616 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2617 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2618 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2619 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2621 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2622 glStencilOp(fail, zfail, zpass);
2623 checkGLcall("glStencilOp(fail, zfail, zpass);");
2625 break;
2626 case D3DRS_STENCILZFAIL :
2628 GLenum fail ;
2629 GLenum zpass ;
2630 GLenum zfail ;
2632 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2633 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2634 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2635 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2636 zfail = StencilOp(Value);
2638 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2639 glStencilOp(fail, zfail, zpass);
2640 checkGLcall("glStencilOp(fail, zfail, zpass);");
2642 break;
2643 case D3DRS_STENCILPASS :
2645 GLenum fail ;
2646 GLenum zpass ;
2647 GLenum zfail ;
2649 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2650 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2651 zpass = StencilOp(Value);
2652 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2653 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2655 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2656 glStencilOp(fail, zfail, zpass);
2657 checkGLcall("glStencilOp(fail, zfail, zpass);");
2659 break;
2661 case D3DRS_STENCILWRITEMASK :
2663 glStencilMask(Value);
2664 TRACE("glStencilMask(%lu)\n", Value);
2665 checkGLcall("glStencilMask");
2667 break;
2669 case D3DRS_FOGENABLE :
2671 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2672 glEnable(GL_FOG);
2673 checkGLcall("glEnable GL_FOG");
2674 } else {
2675 glDisable(GL_FOG);
2676 checkGLcall("glDisable GL_FOG");
2679 break;
2681 case D3DRS_FOGCOLOR :
2683 float col[4];
2684 D3DCOLORTOGLFLOAT4(Value, col);
2685 /* Set the default alpha blend color */
2686 glFogfv(GL_FOG_COLOR, &col[0]);
2687 checkGLcall("glFog GL_FOG_COLOR");
2689 break;
2691 case D3DRS_FOGTABLEMODE :
2693 switch (Value) {
2694 case D3DFOG_NONE: /* I don't know what to do here */ break;
2695 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2696 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2697 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2698 default:
2699 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2702 break;
2704 case D3DRS_FOGSTART :
2706 float *f = (float*) &Value;
2707 glFogfv(GL_FOG_START, f);
2708 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2709 TRACE("Fog Start == %f\n", *f);
2711 break;
2713 case D3DRS_FOGEND :
2715 float *f = (float*) &Value;
2716 glFogfv(GL_FOG_END, f);
2717 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2718 TRACE("Fog End == %f\n", *f);
2720 break;
2722 case D3DRS_FOGDENSITY :
2724 float *f = (float*) &Value;
2725 glFogfv(GL_FOG_DENSITY, f);
2726 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2728 break;
2730 case D3DRS_VERTEXBLEND :
2732 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2733 TRACE("Vertex Blending state to %ld\n", Value);
2735 break;
2737 case D3DRS_TWEENFACTOR :
2739 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2740 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2742 break;
2744 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2746 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2748 break;
2750 case D3DRS_COLORVERTEX :
2751 case D3DRS_DIFFUSEMATERIALSOURCE :
2752 case D3DRS_SPECULARMATERIALSOURCE :
2753 case D3DRS_AMBIENTMATERIALSOURCE :
2754 case D3DRS_EMISSIVEMATERIALSOURCE :
2756 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2758 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2759 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2760 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2761 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2762 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2763 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2765 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2766 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2767 Parm = GL_AMBIENT_AND_DIFFUSE;
2768 } else {
2769 Parm = GL_DIFFUSE;
2771 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2772 Parm = GL_AMBIENT;
2773 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2774 Parm = GL_EMISSION;
2775 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2776 Parm = GL_SPECULAR;
2777 } else {
2778 Parm = -1;
2781 if (Parm == -1) {
2782 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2783 } else {
2784 This->tracking_color = NEEDS_TRACKING;
2785 This->tracking_parm = Parm;
2788 } else {
2789 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2792 break;
2794 case D3DRS_LINEPATTERN :
2796 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2797 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2799 if (pattern->wRepeatFactor) {
2800 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2801 checkGLcall("glLineStipple(repeat, linepattern)");
2802 glEnable(GL_LINE_STIPPLE);
2803 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2804 } else {
2805 glDisable(GL_LINE_STIPPLE);
2806 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2809 break;
2811 case D3DRS_ZBIAS :
2813 if (Value) {
2814 TRACE("ZBias value %f\n", *((float*)&Value));
2815 glPolygonOffset(0, -*((float*)&Value));
2816 checkGLcall("glPolygonOffset(0, -Value)");
2817 glEnable(GL_POLYGON_OFFSET_FILL);
2818 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2819 glEnable(GL_POLYGON_OFFSET_LINE);
2820 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2821 glEnable(GL_POLYGON_OFFSET_POINT);
2822 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2823 } else {
2824 glDisable(GL_POLYGON_OFFSET_FILL);
2825 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2826 glDisable(GL_POLYGON_OFFSET_LINE);
2827 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2828 glDisable(GL_POLYGON_OFFSET_POINT);
2829 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2832 break;
2834 case D3DRS_NORMALIZENORMALS :
2835 if (Value) {
2836 glEnable(GL_NORMALIZE);
2837 checkGLcall("glEnable(GL_NORMALIZE);");
2838 } else {
2839 glDisable(GL_NORMALIZE);
2840 checkGLcall("glDisable(GL_NORMALIZE);");
2842 break;
2844 case D3DRS_POINTSIZE :
2845 TRACE("Set point size to %f\n", *((float*)&Value));
2846 glPointSize(*((float*)&Value));
2847 checkGLcall("glPointSize(...);");
2848 break;
2850 case D3DRS_POINTSIZE_MIN :
2851 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2852 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2853 checkGLcall("glPointParameterfEXT(...);");
2854 } else {
2855 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2857 break;
2859 case D3DRS_POINTSIZE_MAX :
2860 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2861 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2862 checkGLcall("glPointParameterfEXT(...);");
2863 } else {
2864 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2866 break;
2868 case D3DRS_POINTSCALE_A :
2869 case D3DRS_POINTSCALE_B :
2870 case D3DRS_POINTSCALE_C :
2871 case D3DRS_POINTSCALEENABLE :
2873 /* If enabled, supply the parameters, otherwise fall back to defaults */
2874 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2875 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2876 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2877 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2878 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
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 on this opengl\n");
2886 } else {
2887 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2888 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2889 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2890 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2891 } else {
2892 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2895 break;
2898 case D3DRS_COLORWRITEENABLE :
2899 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2900 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2901 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2902 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2903 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2904 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
2905 Value & D3DCOLORWRITEENABLE_GREEN,
2906 Value & D3DCOLORWRITEENABLE_BLUE,
2907 Value & D3DCOLORWRITEENABLE_ALPHA);
2908 checkGLcall("glColorMask(...)");
2909 break;
2911 /* Unhandled yet...! */
2912 case D3DRS_LASTPIXEL :
2913 case D3DRS_ZVISIBLE :
2914 case D3DRS_EDGEANTIALIAS :
2915 case D3DRS_RANGEFOGENABLE :
2916 case D3DRS_WRAP0 :
2917 case D3DRS_WRAP1 :
2918 case D3DRS_WRAP2 :
2919 case D3DRS_WRAP3 :
2920 case D3DRS_WRAP4 :
2921 case D3DRS_WRAP5 :
2922 case D3DRS_WRAP6 :
2923 case D3DRS_WRAP7 :
2924 case D3DRS_FOGVERTEXMODE :
2925 case D3DRS_LOCALVIEWER :
2926 case D3DRS_SOFTWAREVERTEXPROCESSING :
2927 case D3DRS_POINTSPRITEENABLE :
2928 case D3DRS_MULTISAMPLEANTIALIAS :
2929 case D3DRS_MULTISAMPLEMASK :
2930 case D3DRS_PATCHEDGESTYLE :
2931 case D3DRS_PATCHSEGMENTS :
2932 case D3DRS_DEBUGMONITORTOKEN :
2933 case D3DRS_POSITIONORDER :
2934 case D3DRS_NORMALORDER :
2935 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2936 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2937 break;
2938 default:
2939 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2942 LEAVE_GL();
2944 return D3D_OK;
2946 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2947 ICOM_THIS(IDirect3DDevice8Impl,iface);
2948 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2949 *pValue = This->StateBlock->renderstate[State];
2950 return D3D_OK;
2952 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2953 ICOM_THIS(IDirect3DDevice8Impl,iface);
2955 TRACE("(%p)\n", This);
2957 return IDirect3DDeviceImpl_BeginStateBlock(This);
2959 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2960 IDirect3DStateBlockImpl* pSB;
2961 ICOM_THIS(IDirect3DDevice8Impl,iface);
2962 HRESULT res;
2964 TRACE("(%p)\n", This);
2966 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2967 *pToken = (DWORD) pSB;
2968 return res;
2971 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2972 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2973 ICOM_THIS(IDirect3DDevice8Impl,iface);
2975 TRACE("(%p)\n", This);
2977 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2980 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2981 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2982 ICOM_THIS(IDirect3DDevice8Impl,iface);
2984 TRACE("(%p)\n", This);
2986 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2988 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2989 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2990 ICOM_THIS(IDirect3DDevice8Impl,iface);
2992 TRACE("(%p)\n", This);
2994 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2997 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2998 IDirect3DStateBlockImpl* pSB;
2999 ICOM_THIS(IDirect3DDevice8Impl,iface);
3000 HRESULT res;
3002 TRACE("(%p) : for type %d\n", This, Type);
3004 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3005 *pToken = (DWORD) pSB;
3006 return res;
3009 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3010 ICOM_THIS(IDirect3DDevice8Impl,iface);
3011 FIXME("(%p) : stub\n", This); return D3D_OK;
3013 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3014 ICOM_THIS(IDirect3DDevice8Impl,iface);
3015 FIXME("(%p) : stub\n", This); return D3D_OK;
3017 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3018 ICOM_THIS(IDirect3DDevice8Impl,iface);
3019 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3020 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3021 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3022 return D3D_OK;
3024 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3026 IDirect3DBaseTexture8 *oldTxt;
3027 BOOL reapplyStates = TRUE;
3028 DWORD oldTextureDimensions = -1;
3029 DWORD reapplyFlags = 0;
3031 ICOM_THIS(IDirect3DDevice8Impl,iface);
3032 D3DRESOURCETYPE textureType;
3034 oldTxt = This->UpdateStateBlock->textures[Stage];
3035 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3037 /* Reject invalid texture units */
3038 if (Stage >= GL_LIMITS(textures)) {
3039 TRACE("Attempt to access invalid texture rejected\n");
3040 return D3DERR_INVALIDCALL;
3043 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3044 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3045 This->UpdateStateBlock->textures[Stage] = pTexture;
3047 /* Handle recording of state blocks */
3048 if (This->isRecordingState) {
3049 TRACE("Recording... not performing anything\n");
3050 return D3D_OK;
3053 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3054 ENTER_GL();
3056 /* Make appropriate texture active */
3057 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3058 #if defined(GL_VERSION_1_3)
3059 glActiveTexture(GL_TEXTURE0 + Stage);
3060 #else
3061 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3062 #endif
3063 checkGLcall("glActiveTextureARB");
3064 } else if (Stage>0) {
3065 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3068 /* Decrement the count of the previous texture */
3069 if (NULL != oldTxt) {
3070 IDirect3DBaseTexture8Impl_Release(oldTxt);
3073 if (NULL != pTexture) {
3074 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3076 /* Now setup the texture appropraitly */
3077 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3079 if (textureType == D3DRTYPE_TEXTURE) {
3080 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3081 TRACE("Skipping setting texture as old == new\n");
3082 reapplyStates = FALSE;
3083 } else {
3084 /* Standard 2D texture */
3085 TRACE("Standard 2d texture\n");
3086 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3088 /* Load up the texture now */
3089 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3091 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3092 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3093 TRACE("Skipping setting texture as old == new\n");
3094 reapplyStates = FALSE;
3095 } else {
3096 /* Standard 3D (volume) texture */
3097 TRACE("Standard 3d texture\n");
3098 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3100 /* Load up the texture now */
3101 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3103 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3104 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3105 TRACE("Skipping setting texture as old == new\n");
3106 reapplyStates = FALSE;
3107 } else {
3108 /* Standard Cube texture */
3109 TRACE("Standard Cube texture\n");
3110 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3112 /* Load up the texture now */
3113 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3115 } else {
3116 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3118 } else {
3119 TRACE("Setting to no texture (ie default texture)\n");
3120 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3121 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3122 checkGLcall("glBindTexture");
3123 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3126 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3127 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3128 glDisable(oldTextureDimensions);
3129 checkGLcall("Disable oldTextureDimensions");
3130 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3131 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3132 checkGLcall("glEnable new texture dimensions");
3135 /* If Alpha arg1 is texture then handle the special case when there changes between a
3136 texture and no texture - See comments in set_tex_op */
3137 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3138 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3140 reapplyFlags |= REAPPLY_ALPHAOP;
3145 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3146 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3147 if (reapplyStates) {
3148 setupTextureStates(iface, Stage, reapplyFlags);
3151 LEAVE_GL();
3153 return D3D_OK;
3156 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3157 ICOM_THIS(IDirect3DDevice8Impl,iface);
3158 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3159 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3160 return D3D_OK;
3163 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3164 ICOM_THIS(IDirect3DDevice8Impl,iface);
3166 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3168 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3170 /* Reject invalid texture units */
3171 if (Stage >= GL_LIMITS(textures)) {
3172 TRACE("Attempt to access invalid texture rejected\n");
3173 return D3DERR_INVALIDCALL;
3176 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3177 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3178 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3180 /* Handle recording of state blocks */
3181 if (This->isRecordingState) {
3182 TRACE("Recording... not performing anything\n");
3183 return D3D_OK;
3186 ENTER_GL();
3188 /* Make appropriate texture active */
3189 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3190 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3191 #if defined(GL_VERSION_1_3)
3192 glActiveTexture(GL_TEXTURE0 + Stage);
3193 vcheckGLcall("glActiveTexture");
3194 #else
3195 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3196 vcheckGLcall("glActiveTextureARB");
3197 #endif
3198 } else if (Stage > 0) {
3199 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3202 switch (Type) {
3204 case D3DTSS_MINFILTER :
3205 case D3DTSS_MIPFILTER :
3207 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3208 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3209 GLint realVal = GL_LINEAR;
3211 if (ValueMIN == D3DTEXF_POINT) {
3212 /* GL_NEAREST_* */
3213 if (ValueMIP == D3DTEXF_POINT) {
3214 realVal = GL_NEAREST_MIPMAP_NEAREST;
3215 } else if (ValueMIP == D3DTEXF_LINEAR) {
3216 realVal = GL_NEAREST_MIPMAP_LINEAR;
3217 } else if (ValueMIP == D3DTEXF_NONE) {
3218 realVal = GL_NEAREST;
3219 } else {
3220 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3221 realVal = GL_NEAREST_MIPMAP_LINEAR;
3223 } else if (ValueMIN == D3DTEXF_LINEAR) {
3224 /* GL_LINEAR_* */
3225 if (ValueMIP == D3DTEXF_POINT) {
3226 realVal = GL_LINEAR_MIPMAP_NEAREST;
3227 } else if (ValueMIP == D3DTEXF_LINEAR) {
3228 realVal = GL_LINEAR_MIPMAP_LINEAR;
3229 } else if (ValueMIP == D3DTEXF_NONE) {
3230 realVal = GL_LINEAR;
3231 } else {
3232 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3233 realVal = GL_LINEAR_MIPMAP_LINEAR;
3235 } else if (ValueMIN == D3DTEXF_NONE) {
3236 /* Doesnt really make sense - Windows just seems to disable
3237 mipmapping when this occurs */
3238 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3239 realVal = GL_LINEAR;
3241 } else {
3242 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3243 realVal = GL_LINEAR_MIPMAP_LINEAR;
3246 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3247 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3248 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3250 break;
3252 case D3DTSS_MAXANISOTROPY :
3254 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3255 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3256 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3259 break;
3261 case D3DTSS_MAGFILTER :
3262 if (Value == D3DTEXF_POINT) {
3263 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3264 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3265 } else if (Value == D3DTEXF_LINEAR) {
3266 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3267 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3268 } else {
3269 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3271 break;
3273 case D3DTSS_ALPHAOP :
3274 case D3DTSS_COLOROP :
3277 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3278 /* TODO: Disable by making this and all later levels disabled */
3279 glDisable(GL_TEXTURE_1D);
3280 checkGLcall("Disable GL_TEXTURE_1D");
3281 glDisable(GL_TEXTURE_2D);
3282 checkGLcall("Disable GL_TEXTURE_2D");
3283 glDisable(GL_TEXTURE_3D);
3284 checkGLcall("Disable GL_TEXTURE_3D");
3285 break; /* Dont bother setting the texture operations */
3286 } else {
3287 /* Enable only the appropriate texture dimension */
3288 if (Type == D3DTSS_COLOROP) {
3289 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3290 glEnable(GL_TEXTURE_1D);
3291 checkGLcall("Enable GL_TEXTURE_1D");
3292 } else {
3293 glDisable(GL_TEXTURE_1D);
3294 checkGLcall("Disable GL_TEXTURE_1D");
3296 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3297 glEnable(GL_TEXTURE_2D);
3298 checkGLcall("Enable GL_TEXTURE_2D");
3299 } else {
3300 glDisable(GL_TEXTURE_2D);
3301 checkGLcall("Disable GL_TEXTURE_2D");
3303 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3304 glEnable(GL_TEXTURE_3D);
3305 checkGLcall("Enable GL_TEXTURE_3D");
3306 } else {
3307 glDisable(GL_TEXTURE_3D);
3308 checkGLcall("Disable GL_TEXTURE_3D");
3310 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3311 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3312 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3313 } else {
3314 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3315 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3319 /* Drop through... (Except disable case) */
3320 case D3DTSS_COLORARG0 :
3321 case D3DTSS_COLORARG1 :
3322 case D3DTSS_COLORARG2 :
3323 case D3DTSS_ALPHAARG0 :
3324 case D3DTSS_ALPHAARG1 :
3325 case D3DTSS_ALPHAARG2 :
3327 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3328 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3329 if (isAlphaArg) {
3330 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3331 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3332 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3333 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3334 } else {
3335 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3336 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3337 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3338 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3341 break;
3344 case D3DTSS_ADDRESSU :
3345 case D3DTSS_ADDRESSV :
3346 case D3DTSS_ADDRESSW :
3348 GLint wrapParm = GL_REPEAT;
3349 switch (Value) {
3350 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3351 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3352 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3353 #if defined(GL_VERSION_1_4)
3354 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3355 #elif defined(GL_ARB_texture_mirrored_repeat)
3356 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3357 #else
3358 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3359 #endif
3360 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3361 default:
3362 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3363 wrapParm = GL_REPEAT;
3366 switch (Type) {
3367 case D3DTSS_ADDRESSU:
3368 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3369 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3370 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3371 break;
3372 case D3DTSS_ADDRESSV:
3373 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3374 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3375 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3376 break;
3377 case D3DTSS_ADDRESSW:
3378 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3379 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3380 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3381 break;
3382 default: /* nop */
3383 break; /** stupic compilator */
3386 break;
3388 case D3DTSS_BORDERCOLOR :
3390 float col[4];
3391 D3DCOLORTOGLFLOAT4(Value, col);
3392 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3393 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3394 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3396 break;
3398 case D3DTSS_TEXCOORDINDEX :
3400 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3402 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3403 one flag, you can still specify an index value, which the system uses to
3404 determine the texture wrapping mode.
3405 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3406 means use the vertex position (camera-space) as the input texture coordinates
3407 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3408 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3409 to the TEXCOORDINDEX value */
3411 /**
3412 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3414 switch (Value & 0xFFFF0000) {
3415 case D3DTSS_TCI_PASSTHRU:
3416 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3417 glDisable(GL_TEXTURE_GEN_S);
3418 glDisable(GL_TEXTURE_GEN_T);
3419 glDisable(GL_TEXTURE_GEN_R);
3420 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3421 break;
3423 case D3DTSS_TCI_CAMERASPACEPOSITION:
3424 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3425 as the input texture coordinates for this stage's texture transformation. This
3426 equates roughly to EYE_LINEAR */
3428 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3429 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3430 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3431 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3432 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3434 glMatrixMode(GL_MODELVIEW);
3435 glPushMatrix();
3436 glLoadIdentity();
3437 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3438 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3439 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3440 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3441 glPopMatrix();
3443 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3444 glEnable(GL_TEXTURE_GEN_S);
3445 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3446 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3447 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3448 glEnable(GL_TEXTURE_GEN_T);
3449 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3450 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3451 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3452 glEnable(GL_TEXTURE_GEN_R);
3453 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3454 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3455 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3457 break;
3459 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3460 case D3DTSS_TCI_CAMERASPACENORMAL:
3462 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3463 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3464 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3465 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3466 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3468 glMatrixMode(GL_MODELVIEW);
3469 glPushMatrix();
3470 glLoadIdentity();
3471 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3472 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3473 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3474 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3475 glPopMatrix();
3477 glEnable(GL_TEXTURE_GEN_S);
3478 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3479 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3480 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3481 glEnable(GL_TEXTURE_GEN_T);
3482 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3483 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3484 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3485 glEnable(GL_TEXTURE_GEN_R);
3486 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3487 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3488 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3490 break;
3491 #endif
3493 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3494 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3497 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3498 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3499 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3500 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3501 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3503 glMatrixMode(GL_MODELVIEW);
3504 glPushMatrix();
3505 glLoadIdentity();
3506 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3507 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3508 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3509 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3510 glPopMatrix();
3512 glEnable(GL_TEXTURE_GEN_S);
3513 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3514 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3515 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3516 glEnable(GL_TEXTURE_GEN_T);
3517 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3518 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3519 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3520 glEnable(GL_TEXTURE_GEN_R);
3521 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3522 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3523 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3525 break;
3526 #endif
3528 /* Unhandled types: */
3529 default:
3530 /* Todo: */
3531 /* ? disable GL_TEXTURE_GEN_n ? */
3532 glDisable(GL_TEXTURE_GEN_S);
3533 glDisable(GL_TEXTURE_GEN_T);
3534 glDisable(GL_TEXTURE_GEN_R);
3535 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3536 break;
3539 break;
3541 /* Unhandled */
3542 case D3DTSS_BUMPENVMAT00 :
3543 case D3DTSS_BUMPENVMAT01 :
3544 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3545 break;
3546 case D3DTSS_BUMPENVMAT10 :
3547 case D3DTSS_BUMPENVMAT11 :
3548 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3549 break;
3551 case D3DTSS_TEXTURETRANSFORMFLAGS :
3552 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3553 break;
3555 case D3DTSS_MIPMAPLODBIAS :
3556 case D3DTSS_MAXMIPLEVEL :
3557 case D3DTSS_BUMPENVLSCALE :
3558 case D3DTSS_BUMPENVLOFFSET :
3559 case D3DTSS_RESULTARG :
3560 default:
3561 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3562 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3565 LEAVE_GL();
3567 return D3D_OK;
3569 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3570 ICOM_THIS(IDirect3DDevice8Impl,iface);
3571 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3572 return D3D_OK;
3574 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3575 ICOM_THIS(IDirect3DDevice8Impl,iface);
3576 FIXME("(%p) : stub\n", This);
3577 return D3D_OK;
3579 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3580 ICOM_THIS(IDirect3DDevice8Impl,iface);
3581 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3582 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3583 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3584 return D3D_OK;
3586 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3587 ICOM_THIS(IDirect3DDevice8Impl,iface);
3588 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3589 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3590 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3591 return D3D_OK;
3593 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3594 ICOM_THIS(IDirect3DDevice8Impl,iface);
3595 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3596 This->currentPalette = PaletteNumber;
3598 #if defined(GL_EXT_paletted_texture)
3599 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3601 ENTER_GL();
3603 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3604 GL_RGBA, /* internal format */
3605 256, /* table size */
3606 GL_RGBA, /* table format */
3607 GL_UNSIGNED_BYTE, /* table type */
3608 This->palettes[PaletteNumber]);
3609 checkGLcall("glColorTableEXT");
3611 LEAVE_GL();
3613 } else {
3614 /* Delayed palette handling ... waiting for software emulation into preload code */
3616 #endif
3617 return D3D_OK;
3619 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3620 ICOM_THIS(IDirect3DDevice8Impl,iface);
3621 *PaletteNumber = This->currentPalette;
3622 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3623 return D3D_OK;
3625 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3627 ICOM_THIS(IDirect3DDevice8Impl,iface);
3628 This->StateBlock->streamIsUP = FALSE;
3630 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3631 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3633 return D3D_OK;
3635 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3636 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3637 UINT idxStride = 2;
3638 IDirect3DIndexBuffer8 *pIB;
3639 D3DINDEXBUFFER_DESC IdxBufDsc;
3641 ICOM_THIS(IDirect3DDevice8Impl,iface);
3642 pIB = This->StateBlock->pIndexData;
3643 This->StateBlock->streamIsUP = FALSE;
3645 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3646 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3647 minIndex, NumVertices, startIndex, primCount);
3649 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3650 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3651 idxStride = 2;
3652 } else {
3653 idxStride = 4;
3656 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3657 minIndex);
3659 return D3D_OK;
3661 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3662 ICOM_THIS(IDirect3DDevice8Impl,iface);
3664 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3665 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3667 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3669 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3670 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3671 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3672 This->StateBlock->streamIsUP = TRUE;
3673 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3674 This->StateBlock->stream_stride[0] = 0;
3675 This->StateBlock->stream_source[0] = NULL;
3677 /*stream zero settings set to null at end */
3678 return D3D_OK;
3680 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3681 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3682 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3683 UINT VertexStreamZeroStride) {
3684 int idxStride;
3685 ICOM_THIS(IDirect3DDevice8Impl,iface);
3686 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),
3687 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3689 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3690 if (IndexDataFormat == D3DFMT_INDEX16) {
3691 idxStride = 2;
3692 } else {
3693 idxStride = 4;
3696 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3697 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3698 This->StateBlock->streamIsUP = TRUE;
3699 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3700 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3702 /*stream zero settings set to null at end */
3703 This->StateBlock->stream_source[0] = NULL;
3704 This->StateBlock->stream_stride[0] = 0;
3705 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3707 return D3D_OK;
3709 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3710 ICOM_THIS(IDirect3DDevice8Impl,iface);
3711 FIXME("(%p) : stub\n", This); return D3D_OK;
3713 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3714 ICOM_THIS(IDirect3DDevice8Impl,iface);
3715 IDirect3DVertexShaderImpl* object;
3716 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3717 HRESULT res;
3718 UINT i;
3720 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3721 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3722 return D3DERR_INVALIDCALL;
3724 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3725 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3726 return D3DERR_OUTOFVIDEOMEMORY;
3729 /** Create the Vertex Shader */
3730 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3731 /** TODO: check FAILED(res) */
3733 /** Create and Bind the Vertex Shader Declaration */
3734 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3735 /** TODO: check FAILED(res) */
3737 VertexShaders[i] = object;
3738 VertexShaderDeclarations[i] = attached_decl;
3739 *pHandle = VS_HIGHESTFIXEDFXF + i;
3740 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3742 return D3D_OK;
3744 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3745 ICOM_THIS(IDirect3DDevice8Impl,iface);
3747 This->UpdateStateBlock->VertexShader = Handle;
3748 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3749 This->UpdateStateBlock->Set.vertexShader = TRUE;
3751 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3752 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3753 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3754 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3755 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3756 } else { /* use a fvf, so desactivate the vshader decl */
3757 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3758 This->UpdateStateBlock->vertexShaderDecl = NULL;
3759 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3760 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3762 /* Handle recording of state blocks */
3763 if (This->isRecordingState) {
3764 TRACE("Recording... not performing anything\n");
3765 return D3D_OK;
3768 * TODO: merge HAL shaders context switching from prototype
3770 return D3D_OK;
3772 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3773 ICOM_THIS(IDirect3DDevice8Impl,iface);
3774 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3775 *pHandle = This->StateBlock->VertexShader;
3776 return D3D_OK;
3779 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3780 ICOM_THIS(IDirect3DDevice8Impl,iface);
3781 IDirect3DVertexShaderImpl* object;
3782 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3784 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3785 return D3DERR_INVALIDCALL;
3789 * Delete Vertex Shader
3791 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3792 if (NULL == object) {
3793 return D3DERR_INVALIDCALL;
3795 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3796 /* TODO: check validity of object */
3797 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3798 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3799 HeapFree(GetProcessHeap(), 0, (void *)object);
3800 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3803 * Delete Vertex Shader Declaration
3805 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3806 if (NULL == attached_decl) {
3807 return D3DERR_INVALIDCALL;
3809 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3810 /* TODO: check validity of object */
3811 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3812 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3813 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3815 return D3D_OK;
3818 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3819 ICOM_THIS(IDirect3DDevice8Impl,iface);
3821 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3822 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3823 return D3DERR_INVALIDCALL;
3825 if (NULL == pConstantData) {
3826 return D3DERR_INVALIDCALL;
3828 if (ConstantCount > 1) {
3829 FLOAT* f = (FLOAT*)pConstantData;
3830 UINT i;
3831 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3832 for (i = 0; i < ConstantCount; ++i) {
3833 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3834 f += 4;
3836 } else {
3837 FLOAT* f = (FLOAT*) pConstantData;
3838 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3840 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3841 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3842 return D3D_OK;
3844 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3845 ICOM_THIS(IDirect3DDevice8Impl,iface);
3847 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3848 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3849 return D3DERR_INVALIDCALL;
3851 if (NULL == pConstantData) {
3852 return D3DERR_INVALIDCALL;
3854 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3855 return D3D_OK;
3857 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3858 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3859 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3861 attached_decl = VERTEX_SHADER_DECL(Handle);
3862 if (NULL == attached_decl) {
3863 return D3DERR_INVALIDCALL;
3865 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3867 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3868 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3869 IDirect3DVertexShaderImpl* object;
3871 object = VERTEX_SHADER(Handle);
3872 if (NULL == object) {
3873 return D3DERR_INVALIDCALL;
3875 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3878 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3879 ICOM_THIS(IDirect3DDevice8Impl,iface);
3880 IDirect3DIndexBuffer8 *oldIdxs;
3882 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3883 oldIdxs = This->StateBlock->pIndexData;
3885 This->UpdateStateBlock->Changed.Indices = TRUE;
3886 This->UpdateStateBlock->Set.Indices = TRUE;
3887 This->UpdateStateBlock->pIndexData = pIndexData;
3888 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3890 /* Handle recording of state blocks */
3891 if (This->isRecordingState) {
3892 TRACE("Recording... not performing anything\n");
3893 return D3D_OK;
3896 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3897 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3898 return D3D_OK;
3900 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3901 ICOM_THIS(IDirect3DDevice8Impl,iface);
3902 FIXME("(%p) : stub\n", This);
3904 *ppIndexData = This->StateBlock->pIndexData;
3905 /* up ref count on ppindexdata */
3906 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3907 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3909 return D3D_OK;
3911 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3912 ICOM_THIS(IDirect3DDevice8Impl,iface);
3913 IDirect3DPixelShaderImpl* object;
3914 HRESULT res;
3915 UINT i;
3917 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3918 if (NULL == pFunction || NULL == pHandle) {
3919 return D3DERR_INVALIDCALL;
3921 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3922 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3923 return D3DERR_OUTOFVIDEOMEMORY;
3926 /** Create the Pixel Shader */
3927 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3928 if (SUCCEEDED(res)) {
3929 PixelShaders[i] = object;
3930 *pHandle = VS_HIGHESTFIXEDFXF + i;
3931 return D3D_OK;
3933 *pHandle = 0xFFFFFFFF;
3934 return res;
3936 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3937 ICOM_THIS(IDirect3DDevice8Impl,iface);
3939 This->UpdateStateBlock->PixelShader = Handle;
3940 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3941 This->UpdateStateBlock->Set.pixelShader = TRUE;
3943 /* Handle recording of state blocks */
3944 if (This->isRecordingState) {
3945 TRACE_(d3d_shader)("Recording... not performing anything\n");
3946 return D3D_OK;
3949 /* FIXME: Quieten when not being used */
3950 if (Handle != 0) {
3951 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3952 } else {
3953 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3956 return D3D_OK;
3958 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3959 ICOM_THIS(IDirect3DDevice8Impl,iface);
3960 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3961 *pHandle = This->StateBlock->PixelShader;
3962 return D3D_OK;
3965 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3966 ICOM_THIS(IDirect3DDevice8Impl,iface);
3967 IDirect3DPixelShaderImpl* object;
3969 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3970 return D3DERR_INVALIDCALL;
3972 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3973 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3974 /* TODO: check validity of object before free */
3975 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3976 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3977 HeapFree(GetProcessHeap(), 0, (void *)object);
3978 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3980 return D3D_OK;
3983 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3984 ICOM_THIS(IDirect3DDevice8Impl,iface);
3986 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3987 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3988 return D3DERR_INVALIDCALL;
3990 if (NULL == pConstantData) {
3991 return D3DERR_INVALIDCALL;
3993 if (ConstantCount > 1) {
3994 FLOAT* f = (FLOAT*)pConstantData;
3995 UINT i;
3996 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3997 for (i = 0; i < ConstantCount; ++i) {
3998 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3999 f += 4;
4001 } else {
4002 FLOAT* f = (FLOAT*) pConstantData;
4003 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4005 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4006 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4007 return D3D_OK;
4009 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4010 ICOM_THIS(IDirect3DDevice8Impl,iface);
4012 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4013 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4014 return D3DERR_INVALIDCALL;
4016 if (NULL == pConstantData) {
4017 return D3DERR_INVALIDCALL;
4019 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4020 return D3D_OK;
4022 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4023 IDirect3DPixelShaderImpl* object;
4025 object = PIXEL_SHADER(Handle);
4026 if (NULL == object) {
4027 return D3DERR_INVALIDCALL;
4029 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4031 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4032 ICOM_THIS(IDirect3DDevice8Impl,iface);
4033 FIXME("(%p) : stub\n", This); return D3D_OK;
4035 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4036 ICOM_THIS(IDirect3DDevice8Impl,iface);
4037 FIXME("(%p) : stub\n", This); return D3D_OK;
4039 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4040 ICOM_THIS(IDirect3DDevice8Impl,iface);
4041 FIXME("(%p) : stub\n", This); return D3D_OK;
4044 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4045 IDirect3DVertexBuffer8 *oldSrc;
4046 ICOM_THIS(IDirect3DDevice8Impl,iface);
4048 oldSrc = This->StateBlock->stream_source[StreamNumber];
4049 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4051 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4052 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4053 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4054 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4056 /* Handle recording of state blocks */
4057 if (This->isRecordingState) {
4058 TRACE("Recording... not performing anything\n");
4059 return D3D_OK;
4062 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4063 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4064 return D3D_OK;
4066 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4067 ICOM_THIS(IDirect3DDevice8Impl,iface);
4068 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4069 *pStream = This->StateBlock->stream_source[StreamNumber];
4070 *pStride = This->StateBlock->stream_stride[StreamNumber];
4071 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4072 return D3D_OK;
4076 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4078 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4079 IDirect3DDevice8Impl_QueryInterface,
4080 IDirect3DDevice8Impl_AddRef,
4081 IDirect3DDevice8Impl_Release,
4082 IDirect3DDevice8Impl_TestCooperativeLevel,
4083 IDirect3DDevice8Impl_GetAvailableTextureMem,
4084 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4085 IDirect3DDevice8Impl_GetDirect3D,
4086 IDirect3DDevice8Impl_GetDeviceCaps,
4087 IDirect3DDevice8Impl_GetDisplayMode,
4088 IDirect3DDevice8Impl_GetCreationParameters,
4089 IDirect3DDevice8Impl_SetCursorProperties,
4090 IDirect3DDevice8Impl_SetCursorPosition,
4091 IDirect3DDevice8Impl_ShowCursor,
4092 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4093 IDirect3DDevice8Impl_Reset,
4094 IDirect3DDevice8Impl_Present,
4095 IDirect3DDevice8Impl_GetBackBuffer,
4096 IDirect3DDevice8Impl_GetRasterStatus,
4097 IDirect3DDevice8Impl_SetGammaRamp,
4098 IDirect3DDevice8Impl_GetGammaRamp,
4099 IDirect3DDevice8Impl_CreateTexture,
4100 IDirect3DDevice8Impl_CreateVolumeTexture,
4101 IDirect3DDevice8Impl_CreateCubeTexture,
4102 IDirect3DDevice8Impl_CreateVertexBuffer,
4103 IDirect3DDevice8Impl_CreateIndexBuffer,
4104 IDirect3DDevice8Impl_CreateRenderTarget,
4105 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4106 IDirect3DDevice8Impl_CreateImageSurface,
4107 IDirect3DDevice8Impl_CopyRects,
4108 IDirect3DDevice8Impl_UpdateTexture,
4109 IDirect3DDevice8Impl_GetFrontBuffer,
4110 IDirect3DDevice8Impl_SetRenderTarget,
4111 IDirect3DDevice8Impl_GetRenderTarget,
4112 IDirect3DDevice8Impl_GetDepthStencilSurface,
4113 IDirect3DDevice8Impl_BeginScene,
4114 IDirect3DDevice8Impl_EndScene,
4115 IDirect3DDevice8Impl_Clear,
4116 IDirect3DDevice8Impl_SetTransform,
4117 IDirect3DDevice8Impl_GetTransform,
4118 IDirect3DDevice8Impl_MultiplyTransform,
4119 IDirect3DDevice8Impl_SetViewport,
4120 IDirect3DDevice8Impl_GetViewport,
4121 IDirect3DDevice8Impl_SetMaterial,
4122 IDirect3DDevice8Impl_GetMaterial,
4123 IDirect3DDevice8Impl_SetLight,
4124 IDirect3DDevice8Impl_GetLight,
4125 IDirect3DDevice8Impl_LightEnable,
4126 IDirect3DDevice8Impl_GetLightEnable,
4127 IDirect3DDevice8Impl_SetClipPlane,
4128 IDirect3DDevice8Impl_GetClipPlane,
4129 IDirect3DDevice8Impl_SetRenderState,
4130 IDirect3DDevice8Impl_GetRenderState,
4131 IDirect3DDevice8Impl_BeginStateBlock,
4132 IDirect3DDevice8Impl_EndStateBlock,
4133 IDirect3DDevice8Impl_ApplyStateBlock,
4134 IDirect3DDevice8Impl_CaptureStateBlock,
4135 IDirect3DDevice8Impl_DeleteStateBlock,
4136 IDirect3DDevice8Impl_CreateStateBlock,
4137 IDirect3DDevice8Impl_SetClipStatus,
4138 IDirect3DDevice8Impl_GetClipStatus,
4139 IDirect3DDevice8Impl_GetTexture,
4140 IDirect3DDevice8Impl_SetTexture,
4141 IDirect3DDevice8Impl_GetTextureStageState,
4142 IDirect3DDevice8Impl_SetTextureStageState,
4143 IDirect3DDevice8Impl_ValidateDevice,
4144 IDirect3DDevice8Impl_GetInfo,
4145 IDirect3DDevice8Impl_SetPaletteEntries,
4146 IDirect3DDevice8Impl_GetPaletteEntries,
4147 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4148 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4149 IDirect3DDevice8Impl_DrawPrimitive,
4150 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4151 IDirect3DDevice8Impl_DrawPrimitiveUP,
4152 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4153 IDirect3DDevice8Impl_ProcessVertices,
4154 IDirect3DDevice8Impl_CreateVertexShader,
4155 IDirect3DDevice8Impl_SetVertexShader,
4156 IDirect3DDevice8Impl_GetVertexShader,
4157 IDirect3DDevice8Impl_DeleteVertexShader,
4158 IDirect3DDevice8Impl_SetVertexShaderConstant,
4159 IDirect3DDevice8Impl_GetVertexShaderConstant,
4160 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4161 IDirect3DDevice8Impl_GetVertexShaderFunction,
4162 IDirect3DDevice8Impl_SetStreamSource,
4163 IDirect3DDevice8Impl_GetStreamSource,
4164 IDirect3DDevice8Impl_SetIndices,
4165 IDirect3DDevice8Impl_GetIndices,
4166 IDirect3DDevice8Impl_CreatePixelShader,
4167 IDirect3DDevice8Impl_SetPixelShader,
4168 IDirect3DDevice8Impl_GetPixelShader,
4169 IDirect3DDevice8Impl_DeletePixelShader,
4170 IDirect3DDevice8Impl_SetPixelShaderConstant,
4171 IDirect3DDevice8Impl_GetPixelShaderConstant,
4172 IDirect3DDevice8Impl_GetPixelShaderFunction,
4173 IDirect3DDevice8Impl_DrawRectPatch,
4174 IDirect3DDevice8Impl_DrawTriPatch,
4175 IDirect3DDevice8Impl_DeletePatch
4178 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4180 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4181 ICOM_THIS(IDirect3DDevice8Impl,iface);
4183 ENTER_GL();
4185 #if 0
4186 if (This->glCtx != This->render_ctx) {
4187 glXDestroyContext(This->display, This->render_ctx);
4188 This->render_ctx = This->glCtx;
4190 #endif
4191 if (This->win != This->drawable) {
4192 glXDestroyPbuffer(This->display, This->drawable);
4193 This->drawable = This->win;
4196 LEAVE_GL();
4198 #endif
4199 return D3D_OK;
4202 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4203 IDirect3DSurface8* RenderSurface,
4204 IDirect3DSurface8* StencilSurface) {
4206 HRESULT ret = D3DERR_INVALIDCALL;
4208 * Currently only active for GLX >= 1.3
4209 * for others versions we'll have to use GLXPixmaps
4211 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4212 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4213 * so only check OpenGL version
4215 #if defined(GL_VERSION_1_3)
4216 GLXFBConfig* cfgs = NULL;
4217 int nCfgs = 0;
4218 int attribs[256];
4219 int nAttribs = 0;
4220 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4221 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4222 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4223 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4224 IDirect3DSurface8Impl* tmp;
4226 ICOM_THIS(IDirect3DDevice8Impl,iface);
4228 #define PUSH1(att) attribs[nAttribs++] = (att);
4229 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4231 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4232 PUSH2(GLX_X_RENDERABLE, TRUE);
4233 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4235 switch (BackBufferFormat) {
4236 /* color buffer */
4237 case D3DFMT_P8:
4238 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4239 PUSH2(GLX_BUFFER_SIZE, 8);
4240 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4241 break;
4243 case D3DFMT_R3G3B2:
4244 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4245 PUSH2(GLX_RED_SIZE, 3);
4246 PUSH2(GLX_GREEN_SIZE, 3);
4247 PUSH2(GLX_BLUE_SIZE, 2);
4248 break;
4250 case D3DFMT_A1R5G5B5:
4251 PUSH2(GLX_ALPHA_SIZE, 1);
4252 case D3DFMT_X1R5G5B5:
4253 PUSH2(GLX_RED_SIZE, 5);
4254 PUSH2(GLX_GREEN_SIZE, 5);
4255 PUSH2(GLX_BLUE_SIZE, 5);
4256 break;
4258 case D3DFMT_R5G6B5:
4259 PUSH2(GLX_RED_SIZE, 5);
4260 PUSH2(GLX_GREEN_SIZE, 6);
4261 PUSH2(GLX_BLUE_SIZE, 5);
4262 break;
4264 case D3DFMT_A4R4G4B4:
4265 PUSH2(GLX_ALPHA_SIZE, 4);
4266 case D3DFMT_X4R4G4B4:
4267 PUSH2(GLX_RED_SIZE, 4);
4268 PUSH2(GLX_GREEN_SIZE, 4);
4269 PUSH2(GLX_BLUE_SIZE, 4);
4270 break;
4272 case D3DFMT_A8R8G8B8:
4273 PUSH2(GLX_ALPHA_SIZE, 8);
4274 case D3DFMT_R8G8B8:
4275 case D3DFMT_X8R8G8B8:
4276 PUSH2(GLX_RED_SIZE, 8);
4277 PUSH2(GLX_GREEN_SIZE, 8);
4278 PUSH2(GLX_BLUE_SIZE, 8);
4279 break;
4281 default:
4282 break;
4285 switch (StencilBufferFormat) {
4286 case D3DFMT_D16_LOCKABLE:
4287 case D3DFMT_D16:
4288 PUSH2(GLX_DEPTH_SIZE, 16);
4289 break;
4291 case D3DFMT_D15S1:
4292 PUSH2(GLX_DEPTH_SIZE, 15);
4293 break;
4295 case D3DFMT_D24X8:
4296 PUSH2(GLX_DEPTH_SIZE, 24);
4297 break;
4299 case D3DFMT_D24X4S4:
4300 PUSH2(GLX_DEPTH_SIZE, 24);
4301 PUSH2(GLX_STENCIL_SIZE, 4);
4302 break;
4304 case D3DFMT_D24S8:
4305 PUSH2(GLX_DEPTH_SIZE, 24);
4306 PUSH2(GLX_STENCIL_SIZE, 8);
4307 break;
4309 case D3DFMT_D32:
4310 PUSH2(GLX_DEPTH_SIZE, 32);
4311 break;
4313 default:
4314 break;
4317 PUSH1(None);
4319 ENTER_GL();
4321 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4322 if (NULL != cfgs) {
4323 #if 0
4324 int i;
4325 for (i = 0; i < nCfgs; ++i) {
4326 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4328 #endif
4330 if (NULL != This->renderTarget) {
4331 GLenum prev_read;
4332 glFlush();
4333 vcheckGLcall("glFlush");
4335 #if 0
4336 /** very very usefull debug code */
4337 glXSwapBuffers(This->display, This->drawable);
4338 printf("Hit Enter to get next frame ...\n");
4339 getchar();
4340 #endif
4342 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4343 vcheckGLcall("glIntegerv");
4344 glReadBuffer(GL_BACK);
4345 vcheckGLcall("glReadBuffer");
4347 long j;
4348 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4350 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4351 pitch = pitch / 2;
4353 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4354 glReadPixels(0,
4355 This->renderTarget->myDesc.Height - j - 1,
4356 This->renderTarget->myDesc.Width,
4358 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4359 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4360 This->renderTarget->allocatedMemory + j * pitch);
4361 vcheckGLcall("glReadPixels");
4364 glReadBuffer(prev_read);
4365 vcheckGLcall("glReadBuffer");
4368 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4369 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4370 nAttribs = 0;
4371 PUSH2(GLX_PBUFFER_WIDTH, Width);
4372 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4373 PUSH1(None);
4374 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4376 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4377 if (NULL == This->render_ctx) {
4378 ERR("cannot create glxContext\n");
4381 glFlush();
4382 glXSwapBuffers(This->display, This->drawable);
4383 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4384 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4386 checkGLcall("glXMakeContextCurrent");
4389 tmp = This->renderTarget;
4390 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4391 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4392 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4394 tmp = This->stencilBufferTarget;
4395 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4396 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4397 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4399 ret = D3D_OK;
4401 } else {
4402 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4405 #undef PUSH1
4406 #undef PUSH2
4408 LEAVE_GL();
4410 #endif
4412 return ret;