ColorWriteEnable should not impact clearing the screen.
[wine/gsoc_dplay.git] / dlls / d3d8 / device.c
blob72b754112b60658dea895c9620ac24ca5a3d6117
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 - 1); 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 curRect = pRects;
1356 } else {
1357 curRect = NULL;
1360 /* Only set the values up once, as they are not changing */
1361 if (Flags & D3DCLEAR_STENCIL) {
1362 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1363 glClearStencil(Stencil);
1364 checkGLcall("glClearStencil");
1365 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1368 if (Flags & D3DCLEAR_ZBUFFER) {
1369 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1370 glDepthMask(GL_TRUE);
1371 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1372 glClearDepth(Z);
1373 checkGLcall("glClearDepth");
1374 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1377 if (Flags & D3DCLEAR_TARGET) {
1378 TRACE("Clearing screen with glClear to color %lx\n", Color);
1379 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1380 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1381 ((Color >> 8) & 0xFF) / 255.0f,
1382 ((Color >> 0) & 0xFF) / 255.0f,
1383 ((Color >> 24) & 0xFF) / 255.0f);
1384 checkGLcall("glClearColor");
1386 /* Clear ALL colors! */
1387 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1388 glMask = glMask | GL_COLOR_BUFFER_BIT;
1391 /* Now process each rect in turn */
1392 for (i = 0; i < Count || i == 0; i++) {
1394 if (curRect) {
1395 /* Note gl uses lower left, width/height */
1396 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1397 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1398 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1399 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1400 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1401 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1402 checkGLcall("glScissor");
1403 } else {
1404 glScissor(This->StateBlock->viewport.X,
1405 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1406 This->StateBlock->viewport.Width,
1407 This->StateBlock->viewport.Height);
1408 checkGLcall("glScissor");
1411 /* Clear the selected rectangle (or full screen) */
1412 glClear(glMask);
1413 checkGLcall("glClear");
1415 /* Step to the next rectangle */
1416 if (curRect) curRect = curRect + sizeof(D3DRECT);
1419 /* Restore the old values (why..?) */
1420 if (Flags & D3DCLEAR_STENCIL) {
1421 glClearStencil(old_stencil_clear_value);
1423 if (Flags & D3DCLEAR_ZBUFFER) {
1424 glDepthMask(old_ztest);
1425 glClearDepth(old_z_clear_value);
1427 if (Flags & D3DCLEAR_TARGET) {
1428 glClearColor(old_color_clear_value[0],
1429 old_color_clear_value[1],
1430 old_color_clear_value[2],
1431 old_color_clear_value[3]);
1432 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1433 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1434 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1435 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1438 glDisable(GL_SCISSOR_TEST);
1439 checkGLcall("glDisable");
1440 LEAVE_GL();
1442 return D3D_OK;
1444 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1445 ICOM_THIS(IDirect3DDevice8Impl,iface);
1446 int k;
1448 /* Most of this routine, comments included copied from ddraw tree initially: */
1449 TRACE("(%p) : State=%d\n", This, d3dts);
1451 /* Handle recording of state blocks */
1452 if (This->isRecordingState) {
1453 TRACE("Recording... not performing anything\n");
1454 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1455 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1456 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1457 return D3D_OK;
1461 * if the new matrix is the same as the current one,
1462 * we cut off any further processing. this seems to be a reasonable
1463 * optimization because as was noticed, some apps (warcraft3 for example)
1464 * tend towards setting the same matrix repeatedly for some dumb reason.
1466 * From here on we assume that the new matrix is different, wherever it matters
1467 * but note
1469 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1470 TRACE("The app is setting the same matrix over again\n");
1471 return D3D_OK;
1472 } else {
1473 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1477 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1478 where ViewMat = Camera space, WorldMat = world space.
1480 In OpenGL, camera and world space is combined into GL_MODELVIEW
1481 matrix. The Projection matrix stay projection matrix.
1484 /* Capture the times we can just ignore the change */
1485 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1486 This->modelview_valid = FALSE;
1487 return D3D_OK;
1489 } else if (d3dts == D3DTS_PROJECTION) {
1490 This->proj_valid = FALSE;
1491 return D3D_OK;
1493 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1494 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1495 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1496 return D3D_OK;
1499 /* Chances are we really are going to have to change a matrix */
1500 ENTER_GL();
1502 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1503 if (d3dts < GL_LIMITS(textures)) {
1504 int tex = d3dts - D3DTS_TEXTURE0;
1505 #if defined(GL_VERSION_1_3)
1506 glActiveTexture(GL_TEXTURE0 + tex);
1507 #else
1508 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1509 #endif
1510 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1513 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1515 PLIGHTINFOEL *lightChain = NULL;
1516 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1517 This->modelview_valid = FALSE;
1518 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1519 glMatrixMode(GL_MODELVIEW);
1520 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1521 glPushMatrix();
1522 glLoadMatrixf((float *)lpmatrix);
1523 checkGLcall("glLoadMatrixf(...)");
1525 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1526 * NOTE: We have to reset the positions even if the light/plane is not currently
1527 * enabled, since the call to enable it will not reset the position.
1528 * NOTE2: Apparently texture transforms do NOT need reapplying
1531 /* Reset lights */
1532 lightChain = This->StateBlock->lights;
1533 while (lightChain && lightChain->glIndex != -1) {
1534 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1535 checkGLcall("glLightfv posn");
1536 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1537 checkGLcall("glLightfv dirn");
1538 lightChain = lightChain->next;
1540 /* Reset Clipping Planes if clipping is enabled */
1541 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1542 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1543 checkGLcall("glClipPlane");
1545 glPopMatrix();
1547 } else { /* What was requested!?? */
1548 WARN("invalid matrix specified: %i\n", d3dts);
1552 /* Release lock, all done */
1553 LEAVE_GL();
1554 return D3D_OK;
1557 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1558 ICOM_THIS(IDirect3DDevice8Impl,iface);
1559 TRACE("(%p) : for State %d\n", This, State);
1560 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1561 return D3D_OK;
1564 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1565 D3DMATRIX *mat = NULL;
1566 D3DMATRIX temp;
1568 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1569 but works regardless of recording being on.
1570 If this is found to be wrong, change to StateBlock. */
1571 ICOM_THIS(IDirect3DDevice8Impl,iface);
1572 TRACE("(%p) : For state %u\n", This, State);
1574 if (State < HIGHEST_TRANSFORMSTATE)
1576 mat = &This->UpdateStateBlock->transforms[State];
1577 } else {
1578 FIXME("Unhandled transform state!!\n");
1581 /* Copied from ddraw code: */
1582 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);
1583 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);
1584 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);
1585 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);
1587 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);
1588 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);
1589 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);
1590 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);
1592 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);
1593 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);
1594 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);
1595 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);
1597 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);
1598 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);
1599 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);
1600 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);
1602 /* Apply change via set transform - will reapply to eg. lights this way */
1603 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1604 return D3D_OK;
1606 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1607 ICOM_THIS(IDirect3DDevice8Impl,iface);
1609 TRACE("(%p)\n", This);
1610 This->UpdateStateBlock->Changed.viewport = TRUE;
1611 This->UpdateStateBlock->Set.viewport = TRUE;
1612 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1614 /* Handle recording of state blocks */
1615 if (This->isRecordingState) {
1616 TRACE("Recording... not performing anything\n");
1617 return D3D_OK;
1620 ENTER_GL();
1622 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1623 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1625 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1626 checkGLcall("glDepthRange");
1627 /* Note: GL requires lower left, DirectX supplies upper left */
1628 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1629 pViewport->Width, pViewport->Height);
1630 checkGLcall("glViewport");
1632 LEAVE_GL();
1634 return D3D_OK;
1637 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1638 ICOM_THIS(IDirect3DDevice8Impl,iface);
1639 TRACE("(%p)\n", This);
1640 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1641 return D3D_OK;
1644 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1645 ICOM_THIS(IDirect3DDevice8Impl,iface);
1647 This->UpdateStateBlock->Changed.material = TRUE;
1648 This->UpdateStateBlock->Set.material = TRUE;
1649 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1651 /* Handle recording of state blocks */
1652 if (This->isRecordingState) {
1653 TRACE("Recording... not performing anything\n");
1654 return D3D_OK;
1657 ENTER_GL();
1658 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1659 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1660 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1661 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1662 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1664 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1665 checkGLcall("glMaterialfv");
1666 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1667 checkGLcall("glMaterialfv");
1669 /* Only change material color if specular is enabled, otherwise it is set to black */
1670 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1671 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1672 checkGLcall("glMaterialfv");
1673 } else {
1674 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1675 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1676 checkGLcall("glMaterialfv");
1678 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1679 checkGLcall("glMaterialfv");
1680 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1681 checkGLcall("glMaterialf");
1683 LEAVE_GL();
1684 return D3D_OK;
1686 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1687 ICOM_THIS(IDirect3DDevice8Impl,iface);
1688 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1689 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1690 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1691 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1692 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1693 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1694 return D3D_OK;
1697 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1698 you can reference any indexes you want as long as that number max are enabled are any
1699 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1700 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1701 but when recording, just build a chain pretty much of commands to be replayed. */
1703 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1704 float rho;
1705 PLIGHTINFOEL *object, *temp;
1707 ICOM_THIS(IDirect3DDevice8Impl,iface);
1708 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1710 /* If recording state block, just add to end of lights chain */
1711 if (This->isRecordingState) {
1712 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1713 if (NULL == object) {
1714 return D3DERR_OUTOFVIDEOMEMORY;
1716 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1717 object->OriginalIndex = Index;
1718 object->glIndex = -1;
1719 object->changed = TRUE;
1721 /* Add to the END of the chain of lights changes to be replayed */
1722 if (This->UpdateStateBlock->lights == NULL) {
1723 This->UpdateStateBlock->lights = object;
1724 } else {
1725 temp = This->UpdateStateBlock->lights;
1726 while (temp->next != NULL) temp=temp->next;
1727 temp->next = object;
1729 TRACE("Recording... not performing anything more\n");
1730 return D3D_OK;
1733 /* Ok, not recording any longer so do real work */
1734 object = This->StateBlock->lights;
1735 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1737 /* If we didnt find it in the list of lights, time to add it */
1738 if (object == NULL) {
1739 PLIGHTINFOEL *insertAt,*prevPos;
1741 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1742 if (NULL == object) {
1743 return D3DERR_OUTOFVIDEOMEMORY;
1745 object->OriginalIndex = Index;
1746 object->glIndex = -1;
1748 /* Add it to the front of list with the idea that lights will be changed as needed
1749 BUT after any lights currently assigned GL indexes */
1750 insertAt = This->StateBlock->lights;
1751 prevPos = NULL;
1752 while (insertAt != NULL && insertAt->glIndex != -1) {
1753 prevPos = insertAt;
1754 insertAt = insertAt->next;
1757 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1758 This->StateBlock->lights = object;
1759 } else if (insertAt == NULL) { /* End of list */
1760 prevPos->next = object;
1761 object->prev = prevPos;
1762 } else { /* Middle of chain */
1763 if (prevPos == NULL) {
1764 This->StateBlock->lights = object;
1765 } else {
1766 prevPos->next = object;
1768 object->prev = prevPos;
1769 object->next = insertAt;
1770 insertAt->prev = object;
1774 /* Initialze the object */
1775 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,
1776 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1777 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1778 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1779 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1780 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1781 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1783 /* Save away the information */
1784 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1786 switch (pLight->Type) {
1787 case D3DLIGHT_POINT:
1788 /* Position */
1789 object->lightPosn[0] = pLight->Position.x;
1790 object->lightPosn[1] = pLight->Position.y;
1791 object->lightPosn[2] = pLight->Position.z;
1792 object->lightPosn[3] = 1.0f;
1793 object->cutoff = 180.0f;
1794 /* FIXME: Range */
1795 break;
1797 case D3DLIGHT_SPOT:
1798 /* Position */
1799 object->lightPosn[0] = pLight->Position.x;
1800 object->lightPosn[1] = pLight->Position.y;
1801 object->lightPosn[2] = pLight->Position.z;
1802 object->lightPosn[3] = 1.0;
1804 /* Direction */
1805 object->lightDirn[0] = pLight->Direction.x;
1806 object->lightDirn[1] = pLight->Direction.y;
1807 object->lightDirn[2] = pLight->Direction.z;
1808 object->lightDirn[3] = 1.0;
1811 * opengl-ish and d3d-ish spot lights use too different models for the
1812 * light "intensity" as a function of the angle towards the main light direction,
1813 * so we only can approximate very roughly.
1814 * however spot lights are rather rarely used in games (if ever used at all).
1815 * furthermore if still used, probably nobody pays attention to such details.
1817 if (pLight->Falloff == 0) {
1818 rho = 6.28f;
1819 } else {
1820 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1822 if (rho < 0.0001) rho = 0.0001f;
1823 object->exponent = -0.3/log(cos(rho/2));
1824 object->cutoff = pLight->Phi*90/M_PI;
1826 /* FIXME: Range */
1827 break;
1829 case D3DLIGHT_DIRECTIONAL:
1830 /* Direction */
1831 object->lightPosn[0] = -pLight->Direction.x;
1832 object->lightPosn[1] = -pLight->Direction.y;
1833 object->lightPosn[2] = -pLight->Direction.z;
1834 object->lightPosn[3] = 0.0;
1835 object->exponent = 0.0f;
1836 object->cutoff = 180.0f;
1837 break;
1839 default:
1840 FIXME("Unrecognized light type %d\n", pLight->Type);
1843 /* Update the live definitions if the light is currently assigned a glIndex */
1844 if (object->glIndex != -1) {
1845 setup_light(iface, object->glIndex, object);
1847 return D3D_OK;
1849 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1850 PLIGHTINFOEL *lightInfo = NULL;
1851 ICOM_THIS(IDirect3DDevice8Impl,iface);
1852 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1854 /* Locate the light in the live lights */
1855 lightInfo = This->StateBlock->lights;
1856 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1858 if (lightInfo == NULL) {
1859 TRACE("Light information requested but light not defined\n");
1860 return D3DERR_INVALIDCALL;
1863 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1864 return D3D_OK;
1866 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1867 PLIGHTINFOEL *lightInfo = NULL;
1868 ICOM_THIS(IDirect3DDevice8Impl,iface);
1869 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1871 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1872 if (This->isRecordingState) {
1873 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1874 if (NULL == lightInfo) {
1875 return D3DERR_OUTOFVIDEOMEMORY;
1877 lightInfo->OriginalIndex = Index;
1878 lightInfo->glIndex = -1;
1879 lightInfo->enabledChanged = TRUE;
1881 /* Add to the END of the chain of lights changes to be replayed */
1882 if (This->UpdateStateBlock->lights == NULL) {
1883 This->UpdateStateBlock->lights = lightInfo;
1884 } else {
1885 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1886 while (temp->next != NULL) temp=temp->next;
1887 temp->next = lightInfo;
1889 TRACE("Recording... not performing anything more\n");
1890 return D3D_OK;
1893 /* Not recording... So, locate the light in the live lights */
1894 lightInfo = This->StateBlock->lights;
1895 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1897 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1898 if (lightInfo == NULL) {
1899 D3DLIGHT8 lightParms;
1900 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1901 wait until someone confirms it seems to work! */
1902 TRACE("Light enabled requested but light not defined, so defining one!\n");
1903 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1904 lightParms.Diffuse.r = 1.0;
1905 lightParms.Diffuse.g = 1.0;
1906 lightParms.Diffuse.b = 1.0;
1907 lightParms.Diffuse.a = 0.0;
1908 lightParms.Specular.r = 0.0;
1909 lightParms.Specular.g = 0.0;
1910 lightParms.Specular.b = 0.0;
1911 lightParms.Specular.a = 0.0;
1912 lightParms.Ambient.r = 0.0;
1913 lightParms.Ambient.g = 0.0;
1914 lightParms.Ambient.b = 0.0;
1915 lightParms.Ambient.a = 0.0;
1916 lightParms.Position.x = 0.0;
1917 lightParms.Position.y = 0.0;
1918 lightParms.Position.z = 0.0;
1919 lightParms.Direction.x = 0.0;
1920 lightParms.Direction.y = 0.0;
1921 lightParms.Direction.z = 1.0;
1922 lightParms.Range = 0.0;
1923 lightParms.Falloff = 0.0;
1924 lightParms.Attenuation0 = 0.0;
1925 lightParms.Attenuation1 = 0.0;
1926 lightParms.Attenuation2 = 0.0;
1927 lightParms.Theta = 0.0;
1928 lightParms.Phi = 0.0;
1929 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1931 /* Search for it again! Should be fairly quick as near head of list */
1932 lightInfo = This->StateBlock->lights;
1933 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1934 if (lightInfo == NULL) {
1935 FIXME("Adding default lights has failed dismally\n");
1936 return D3DERR_INVALIDCALL;
1940 /* OK, we now have a light... */
1941 if (Enable == FALSE) {
1943 /* If we are disabling it, check it was enabled, and
1944 still only do something if it has assigned a glIndex (which it should have!) */
1945 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1946 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1947 ENTER_GL();
1948 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1949 checkGLcall("glDisable GL_LIGHT0+Index");
1950 LEAVE_GL();
1951 } else {
1952 TRACE("Nothing to do as light was not enabled\n");
1954 lightInfo->lightEnabled = FALSE;
1955 } else {
1957 /* We are enabling it. If it is enabled, its really simple */
1958 if (lightInfo->lightEnabled == TRUE) {
1959 /* nop */
1960 TRACE("Nothing to do as light was enabled\n");
1962 /* If it already has a glIndex, its still simple */
1963 } else if (lightInfo->glIndex != -1) {
1964 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1965 lightInfo->lightEnabled = TRUE;
1966 ENTER_GL();
1967 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1968 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1969 LEAVE_GL();
1971 /* Otherwise got to find space - lights are ordered gl indexes first */
1972 } else {
1973 PLIGHTINFOEL *bsf = NULL;
1974 PLIGHTINFOEL *pos = This->StateBlock->lights;
1975 PLIGHTINFOEL *prev = NULL;
1976 int Index= 0;
1977 int glIndex = -1;
1979 /* Try to minimize changes as much as possible */
1980 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1982 /* Try to remember which index can be replaced if necessary */
1983 if (bsf==NULL && pos->lightEnabled == FALSE) {
1984 /* Found a light we can replace, save as best replacement */
1985 bsf = pos;
1988 /* Step to next space */
1989 prev = pos;
1990 pos = pos->next;
1991 Index ++;
1994 /* If we have too many active lights, fail the call */
1995 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1996 FIXME("Program requests too many concurrent lights\n");
1997 return D3DERR_INVALIDCALL;
1999 /* If we have allocated all lights, but not all are enabled,
2000 reuse one which is not enabled */
2001 } else if (Index == This->maxConcurrentLights) {
2002 /* use bsf - Simply swap the new light and the BSF one */
2003 PLIGHTINFOEL *bsfNext = bsf->next;
2004 PLIGHTINFOEL *bsfPrev = bsf->prev;
2006 /* Sort out ends */
2007 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2008 if (bsf->prev != NULL) {
2009 bsf->prev->next = lightInfo;
2010 } else {
2011 This->StateBlock->lights = lightInfo;
2014 /* If not side by side, lots of chains to update */
2015 if (bsf->next != lightInfo) {
2016 lightInfo->prev->next = bsf;
2017 bsf->next->prev = lightInfo;
2018 bsf->next = lightInfo->next;
2019 bsf->prev = lightInfo->prev;
2020 lightInfo->next = bsfNext;
2021 lightInfo->prev = bsfPrev;
2023 } else {
2024 /* Simple swaps */
2025 bsf->prev = lightInfo;
2026 bsf->next = lightInfo->next;
2027 lightInfo->next = bsf;
2028 lightInfo->prev = bsfPrev;
2032 /* Update states */
2033 glIndex = bsf->glIndex;
2034 bsf->glIndex = -1;
2035 lightInfo->glIndex = glIndex;
2036 lightInfo->lightEnabled = TRUE;
2038 /* Finally set up the light in gl itself */
2039 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2040 ENTER_GL();
2041 setup_light(iface, glIndex, lightInfo);
2042 glEnable(GL_LIGHT0 + glIndex);
2043 checkGLcall("glEnable GL_LIGHT0 new setup");
2044 LEAVE_GL();
2046 /* If we reached the end of the allocated lights, with space in the
2047 gl lights, setup a new light */
2048 } else if (pos->glIndex == -1) {
2050 /* We reached the end of the allocated gl lights, so already
2051 know the index of the next one! */
2052 glIndex = Index;
2053 lightInfo->glIndex = glIndex;
2054 lightInfo->lightEnabled = TRUE;
2056 /* In an ideal world, its already in the right place */
2057 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2058 /* No need to move it */
2059 } else {
2060 /* Remove this light from the list */
2061 lightInfo->prev->next = lightInfo->next;
2062 if (lightInfo->next != NULL) {
2063 lightInfo->next->prev = lightInfo->prev;
2066 /* Add in at appropriate place (inbetween prev and pos) */
2067 lightInfo->prev = prev;
2068 lightInfo->next = pos;
2069 if (prev == NULL) {
2070 This->StateBlock->lights = lightInfo;
2071 } else {
2072 prev->next = lightInfo;
2074 if (pos != NULL) {
2075 pos->prev = lightInfo;
2079 /* Finally set up the light in gl itself */
2080 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2081 ENTER_GL();
2082 setup_light(iface, glIndex, lightInfo);
2083 glEnable(GL_LIGHT0 + glIndex);
2084 checkGLcall("glEnable GL_LIGHT0 new setup");
2085 LEAVE_GL();
2090 return D3D_OK;
2092 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2094 PLIGHTINFOEL *lightInfo = NULL;
2095 ICOM_THIS(IDirect3DDevice8Impl,iface);
2096 TRACE("(%p) : for idx(%ld)\n", This, Index);
2098 /* Locate the light in the live lights */
2099 lightInfo = This->StateBlock->lights;
2100 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2102 if (lightInfo == NULL) {
2103 TRACE("Light enabled state requested but light not defined\n");
2104 return D3DERR_INVALIDCALL;
2106 *pEnable = lightInfo->lightEnabled;
2107 return D3D_OK;
2109 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2110 ICOM_THIS(IDirect3DDevice8Impl,iface);
2111 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2113 /* Validate Index */
2114 if (Index >= GL_LIMITS(clipplanes)) {
2115 TRACE("Application has requested clipplane this device doesnt support\n");
2116 return D3DERR_INVALIDCALL;
2119 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2120 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2121 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2122 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2123 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2124 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2126 /* Handle recording of state blocks */
2127 if (This->isRecordingState) {
2128 TRACE("Recording... not performing anything\n");
2129 return D3D_OK;
2132 /* Apply it */
2134 ENTER_GL();
2136 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2137 glMatrixMode(GL_MODELVIEW);
2138 glPushMatrix();
2139 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2141 TRACE("Clipplane [%f,%f,%f,%f]\n",
2142 This->UpdateStateBlock->clipplane[Index][0],
2143 This->UpdateStateBlock->clipplane[Index][1],
2144 This->UpdateStateBlock->clipplane[Index][2],
2145 This->UpdateStateBlock->clipplane[Index][3]);
2146 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2147 checkGLcall("glClipPlane");
2149 glPopMatrix();
2151 LEAVE_GL();
2153 return D3D_OK;
2155 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2156 ICOM_THIS(IDirect3DDevice8Impl,iface);
2157 TRACE("(%p) : for idx %ld\n", This, Index);
2159 /* Validate Index */
2160 if (Index >= GL_LIMITS(clipplanes)) {
2161 TRACE("Application has requested clipplane this device doesnt support\n");
2162 return D3DERR_INVALIDCALL;
2165 pPlane[0] = This->StateBlock->clipplane[Index][0];
2166 pPlane[1] = This->StateBlock->clipplane[Index][1];
2167 pPlane[2] = This->StateBlock->clipplane[Index][2];
2168 pPlane[3] = This->StateBlock->clipplane[Index][3];
2169 return D3D_OK;
2171 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2172 ICOM_THIS(IDirect3DDevice8Impl,iface);
2173 DWORD OldValue = This->StateBlock->renderstate[State];
2175 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2176 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2177 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2178 This->UpdateStateBlock->renderstate[State] = Value;
2180 /* Handle recording of state blocks */
2181 if (This->isRecordingState) {
2182 TRACE("Recording... not performing anything\n");
2183 return D3D_OK;
2186 ENTER_GL();
2188 switch (State) {
2189 case D3DRS_FILLMODE :
2190 switch ((D3DFILLMODE) Value) {
2191 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2192 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2193 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2194 default:
2195 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2197 checkGLcall("glPolygonMode (fillmode)");
2198 break;
2200 case D3DRS_LIGHTING :
2201 if (Value) {
2202 glEnable(GL_LIGHTING);
2203 checkGLcall("glEnable GL_LIGHTING");
2204 } else {
2205 glDisable(GL_LIGHTING);
2206 checkGLcall("glDisable GL_LIGHTING");
2208 break;
2210 case D3DRS_ZENABLE :
2211 switch ((D3DZBUFFERTYPE) Value) {
2212 case D3DZB_FALSE:
2213 glDisable(GL_DEPTH_TEST);
2214 checkGLcall("glDisable GL_DEPTH_TEST");
2215 break;
2216 case D3DZB_TRUE:
2217 glEnable(GL_DEPTH_TEST);
2218 checkGLcall("glEnable GL_DEPTH_TEST");
2219 break;
2221 case D3DZB_USEW:
2222 default:
2223 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2225 break;
2227 case D3DRS_CULLMODE :
2229 /* If we are culling "back faces with clockwise vertices" then
2230 set front faces to be counter clockwise and enable culling
2231 of back faces */
2232 switch ((D3DCULL) Value) {
2233 case D3DCULL_NONE:
2234 glDisable(GL_CULL_FACE);
2235 checkGLcall("glDisable GL_CULL_FACE");
2236 break;
2237 case D3DCULL_CW:
2238 glEnable(GL_CULL_FACE);
2239 checkGLcall("glEnable GL_CULL_FACE");
2240 glFrontFace(GL_CCW);
2241 checkGLcall("glFrontFace GL_CCW");
2242 glCullFace(GL_BACK);
2243 break;
2244 case D3DCULL_CCW:
2245 glEnable(GL_CULL_FACE);
2246 checkGLcall("glEnable GL_CULL_FACE");
2247 glFrontFace(GL_CW);
2248 checkGLcall("glFrontFace GL_CW");
2249 glCullFace(GL_BACK);
2250 break;
2251 default:
2252 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2254 break;
2256 case D3DRS_SHADEMODE :
2257 switch ((D3DSHADEMODE) Value) {
2258 case D3DSHADE_FLAT:
2259 glShadeModel(GL_FLAT);
2260 checkGLcall("glShadeModel");
2261 break;
2262 case D3DSHADE_GOURAUD:
2263 glShadeModel(GL_SMOOTH);
2264 checkGLcall("glShadeModel");
2265 break;
2266 case D3DSHADE_PHONG:
2267 FIXME("D3DSHADE_PHONG isnt supported?\n");
2269 LEAVE_GL();
2270 return D3DERR_INVALIDCALL;
2271 default:
2272 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2274 break;
2276 case D3DRS_DITHERENABLE :
2277 if (Value) {
2278 glEnable(GL_DITHER);
2279 checkGLcall("glEnable GL_DITHER");
2280 } else {
2281 glDisable(GL_DITHER);
2282 checkGLcall("glDisable GL_DITHER");
2284 break;
2286 case D3DRS_ZWRITEENABLE :
2287 if (Value) {
2288 glDepthMask(1);
2289 checkGLcall("glDepthMask");
2290 } else {
2291 glDepthMask(0);
2292 checkGLcall("glDepthMask");
2294 break;
2296 case D3DRS_ZFUNC :
2298 int glParm = GL_LESS;
2300 switch ((D3DCMPFUNC) Value) {
2301 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2302 case D3DCMP_LESS: glParm=GL_LESS; break;
2303 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2304 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2305 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2306 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2307 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2308 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2309 default:
2310 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2312 glDepthFunc(glParm);
2313 checkGLcall("glDepthFunc");
2315 break;
2317 case D3DRS_AMBIENT :
2319 float col[4];
2320 D3DCOLORTOGLFLOAT4(Value, col);
2321 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2322 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2323 checkGLcall("glLightModel for MODEL_AMBIENT");
2326 break;
2328 case D3DRS_ALPHABLENDENABLE :
2329 if (Value) {
2330 glEnable(GL_BLEND);
2331 checkGLcall("glEnable GL_BLEND");
2332 } else {
2333 glDisable(GL_BLEND);
2334 checkGLcall("glDisable GL_BLEND");
2336 break;
2338 case D3DRS_SRCBLEND :
2339 case D3DRS_DESTBLEND :
2341 int newVal = GL_ZERO;
2342 switch (Value) {
2343 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2344 case D3DBLEND_ONE : newVal = GL_ONE; break;
2345 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2346 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2347 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2348 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2349 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2350 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2351 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2352 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2353 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2355 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2356 This->srcBlend = newVal;
2357 This->dstBlend = newVal;
2358 break;
2360 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2361 This->srcBlend = newVal;
2362 This->dstBlend = newVal;
2363 break;
2364 default:
2365 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2368 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2369 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2370 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2371 glBlendFunc(This->srcBlend, This->dstBlend);
2373 checkGLcall("glBlendFunc");
2375 break;
2377 case D3DRS_ALPHATESTENABLE :
2378 if (Value) {
2379 glEnable(GL_ALPHA_TEST);
2380 checkGLcall("glEnable GL_ALPHA_TEST");
2381 } else {
2382 glDisable(GL_ALPHA_TEST);
2383 checkGLcall("glDisable GL_ALPHA_TEST");
2385 break;
2387 case D3DRS_ALPHAFUNC :
2389 int glParm = GL_LESS;
2390 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2392 switch ((D3DCMPFUNC) Value) {
2393 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2394 case D3DCMP_LESS: glParm = GL_LESS; break;
2395 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2396 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2397 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2398 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2399 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2400 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2401 default:
2402 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2404 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2405 glAlphaFunc(glParm, ref);
2406 This->alphafunc = glParm;
2407 checkGLcall("glAlphaFunc");
2409 break;
2411 case D3DRS_ALPHAREF :
2413 int glParm = This->alphafunc;
2414 float ref = 1.0f;
2416 ref = ((float) Value) / 255.0f;
2417 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2418 glAlphaFunc(glParm, ref);
2419 checkGLcall("glAlphaFunc");
2421 break;
2423 case D3DRS_CLIPPLANEENABLE :
2424 case D3DRS_CLIPPING :
2426 /* Ensure we only do the changed clip planes */
2427 DWORD enable = 0xFFFFFFFF;
2428 DWORD disable = 0x00000000;
2430 /* If enabling / disabling all */
2431 if (State == D3DRS_CLIPPING) {
2432 if (Value) {
2433 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2434 disable = 0x00;
2435 } else {
2436 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2437 enable = 0x00;
2439 } else {
2440 enable = Value & ~OldValue;
2441 disable = ~Value & OldValue;
2444 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2445 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2446 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2447 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2448 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2449 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2451 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2452 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2453 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2454 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2455 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2456 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2458 break;
2460 case D3DRS_BLENDOP :
2462 int glParm = GL_FUNC_ADD;
2464 switch ((D3DBLENDOP) Value) {
2465 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2466 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2467 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2468 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2469 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2470 default:
2471 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2473 TRACE("glBlendEquation(%x)\n", glParm);
2474 glBlendEquation(glParm);
2475 checkGLcall("glBlendEquation");
2477 break;
2479 case D3DRS_TEXTUREFACTOR :
2481 int i;
2483 /* Note the texture color applies to all textures whereas
2484 GL_TEXTURE_ENV_COLOR applies to active only */
2485 float col[4];
2486 D3DCOLORTOGLFLOAT4(Value, col);
2487 /* Set the default alpha blend color */
2488 glBlendColor(col[0], col[1], col[2], col[3]);
2489 checkGLcall("glBlendColor");
2491 /* And now the default texture color as well */
2492 for (i = 0; i < GL_LIMITS(textures); i++) {
2494 /* Note the D3DRS value applies to all textures, but GL has one
2495 per texture, so apply it now ready to be used! */
2496 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2497 #if defined(GL_VERSION_1_3)
2498 glActiveTexture(GL_TEXTURE0 + i);
2499 #else
2500 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2501 #endif
2502 checkGLcall("Activate texture.. to update const color");
2503 } else if (i>0) {
2504 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2507 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2508 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2511 break;
2513 case D3DRS_SPECULARENABLE :
2515 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2516 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2517 specular color. This is wrong:
2518 Separate specular color means the specular colour is maintained separately, whereas
2519 single color means it is merged in. However in both cases they are being used to
2520 some extent.
2521 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2522 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2523 yet running 1.4!
2525 if (Value) {
2526 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2527 checkGLcall("glMaterialfv");
2528 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2529 glEnable(GL_COLOR_SUM_EXT);
2530 } else {
2531 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2533 checkGLcall("glEnable(GL_COLOR_SUM)");
2534 } else {
2535 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2537 /* for the case of enabled lighting: */
2538 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2539 checkGLcall("glMaterialfv");
2541 /* for the case of disabled lighting: */
2542 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2543 glDisable(GL_COLOR_SUM_EXT);
2544 } else {
2545 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2547 checkGLcall("glDisable(GL_COLOR_SUM)");
2550 break;
2552 case D3DRS_STENCILENABLE :
2553 if (Value) {
2554 glEnable(GL_STENCIL_TEST);
2555 checkGLcall("glEnable GL_STENCIL_TEST");
2556 } else {
2557 glDisable(GL_STENCIL_TEST);
2558 checkGLcall("glDisable GL_STENCIL_TEST");
2560 break;
2562 case D3DRS_STENCILFUNC :
2564 int glParm = GL_ALWAYS;
2565 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2566 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2568 switch ((D3DCMPFUNC) Value) {
2569 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2570 case D3DCMP_LESS: glParm=GL_LESS; break;
2571 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2572 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2573 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2574 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2575 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2576 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2577 default:
2578 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2580 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2581 This->stencilfunc = glParm;
2582 glStencilFunc(glParm, ref, mask);
2583 checkGLcall("glStencilFunc");
2585 break;
2587 case D3DRS_STENCILREF :
2589 int glParm = This->stencilfunc;
2590 int ref = 0;
2591 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2593 ref = Value;
2594 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2595 glStencilFunc(glParm, ref, mask);
2596 checkGLcall("glStencilFunc");
2598 break;
2600 case D3DRS_STENCILMASK :
2602 int glParm = This->stencilfunc;
2603 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2604 GLuint mask = Value;
2606 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2607 glStencilFunc(glParm, ref, mask);
2608 checkGLcall("glStencilFunc");
2610 break;
2612 case D3DRS_STENCILFAIL :
2614 GLenum fail ;
2615 GLenum zpass ;
2616 GLenum zfail ;
2618 fail = StencilOp(Value);
2619 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2620 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2621 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2622 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2624 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2625 glStencilOp(fail, zfail, zpass);
2626 checkGLcall("glStencilOp(fail, zfail, zpass);");
2628 break;
2629 case D3DRS_STENCILZFAIL :
2631 GLenum fail ;
2632 GLenum zpass ;
2633 GLenum zfail ;
2635 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2636 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2637 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2638 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2639 zfail = StencilOp(Value);
2641 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2642 glStencilOp(fail, zfail, zpass);
2643 checkGLcall("glStencilOp(fail, zfail, zpass);");
2645 break;
2646 case D3DRS_STENCILPASS :
2648 GLenum fail ;
2649 GLenum zpass ;
2650 GLenum zfail ;
2652 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2653 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2654 zpass = StencilOp(Value);
2655 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2656 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2658 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2659 glStencilOp(fail, zfail, zpass);
2660 checkGLcall("glStencilOp(fail, zfail, zpass);");
2662 break;
2664 case D3DRS_STENCILWRITEMASK :
2666 glStencilMask(Value);
2667 TRACE("glStencilMask(%lu)\n", Value);
2668 checkGLcall("glStencilMask");
2670 break;
2672 case D3DRS_FOGENABLE :
2674 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2675 glEnable(GL_FOG);
2676 checkGLcall("glEnable GL_FOG");
2677 } else {
2678 glDisable(GL_FOG);
2679 checkGLcall("glDisable GL_FOG");
2682 break;
2684 case D3DRS_FOGCOLOR :
2686 float col[4];
2687 D3DCOLORTOGLFLOAT4(Value, col);
2688 /* Set the default alpha blend color */
2689 glFogfv(GL_FOG_COLOR, &col[0]);
2690 checkGLcall("glFog GL_FOG_COLOR");
2692 break;
2694 case D3DRS_FOGTABLEMODE :
2696 switch (Value) {
2697 case D3DFOG_NONE: /* I don't know what to do here */ break;
2698 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2699 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2700 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2701 default:
2702 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2705 break;
2707 case D3DRS_FOGSTART :
2709 float *f = (float*) &Value;
2710 glFogfv(GL_FOG_START, f);
2711 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2712 TRACE("Fog Start == %f\n", *f);
2714 break;
2716 case D3DRS_FOGEND :
2718 float *f = (float*) &Value;
2719 glFogfv(GL_FOG_END, f);
2720 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2721 TRACE("Fog End == %f\n", *f);
2723 break;
2725 case D3DRS_FOGDENSITY :
2727 float *f = (float*) &Value;
2728 glFogfv(GL_FOG_DENSITY, f);
2729 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2731 break;
2733 case D3DRS_VERTEXBLEND :
2735 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2736 TRACE("Vertex Blending state to %ld\n", Value);
2738 break;
2740 case D3DRS_TWEENFACTOR :
2742 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2743 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2745 break;
2747 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2749 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2751 break;
2753 case D3DRS_COLORVERTEX :
2754 case D3DRS_DIFFUSEMATERIALSOURCE :
2755 case D3DRS_SPECULARMATERIALSOURCE :
2756 case D3DRS_AMBIENTMATERIALSOURCE :
2757 case D3DRS_EMISSIVEMATERIALSOURCE :
2759 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2761 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2762 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2763 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2764 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2765 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2766 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2768 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2769 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2770 Parm = GL_AMBIENT_AND_DIFFUSE;
2771 } else {
2772 Parm = GL_DIFFUSE;
2774 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2775 Parm = GL_AMBIENT;
2776 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2777 Parm = GL_EMISSION;
2778 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2779 Parm = GL_SPECULAR;
2780 } else {
2781 Parm = -1;
2784 if (Parm == -1) {
2785 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2786 } else {
2787 This->tracking_color = NEEDS_TRACKING;
2788 This->tracking_parm = Parm;
2791 } else {
2792 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2795 break;
2797 case D3DRS_LINEPATTERN :
2799 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2800 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2802 if (pattern->wRepeatFactor) {
2803 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2804 checkGLcall("glLineStipple(repeat, linepattern)");
2805 glEnable(GL_LINE_STIPPLE);
2806 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2807 } else {
2808 glDisable(GL_LINE_STIPPLE);
2809 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2812 break;
2814 case D3DRS_ZBIAS :
2816 if (Value) {
2817 TRACE("ZBias value %f\n", *((float*)&Value));
2818 glPolygonOffset(0, -*((float*)&Value));
2819 checkGLcall("glPolygonOffset(0, -Value)");
2820 glEnable(GL_POLYGON_OFFSET_FILL);
2821 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2822 glEnable(GL_POLYGON_OFFSET_LINE);
2823 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2824 glEnable(GL_POLYGON_OFFSET_POINT);
2825 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2826 } else {
2827 glDisable(GL_POLYGON_OFFSET_FILL);
2828 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2829 glDisable(GL_POLYGON_OFFSET_LINE);
2830 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2831 glDisable(GL_POLYGON_OFFSET_POINT);
2832 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2835 break;
2837 case D3DRS_NORMALIZENORMALS :
2838 if (Value) {
2839 glEnable(GL_NORMALIZE);
2840 checkGLcall("glEnable(GL_NORMALIZE);");
2841 } else {
2842 glDisable(GL_NORMALIZE);
2843 checkGLcall("glDisable(GL_NORMALIZE);");
2845 break;
2847 case D3DRS_POINTSIZE :
2848 TRACE("Set point size to %f\n", *((float*)&Value));
2849 glPointSize(*((float*)&Value));
2850 checkGLcall("glPointSize(...);");
2851 break;
2853 case D3DRS_POINTSIZE_MIN :
2854 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2855 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2856 checkGLcall("glPointParameterfEXT(...);");
2857 } else {
2858 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2860 break;
2862 case D3DRS_POINTSIZE_MAX :
2863 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2864 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2865 checkGLcall("glPointParameterfEXT(...);");
2866 } else {
2867 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2869 break;
2871 case D3DRS_POINTSCALE_A :
2872 case D3DRS_POINTSCALE_B :
2873 case D3DRS_POINTSCALE_C :
2874 case D3DRS_POINTSCALEENABLE :
2876 /* If enabled, supply the parameters, otherwise fall back to defaults */
2877 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2878 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2879 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2880 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2881 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2883 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2884 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2885 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2886 } else {
2887 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2889 } else {
2890 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2891 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2892 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2893 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2894 } else {
2895 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2898 break;
2901 case D3DRS_COLORWRITEENABLE :
2902 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2903 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2904 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2905 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2906 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2907 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2908 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2909 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2910 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2911 checkGLcall("glColorMask(...)");
2912 break;
2914 /* Unhandled yet...! */
2915 case D3DRS_LASTPIXEL :
2916 case D3DRS_ZVISIBLE :
2917 case D3DRS_EDGEANTIALIAS :
2918 case D3DRS_RANGEFOGENABLE :
2919 case D3DRS_WRAP0 :
2920 case D3DRS_WRAP1 :
2921 case D3DRS_WRAP2 :
2922 case D3DRS_WRAP3 :
2923 case D3DRS_WRAP4 :
2924 case D3DRS_WRAP5 :
2925 case D3DRS_WRAP6 :
2926 case D3DRS_WRAP7 :
2927 case D3DRS_FOGVERTEXMODE :
2928 case D3DRS_LOCALVIEWER :
2929 case D3DRS_SOFTWAREVERTEXPROCESSING :
2930 case D3DRS_POINTSPRITEENABLE :
2931 case D3DRS_MULTISAMPLEANTIALIAS :
2932 case D3DRS_MULTISAMPLEMASK :
2933 case D3DRS_PATCHEDGESTYLE :
2934 case D3DRS_PATCHSEGMENTS :
2935 case D3DRS_DEBUGMONITORTOKEN :
2936 case D3DRS_POSITIONORDER :
2937 case D3DRS_NORMALORDER :
2938 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2939 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2940 break;
2941 default:
2942 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2945 LEAVE_GL();
2947 return D3D_OK;
2949 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2950 ICOM_THIS(IDirect3DDevice8Impl,iface);
2951 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2952 *pValue = This->StateBlock->renderstate[State];
2953 return D3D_OK;
2955 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2956 ICOM_THIS(IDirect3DDevice8Impl,iface);
2958 TRACE("(%p)\n", This);
2960 return IDirect3DDeviceImpl_BeginStateBlock(This);
2962 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2963 IDirect3DStateBlockImpl* pSB;
2964 ICOM_THIS(IDirect3DDevice8Impl,iface);
2965 HRESULT res;
2967 TRACE("(%p)\n", This);
2969 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2970 *pToken = (DWORD) pSB;
2971 return res;
2974 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2975 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2976 ICOM_THIS(IDirect3DDevice8Impl,iface);
2978 TRACE("(%p)\n", This);
2980 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2983 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2984 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2985 ICOM_THIS(IDirect3DDevice8Impl,iface);
2987 TRACE("(%p)\n", This);
2989 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2991 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2992 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2993 ICOM_THIS(IDirect3DDevice8Impl,iface);
2995 TRACE("(%p)\n", This);
2997 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3000 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3001 IDirect3DStateBlockImpl* pSB;
3002 ICOM_THIS(IDirect3DDevice8Impl,iface);
3003 HRESULT res;
3005 TRACE("(%p) : for type %d\n", This, Type);
3007 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3008 *pToken = (DWORD) pSB;
3009 return res;
3012 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3013 ICOM_THIS(IDirect3DDevice8Impl,iface);
3014 FIXME("(%p) : stub\n", This); return D3D_OK;
3016 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3017 ICOM_THIS(IDirect3DDevice8Impl,iface);
3018 FIXME("(%p) : stub\n", This); return D3D_OK;
3020 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3021 ICOM_THIS(IDirect3DDevice8Impl,iface);
3022 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3023 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3024 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3025 return D3D_OK;
3027 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3029 IDirect3DBaseTexture8 *oldTxt;
3030 BOOL reapplyStates = TRUE;
3031 DWORD oldTextureDimensions = -1;
3032 DWORD reapplyFlags = 0;
3034 ICOM_THIS(IDirect3DDevice8Impl,iface);
3035 D3DRESOURCETYPE textureType;
3037 oldTxt = This->UpdateStateBlock->textures[Stage];
3038 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3040 /* Reject invalid texture units */
3041 if (Stage >= GL_LIMITS(textures)) {
3042 TRACE("Attempt to access invalid texture rejected\n");
3043 return D3DERR_INVALIDCALL;
3046 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3047 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3048 This->UpdateStateBlock->textures[Stage] = pTexture;
3050 /* Handle recording of state blocks */
3051 if (This->isRecordingState) {
3052 TRACE("Recording... not performing anything\n");
3053 return D3D_OK;
3056 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3057 ENTER_GL();
3059 /* Make appropriate texture active */
3060 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3061 #if defined(GL_VERSION_1_3)
3062 glActiveTexture(GL_TEXTURE0 + Stage);
3063 #else
3064 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3065 #endif
3066 checkGLcall("glActiveTextureARB");
3067 } else if (Stage>0) {
3068 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3071 /* Decrement the count of the previous texture */
3072 if (NULL != oldTxt) {
3073 IDirect3DBaseTexture8Impl_Release(oldTxt);
3076 if (NULL != pTexture) {
3077 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3079 /* Now setup the texture appropraitly */
3080 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3082 if (textureType == D3DRTYPE_TEXTURE) {
3083 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3084 TRACE("Skipping setting texture as old == new\n");
3085 reapplyStates = FALSE;
3086 } else {
3087 /* Standard 2D texture */
3088 TRACE("Standard 2d texture\n");
3089 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3091 /* Load up the texture now */
3092 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3094 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3095 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3096 TRACE("Skipping setting texture as old == new\n");
3097 reapplyStates = FALSE;
3098 } else {
3099 /* Standard 3D (volume) texture */
3100 TRACE("Standard 3d texture\n");
3101 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3103 /* Load up the texture now */
3104 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3106 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3107 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3108 TRACE("Skipping setting texture as old == new\n");
3109 reapplyStates = FALSE;
3110 } else {
3111 /* Standard Cube texture */
3112 TRACE("Standard Cube texture\n");
3113 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3115 /* Load up the texture now */
3116 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3118 } else {
3119 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3121 } else {
3122 TRACE("Setting to no texture (ie default texture)\n");
3123 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3124 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3125 checkGLcall("glBindTexture");
3126 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3129 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3130 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3131 glDisable(oldTextureDimensions);
3132 checkGLcall("Disable oldTextureDimensions");
3133 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3134 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3135 checkGLcall("glEnable new texture dimensions");
3138 /* If Alpha arg1 is texture then handle the special case when there changes between a
3139 texture and no texture - See comments in set_tex_op */
3140 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3141 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3143 reapplyFlags |= REAPPLY_ALPHAOP;
3148 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3149 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3150 if (reapplyStates) {
3151 setupTextureStates(iface, Stage, reapplyFlags);
3154 LEAVE_GL();
3156 return D3D_OK;
3159 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3160 ICOM_THIS(IDirect3DDevice8Impl,iface);
3161 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3162 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3163 return D3D_OK;
3166 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3167 ICOM_THIS(IDirect3DDevice8Impl,iface);
3169 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3171 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3173 /* Reject invalid texture units */
3174 if (Stage >= GL_LIMITS(textures)) {
3175 TRACE("Attempt to access invalid texture rejected\n");
3176 return D3DERR_INVALIDCALL;
3179 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3180 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3181 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3183 /* Handle recording of state blocks */
3184 if (This->isRecordingState) {
3185 TRACE("Recording... not performing anything\n");
3186 return D3D_OK;
3189 ENTER_GL();
3191 /* Make appropriate texture active */
3192 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3193 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3194 #if defined(GL_VERSION_1_3)
3195 glActiveTexture(GL_TEXTURE0 + Stage);
3196 vcheckGLcall("glActiveTexture");
3197 #else
3198 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3199 vcheckGLcall("glActiveTextureARB");
3200 #endif
3201 } else if (Stage > 0) {
3202 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3205 switch (Type) {
3207 case D3DTSS_MINFILTER :
3208 case D3DTSS_MIPFILTER :
3210 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3211 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3212 GLint realVal = GL_LINEAR;
3214 if (ValueMIN == D3DTEXF_POINT) {
3215 /* GL_NEAREST_* */
3216 if (ValueMIP == D3DTEXF_POINT) {
3217 realVal = GL_NEAREST_MIPMAP_NEAREST;
3218 } else if (ValueMIP == D3DTEXF_LINEAR) {
3219 realVal = GL_NEAREST_MIPMAP_LINEAR;
3220 } else if (ValueMIP == D3DTEXF_NONE) {
3221 realVal = GL_NEAREST;
3222 } else {
3223 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3224 realVal = GL_NEAREST_MIPMAP_LINEAR;
3226 } else if (ValueMIN == D3DTEXF_LINEAR) {
3227 /* GL_LINEAR_* */
3228 if (ValueMIP == D3DTEXF_POINT) {
3229 realVal = GL_LINEAR_MIPMAP_NEAREST;
3230 } else if (ValueMIP == D3DTEXF_LINEAR) {
3231 realVal = GL_LINEAR_MIPMAP_LINEAR;
3232 } else if (ValueMIP == D3DTEXF_NONE) {
3233 realVal = GL_LINEAR;
3234 } else {
3235 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3236 realVal = GL_LINEAR_MIPMAP_LINEAR;
3238 } else if (ValueMIN == D3DTEXF_NONE) {
3239 /* Doesnt really make sense - Windows just seems to disable
3240 mipmapping when this occurs */
3241 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3242 realVal = GL_LINEAR;
3244 } else {
3245 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3246 realVal = GL_LINEAR_MIPMAP_LINEAR;
3249 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3250 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3251 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3253 break;
3255 case D3DTSS_MAXANISOTROPY :
3257 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3258 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3259 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3262 break;
3264 case D3DTSS_MAGFILTER :
3265 if (Value == D3DTEXF_POINT) {
3266 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3267 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3268 } else if (Value == D3DTEXF_LINEAR) {
3269 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3270 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3271 } else {
3272 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3274 break;
3276 case D3DTSS_ALPHAOP :
3277 case D3DTSS_COLOROP :
3280 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3281 /* TODO: Disable by making this and all later levels disabled */
3282 glDisable(GL_TEXTURE_1D);
3283 checkGLcall("Disable GL_TEXTURE_1D");
3284 glDisable(GL_TEXTURE_2D);
3285 checkGLcall("Disable GL_TEXTURE_2D");
3286 glDisable(GL_TEXTURE_3D);
3287 checkGLcall("Disable GL_TEXTURE_3D");
3288 break; /* Dont bother setting the texture operations */
3289 } else {
3290 /* Enable only the appropriate texture dimension */
3291 if (Type == D3DTSS_COLOROP) {
3292 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3293 glEnable(GL_TEXTURE_1D);
3294 checkGLcall("Enable GL_TEXTURE_1D");
3295 } else {
3296 glDisable(GL_TEXTURE_1D);
3297 checkGLcall("Disable GL_TEXTURE_1D");
3299 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3300 glEnable(GL_TEXTURE_2D);
3301 checkGLcall("Enable GL_TEXTURE_2D");
3302 } else {
3303 glDisable(GL_TEXTURE_2D);
3304 checkGLcall("Disable GL_TEXTURE_2D");
3306 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3307 glEnable(GL_TEXTURE_3D);
3308 checkGLcall("Enable GL_TEXTURE_3D");
3309 } else {
3310 glDisable(GL_TEXTURE_3D);
3311 checkGLcall("Disable GL_TEXTURE_3D");
3313 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3314 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3315 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3316 } else {
3317 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3318 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3322 /* Drop through... (Except disable case) */
3323 case D3DTSS_COLORARG0 :
3324 case D3DTSS_COLORARG1 :
3325 case D3DTSS_COLORARG2 :
3326 case D3DTSS_ALPHAARG0 :
3327 case D3DTSS_ALPHAARG1 :
3328 case D3DTSS_ALPHAARG2 :
3330 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3331 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3332 if (isAlphaArg) {
3333 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3334 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3335 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3336 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3337 } else {
3338 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3339 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3340 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3341 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3344 break;
3347 case D3DTSS_ADDRESSU :
3348 case D3DTSS_ADDRESSV :
3349 case D3DTSS_ADDRESSW :
3351 GLint wrapParm = GL_REPEAT;
3352 switch (Value) {
3353 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3354 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3355 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3356 #if defined(GL_VERSION_1_4)
3357 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3358 #elif defined(GL_ARB_texture_mirrored_repeat)
3359 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3360 #else
3361 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3362 #endif
3363 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3364 default:
3365 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3366 wrapParm = GL_REPEAT;
3369 switch (Type) {
3370 case D3DTSS_ADDRESSU:
3371 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3372 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3373 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3374 break;
3375 case D3DTSS_ADDRESSV:
3376 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3377 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3378 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3379 break;
3380 case D3DTSS_ADDRESSW:
3381 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3382 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3383 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3384 break;
3385 default: /* nop */
3386 break; /** stupic compilator */
3389 break;
3391 case D3DTSS_BORDERCOLOR :
3393 float col[4];
3394 D3DCOLORTOGLFLOAT4(Value, col);
3395 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3396 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3397 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3399 break;
3401 case D3DTSS_TEXCOORDINDEX :
3403 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3405 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3406 one flag, you can still specify an index value, which the system uses to
3407 determine the texture wrapping mode.
3408 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3409 means use the vertex position (camera-space) as the input texture coordinates
3410 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3411 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3412 to the TEXCOORDINDEX value */
3414 /**
3415 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3417 switch (Value & 0xFFFF0000) {
3418 case D3DTSS_TCI_PASSTHRU:
3419 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3420 glDisable(GL_TEXTURE_GEN_S);
3421 glDisable(GL_TEXTURE_GEN_T);
3422 glDisable(GL_TEXTURE_GEN_R);
3423 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3424 break;
3426 case D3DTSS_TCI_CAMERASPACEPOSITION:
3427 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3428 as the input texture coordinates for this stage's texture transformation. This
3429 equates roughly to EYE_LINEAR */
3431 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3432 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3433 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3434 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3435 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3437 glMatrixMode(GL_MODELVIEW);
3438 glPushMatrix();
3439 glLoadIdentity();
3440 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3441 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3442 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3443 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3444 glPopMatrix();
3446 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3447 glEnable(GL_TEXTURE_GEN_S);
3448 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3449 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3450 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3451 glEnable(GL_TEXTURE_GEN_T);
3452 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3453 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3454 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3455 glEnable(GL_TEXTURE_GEN_R);
3456 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3457 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3458 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3460 break;
3462 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3463 case D3DTSS_TCI_CAMERASPACENORMAL:
3465 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3466 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3467 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3468 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3469 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3471 glMatrixMode(GL_MODELVIEW);
3472 glPushMatrix();
3473 glLoadIdentity();
3474 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3475 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3476 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3477 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3478 glPopMatrix();
3480 glEnable(GL_TEXTURE_GEN_S);
3481 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3482 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3483 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3484 glEnable(GL_TEXTURE_GEN_T);
3485 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3486 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3487 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3488 glEnable(GL_TEXTURE_GEN_R);
3489 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3490 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3491 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3493 break;
3494 #endif
3496 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3497 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3500 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3501 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3502 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3503 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3504 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3506 glMatrixMode(GL_MODELVIEW);
3507 glPushMatrix();
3508 glLoadIdentity();
3509 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3510 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3511 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3512 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3513 glPopMatrix();
3515 glEnable(GL_TEXTURE_GEN_S);
3516 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3517 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3518 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3519 glEnable(GL_TEXTURE_GEN_T);
3520 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3521 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3522 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3523 glEnable(GL_TEXTURE_GEN_R);
3524 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3525 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3526 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3528 break;
3529 #endif
3531 /* Unhandled types: */
3532 default:
3533 /* Todo: */
3534 /* ? disable GL_TEXTURE_GEN_n ? */
3535 glDisable(GL_TEXTURE_GEN_S);
3536 glDisable(GL_TEXTURE_GEN_T);
3537 glDisable(GL_TEXTURE_GEN_R);
3538 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3539 break;
3542 break;
3544 /* Unhandled */
3545 case D3DTSS_BUMPENVMAT00 :
3546 case D3DTSS_BUMPENVMAT01 :
3547 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3548 break;
3549 case D3DTSS_BUMPENVMAT10 :
3550 case D3DTSS_BUMPENVMAT11 :
3551 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3552 break;
3554 case D3DTSS_TEXTURETRANSFORMFLAGS :
3555 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3556 break;
3558 case D3DTSS_MIPMAPLODBIAS :
3559 case D3DTSS_MAXMIPLEVEL :
3560 case D3DTSS_BUMPENVLSCALE :
3561 case D3DTSS_BUMPENVLOFFSET :
3562 case D3DTSS_RESULTARG :
3563 default:
3564 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3565 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3568 LEAVE_GL();
3570 return D3D_OK;
3572 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3573 ICOM_THIS(IDirect3DDevice8Impl,iface);
3574 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3575 return D3D_OK;
3577 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3578 ICOM_THIS(IDirect3DDevice8Impl,iface);
3579 FIXME("(%p) : stub\n", This);
3580 return D3D_OK;
3582 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3583 ICOM_THIS(IDirect3DDevice8Impl,iface);
3584 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3585 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3586 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3587 return D3D_OK;
3589 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3590 ICOM_THIS(IDirect3DDevice8Impl,iface);
3591 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3592 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3593 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3594 return D3D_OK;
3596 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3597 ICOM_THIS(IDirect3DDevice8Impl,iface);
3598 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3599 This->currentPalette = PaletteNumber;
3601 #if defined(GL_EXT_paletted_texture)
3602 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3604 ENTER_GL();
3606 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3607 GL_RGBA, /* internal format */
3608 256, /* table size */
3609 GL_RGBA, /* table format */
3610 GL_UNSIGNED_BYTE, /* table type */
3611 This->palettes[PaletteNumber]);
3612 checkGLcall("glColorTableEXT");
3614 LEAVE_GL();
3616 } else {
3617 /* Delayed palette handling ... waiting for software emulation into preload code */
3619 #endif
3620 return D3D_OK;
3622 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3623 ICOM_THIS(IDirect3DDevice8Impl,iface);
3624 *PaletteNumber = This->currentPalette;
3625 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3626 return D3D_OK;
3628 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3630 ICOM_THIS(IDirect3DDevice8Impl,iface);
3631 This->StateBlock->streamIsUP = FALSE;
3633 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3634 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3636 return D3D_OK;
3638 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3639 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3640 UINT idxStride = 2;
3641 IDirect3DIndexBuffer8 *pIB;
3642 D3DINDEXBUFFER_DESC IdxBufDsc;
3644 ICOM_THIS(IDirect3DDevice8Impl,iface);
3645 pIB = This->StateBlock->pIndexData;
3646 This->StateBlock->streamIsUP = FALSE;
3648 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3649 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3650 minIndex, NumVertices, startIndex, primCount);
3652 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3653 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3654 idxStride = 2;
3655 } else {
3656 idxStride = 4;
3659 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3660 minIndex);
3662 return D3D_OK;
3664 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3665 ICOM_THIS(IDirect3DDevice8Impl,iface);
3667 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3668 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3670 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3672 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3673 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3674 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3675 This->StateBlock->streamIsUP = TRUE;
3676 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3677 This->StateBlock->stream_stride[0] = 0;
3678 This->StateBlock->stream_source[0] = NULL;
3680 /*stream zero settings set to null at end */
3681 return D3D_OK;
3683 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3684 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3685 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3686 UINT VertexStreamZeroStride) {
3687 int idxStride;
3688 ICOM_THIS(IDirect3DDevice8Impl,iface);
3689 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),
3690 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3692 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3693 if (IndexDataFormat == D3DFMT_INDEX16) {
3694 idxStride = 2;
3695 } else {
3696 idxStride = 4;
3699 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3700 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3701 This->StateBlock->streamIsUP = TRUE;
3702 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3703 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3705 /*stream zero settings set to null at end */
3706 This->StateBlock->stream_source[0] = NULL;
3707 This->StateBlock->stream_stride[0] = 0;
3708 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3710 return D3D_OK;
3712 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3713 ICOM_THIS(IDirect3DDevice8Impl,iface);
3714 FIXME("(%p) : stub\n", This); return D3D_OK;
3716 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3717 ICOM_THIS(IDirect3DDevice8Impl,iface);
3718 IDirect3DVertexShaderImpl* object;
3719 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3720 HRESULT res;
3721 UINT i;
3723 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3724 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3725 return D3DERR_INVALIDCALL;
3727 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3728 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3729 return D3DERR_OUTOFVIDEOMEMORY;
3732 /** Create the Vertex Shader */
3733 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3734 /** TODO: check FAILED(res) */
3736 /** Create and Bind the Vertex Shader Declaration */
3737 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3738 /** TODO: check FAILED(res) */
3740 VertexShaders[i] = object;
3741 VertexShaderDeclarations[i] = attached_decl;
3742 *pHandle = VS_HIGHESTFIXEDFXF + i;
3743 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3745 return D3D_OK;
3747 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3748 ICOM_THIS(IDirect3DDevice8Impl,iface);
3750 This->UpdateStateBlock->VertexShader = Handle;
3751 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3752 This->UpdateStateBlock->Set.vertexShader = TRUE;
3754 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3755 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3756 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3757 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3758 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3759 } else { /* use a fvf, so desactivate the vshader decl */
3760 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3761 This->UpdateStateBlock->vertexShaderDecl = NULL;
3762 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3763 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3765 /* Handle recording of state blocks */
3766 if (This->isRecordingState) {
3767 TRACE("Recording... not performing anything\n");
3768 return D3D_OK;
3771 * TODO: merge HAL shaders context switching from prototype
3773 return D3D_OK;
3775 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3776 ICOM_THIS(IDirect3DDevice8Impl,iface);
3777 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3778 *pHandle = This->StateBlock->VertexShader;
3779 return D3D_OK;
3782 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3783 ICOM_THIS(IDirect3DDevice8Impl,iface);
3784 IDirect3DVertexShaderImpl* object;
3785 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3787 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3788 return D3DERR_INVALIDCALL;
3792 * Delete Vertex Shader
3794 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3795 if (NULL == object) {
3796 return D3DERR_INVALIDCALL;
3798 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3799 /* TODO: check validity of object */
3800 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3801 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3802 HeapFree(GetProcessHeap(), 0, (void *)object);
3803 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3806 * Delete Vertex Shader Declaration
3808 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3809 if (NULL == attached_decl) {
3810 return D3DERR_INVALIDCALL;
3812 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3813 /* TODO: check validity of object */
3814 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3815 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3816 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3818 return D3D_OK;
3821 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3822 ICOM_THIS(IDirect3DDevice8Impl,iface);
3824 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3825 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3826 return D3DERR_INVALIDCALL;
3828 if (NULL == pConstantData) {
3829 return D3DERR_INVALIDCALL;
3831 if (ConstantCount > 1) {
3832 FLOAT* f = (FLOAT*)pConstantData;
3833 UINT i;
3834 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3835 for (i = 0; i < ConstantCount; ++i) {
3836 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3837 f += 4;
3839 } else {
3840 FLOAT* f = (FLOAT*) pConstantData;
3841 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3843 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3844 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3845 return D3D_OK;
3847 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3848 ICOM_THIS(IDirect3DDevice8Impl,iface);
3850 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3851 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3852 return D3DERR_INVALIDCALL;
3854 if (NULL == pConstantData) {
3855 return D3DERR_INVALIDCALL;
3857 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3858 return D3D_OK;
3860 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3861 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3862 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3864 attached_decl = VERTEX_SHADER_DECL(Handle);
3865 if (NULL == attached_decl) {
3866 return D3DERR_INVALIDCALL;
3868 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3870 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3871 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3872 IDirect3DVertexShaderImpl* object;
3874 object = VERTEX_SHADER(Handle);
3875 if (NULL == object) {
3876 return D3DERR_INVALIDCALL;
3878 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3881 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3882 ICOM_THIS(IDirect3DDevice8Impl,iface);
3883 IDirect3DIndexBuffer8 *oldIdxs;
3885 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3886 oldIdxs = This->StateBlock->pIndexData;
3888 This->UpdateStateBlock->Changed.Indices = TRUE;
3889 This->UpdateStateBlock->Set.Indices = TRUE;
3890 This->UpdateStateBlock->pIndexData = pIndexData;
3891 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3893 /* Handle recording of state blocks */
3894 if (This->isRecordingState) {
3895 TRACE("Recording... not performing anything\n");
3896 return D3D_OK;
3899 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3900 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3901 return D3D_OK;
3903 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3904 ICOM_THIS(IDirect3DDevice8Impl,iface);
3905 FIXME("(%p) : stub\n", This);
3907 *ppIndexData = This->StateBlock->pIndexData;
3908 /* up ref count on ppindexdata */
3909 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3910 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3912 return D3D_OK;
3914 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3915 ICOM_THIS(IDirect3DDevice8Impl,iface);
3916 IDirect3DPixelShaderImpl* object;
3917 HRESULT res;
3918 UINT i;
3920 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3921 if (NULL == pFunction || NULL == pHandle) {
3922 return D3DERR_INVALIDCALL;
3924 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3925 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3926 return D3DERR_OUTOFVIDEOMEMORY;
3929 /** Create the Pixel Shader */
3930 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3931 if (SUCCEEDED(res)) {
3932 PixelShaders[i] = object;
3933 *pHandle = VS_HIGHESTFIXEDFXF + i;
3934 return D3D_OK;
3936 *pHandle = 0xFFFFFFFF;
3937 return res;
3939 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3940 ICOM_THIS(IDirect3DDevice8Impl,iface);
3942 This->UpdateStateBlock->PixelShader = Handle;
3943 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3944 This->UpdateStateBlock->Set.pixelShader = TRUE;
3946 /* Handle recording of state blocks */
3947 if (This->isRecordingState) {
3948 TRACE_(d3d_shader)("Recording... not performing anything\n");
3949 return D3D_OK;
3952 /* FIXME: Quieten when not being used */
3953 if (Handle != 0) {
3954 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3955 } else {
3956 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3959 return D3D_OK;
3961 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3962 ICOM_THIS(IDirect3DDevice8Impl,iface);
3963 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3964 *pHandle = This->StateBlock->PixelShader;
3965 return D3D_OK;
3968 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3969 ICOM_THIS(IDirect3DDevice8Impl,iface);
3970 IDirect3DPixelShaderImpl* object;
3972 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3973 return D3DERR_INVALIDCALL;
3975 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3976 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3977 /* TODO: check validity of object before free */
3978 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3979 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3980 HeapFree(GetProcessHeap(), 0, (void *)object);
3981 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3983 return D3D_OK;
3986 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3987 ICOM_THIS(IDirect3DDevice8Impl,iface);
3989 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3990 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3991 return D3DERR_INVALIDCALL;
3993 if (NULL == pConstantData) {
3994 return D3DERR_INVALIDCALL;
3996 if (ConstantCount > 1) {
3997 FLOAT* f = (FLOAT*)pConstantData;
3998 UINT i;
3999 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4000 for (i = 0; i < ConstantCount; ++i) {
4001 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4002 f += 4;
4004 } else {
4005 FLOAT* f = (FLOAT*) pConstantData;
4006 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4008 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4009 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4010 return D3D_OK;
4012 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4013 ICOM_THIS(IDirect3DDevice8Impl,iface);
4015 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4016 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4017 return D3DERR_INVALIDCALL;
4019 if (NULL == pConstantData) {
4020 return D3DERR_INVALIDCALL;
4022 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4023 return D3D_OK;
4025 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4026 IDirect3DPixelShaderImpl* object;
4028 object = PIXEL_SHADER(Handle);
4029 if (NULL == object) {
4030 return D3DERR_INVALIDCALL;
4032 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4034 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4035 ICOM_THIS(IDirect3DDevice8Impl,iface);
4036 FIXME("(%p) : stub\n", This); return D3D_OK;
4038 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4039 ICOM_THIS(IDirect3DDevice8Impl,iface);
4040 FIXME("(%p) : stub\n", This); return D3D_OK;
4042 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4043 ICOM_THIS(IDirect3DDevice8Impl,iface);
4044 FIXME("(%p) : stub\n", This); return D3D_OK;
4047 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4048 IDirect3DVertexBuffer8 *oldSrc;
4049 ICOM_THIS(IDirect3DDevice8Impl,iface);
4051 oldSrc = This->StateBlock->stream_source[StreamNumber];
4052 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4054 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4055 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4056 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4057 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4059 /* Handle recording of state blocks */
4060 if (This->isRecordingState) {
4061 TRACE("Recording... not performing anything\n");
4062 return D3D_OK;
4065 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4066 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4067 return D3D_OK;
4069 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4070 ICOM_THIS(IDirect3DDevice8Impl,iface);
4071 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4072 *pStream = This->StateBlock->stream_source[StreamNumber];
4073 *pStride = This->StateBlock->stream_stride[StreamNumber];
4074 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4075 return D3D_OK;
4079 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4081 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4082 IDirect3DDevice8Impl_QueryInterface,
4083 IDirect3DDevice8Impl_AddRef,
4084 IDirect3DDevice8Impl_Release,
4085 IDirect3DDevice8Impl_TestCooperativeLevel,
4086 IDirect3DDevice8Impl_GetAvailableTextureMem,
4087 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4088 IDirect3DDevice8Impl_GetDirect3D,
4089 IDirect3DDevice8Impl_GetDeviceCaps,
4090 IDirect3DDevice8Impl_GetDisplayMode,
4091 IDirect3DDevice8Impl_GetCreationParameters,
4092 IDirect3DDevice8Impl_SetCursorProperties,
4093 IDirect3DDevice8Impl_SetCursorPosition,
4094 IDirect3DDevice8Impl_ShowCursor,
4095 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4096 IDirect3DDevice8Impl_Reset,
4097 IDirect3DDevice8Impl_Present,
4098 IDirect3DDevice8Impl_GetBackBuffer,
4099 IDirect3DDevice8Impl_GetRasterStatus,
4100 IDirect3DDevice8Impl_SetGammaRamp,
4101 IDirect3DDevice8Impl_GetGammaRamp,
4102 IDirect3DDevice8Impl_CreateTexture,
4103 IDirect3DDevice8Impl_CreateVolumeTexture,
4104 IDirect3DDevice8Impl_CreateCubeTexture,
4105 IDirect3DDevice8Impl_CreateVertexBuffer,
4106 IDirect3DDevice8Impl_CreateIndexBuffer,
4107 IDirect3DDevice8Impl_CreateRenderTarget,
4108 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4109 IDirect3DDevice8Impl_CreateImageSurface,
4110 IDirect3DDevice8Impl_CopyRects,
4111 IDirect3DDevice8Impl_UpdateTexture,
4112 IDirect3DDevice8Impl_GetFrontBuffer,
4113 IDirect3DDevice8Impl_SetRenderTarget,
4114 IDirect3DDevice8Impl_GetRenderTarget,
4115 IDirect3DDevice8Impl_GetDepthStencilSurface,
4116 IDirect3DDevice8Impl_BeginScene,
4117 IDirect3DDevice8Impl_EndScene,
4118 IDirect3DDevice8Impl_Clear,
4119 IDirect3DDevice8Impl_SetTransform,
4120 IDirect3DDevice8Impl_GetTransform,
4121 IDirect3DDevice8Impl_MultiplyTransform,
4122 IDirect3DDevice8Impl_SetViewport,
4123 IDirect3DDevice8Impl_GetViewport,
4124 IDirect3DDevice8Impl_SetMaterial,
4125 IDirect3DDevice8Impl_GetMaterial,
4126 IDirect3DDevice8Impl_SetLight,
4127 IDirect3DDevice8Impl_GetLight,
4128 IDirect3DDevice8Impl_LightEnable,
4129 IDirect3DDevice8Impl_GetLightEnable,
4130 IDirect3DDevice8Impl_SetClipPlane,
4131 IDirect3DDevice8Impl_GetClipPlane,
4132 IDirect3DDevice8Impl_SetRenderState,
4133 IDirect3DDevice8Impl_GetRenderState,
4134 IDirect3DDevice8Impl_BeginStateBlock,
4135 IDirect3DDevice8Impl_EndStateBlock,
4136 IDirect3DDevice8Impl_ApplyStateBlock,
4137 IDirect3DDevice8Impl_CaptureStateBlock,
4138 IDirect3DDevice8Impl_DeleteStateBlock,
4139 IDirect3DDevice8Impl_CreateStateBlock,
4140 IDirect3DDevice8Impl_SetClipStatus,
4141 IDirect3DDevice8Impl_GetClipStatus,
4142 IDirect3DDevice8Impl_GetTexture,
4143 IDirect3DDevice8Impl_SetTexture,
4144 IDirect3DDevice8Impl_GetTextureStageState,
4145 IDirect3DDevice8Impl_SetTextureStageState,
4146 IDirect3DDevice8Impl_ValidateDevice,
4147 IDirect3DDevice8Impl_GetInfo,
4148 IDirect3DDevice8Impl_SetPaletteEntries,
4149 IDirect3DDevice8Impl_GetPaletteEntries,
4150 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4151 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4152 IDirect3DDevice8Impl_DrawPrimitive,
4153 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4154 IDirect3DDevice8Impl_DrawPrimitiveUP,
4155 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4156 IDirect3DDevice8Impl_ProcessVertices,
4157 IDirect3DDevice8Impl_CreateVertexShader,
4158 IDirect3DDevice8Impl_SetVertexShader,
4159 IDirect3DDevice8Impl_GetVertexShader,
4160 IDirect3DDevice8Impl_DeleteVertexShader,
4161 IDirect3DDevice8Impl_SetVertexShaderConstant,
4162 IDirect3DDevice8Impl_GetVertexShaderConstant,
4163 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4164 IDirect3DDevice8Impl_GetVertexShaderFunction,
4165 IDirect3DDevice8Impl_SetStreamSource,
4166 IDirect3DDevice8Impl_GetStreamSource,
4167 IDirect3DDevice8Impl_SetIndices,
4168 IDirect3DDevice8Impl_GetIndices,
4169 IDirect3DDevice8Impl_CreatePixelShader,
4170 IDirect3DDevice8Impl_SetPixelShader,
4171 IDirect3DDevice8Impl_GetPixelShader,
4172 IDirect3DDevice8Impl_DeletePixelShader,
4173 IDirect3DDevice8Impl_SetPixelShaderConstant,
4174 IDirect3DDevice8Impl_GetPixelShaderConstant,
4175 IDirect3DDevice8Impl_GetPixelShaderFunction,
4176 IDirect3DDevice8Impl_DrawRectPatch,
4177 IDirect3DDevice8Impl_DrawTriPatch,
4178 IDirect3DDevice8Impl_DeletePatch
4181 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4183 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4184 ICOM_THIS(IDirect3DDevice8Impl,iface);
4186 ENTER_GL();
4188 #if 0
4189 if (This->glCtx != This->render_ctx) {
4190 glXDestroyContext(This->display, This->render_ctx);
4191 This->render_ctx = This->glCtx;
4193 #endif
4194 if (This->win != This->drawable) {
4195 glXDestroyPbuffer(This->display, This->drawable);
4196 This->drawable = This->win;
4199 LEAVE_GL();
4201 #endif
4202 return D3D_OK;
4205 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4206 IDirect3DSurface8* RenderSurface,
4207 IDirect3DSurface8* StencilSurface) {
4209 HRESULT ret = D3DERR_INVALIDCALL;
4211 * Currently only active for GLX >= 1.3
4212 * for others versions we'll have to use GLXPixmaps
4214 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4215 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4216 * so only check OpenGL version
4218 #if defined(GL_VERSION_1_3)
4219 GLXFBConfig* cfgs = NULL;
4220 int nCfgs = 0;
4221 int attribs[256];
4222 int nAttribs = 0;
4223 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4224 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4225 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4226 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4227 IDirect3DSurface8Impl* tmp;
4229 ICOM_THIS(IDirect3DDevice8Impl,iface);
4231 #define PUSH1(att) attribs[nAttribs++] = (att);
4232 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4234 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4235 PUSH2(GLX_X_RENDERABLE, TRUE);
4236 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4238 switch (BackBufferFormat) {
4239 /* color buffer */
4240 case D3DFMT_P8:
4241 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4242 PUSH2(GLX_BUFFER_SIZE, 8);
4243 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4244 break;
4246 case D3DFMT_R3G3B2:
4247 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4248 PUSH2(GLX_RED_SIZE, 3);
4249 PUSH2(GLX_GREEN_SIZE, 3);
4250 PUSH2(GLX_BLUE_SIZE, 2);
4251 break;
4253 case D3DFMT_A1R5G5B5:
4254 PUSH2(GLX_ALPHA_SIZE, 1);
4255 case D3DFMT_X1R5G5B5:
4256 PUSH2(GLX_RED_SIZE, 5);
4257 PUSH2(GLX_GREEN_SIZE, 5);
4258 PUSH2(GLX_BLUE_SIZE, 5);
4259 break;
4261 case D3DFMT_R5G6B5:
4262 PUSH2(GLX_RED_SIZE, 5);
4263 PUSH2(GLX_GREEN_SIZE, 6);
4264 PUSH2(GLX_BLUE_SIZE, 5);
4265 break;
4267 case D3DFMT_A4R4G4B4:
4268 PUSH2(GLX_ALPHA_SIZE, 4);
4269 case D3DFMT_X4R4G4B4:
4270 PUSH2(GLX_RED_SIZE, 4);
4271 PUSH2(GLX_GREEN_SIZE, 4);
4272 PUSH2(GLX_BLUE_SIZE, 4);
4273 break;
4275 case D3DFMT_A8R8G8B8:
4276 PUSH2(GLX_ALPHA_SIZE, 8);
4277 case D3DFMT_R8G8B8:
4278 case D3DFMT_X8R8G8B8:
4279 PUSH2(GLX_RED_SIZE, 8);
4280 PUSH2(GLX_GREEN_SIZE, 8);
4281 PUSH2(GLX_BLUE_SIZE, 8);
4282 break;
4284 default:
4285 break;
4288 switch (StencilBufferFormat) {
4289 case D3DFMT_D16_LOCKABLE:
4290 case D3DFMT_D16:
4291 PUSH2(GLX_DEPTH_SIZE, 16);
4292 break;
4294 case D3DFMT_D15S1:
4295 PUSH2(GLX_DEPTH_SIZE, 15);
4296 break;
4298 case D3DFMT_D24X8:
4299 PUSH2(GLX_DEPTH_SIZE, 24);
4300 break;
4302 case D3DFMT_D24X4S4:
4303 PUSH2(GLX_DEPTH_SIZE, 24);
4304 PUSH2(GLX_STENCIL_SIZE, 4);
4305 break;
4307 case D3DFMT_D24S8:
4308 PUSH2(GLX_DEPTH_SIZE, 24);
4309 PUSH2(GLX_STENCIL_SIZE, 8);
4310 break;
4312 case D3DFMT_D32:
4313 PUSH2(GLX_DEPTH_SIZE, 32);
4314 break;
4316 default:
4317 break;
4320 PUSH1(None);
4322 ENTER_GL();
4324 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4325 if (NULL != cfgs) {
4326 #if 0
4327 int i;
4328 for (i = 0; i < nCfgs; ++i) {
4329 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4331 #endif
4333 if (NULL != This->renderTarget) {
4334 GLenum prev_read;
4335 glFlush();
4336 vcheckGLcall("glFlush");
4338 #if 0
4339 /** very very usefull debug code */
4340 glXSwapBuffers(This->display, This->drawable);
4341 printf("Hit Enter to get next frame ...\n");
4342 getchar();
4343 #endif
4345 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4346 vcheckGLcall("glIntegerv");
4347 glReadBuffer(GL_BACK);
4348 vcheckGLcall("glReadBuffer");
4350 long j;
4351 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4353 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4354 pitch = pitch / 2;
4356 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4357 glReadPixels(0,
4358 This->renderTarget->myDesc.Height - j - 1,
4359 This->renderTarget->myDesc.Width,
4361 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4362 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4363 This->renderTarget->allocatedMemory + j * pitch);
4364 vcheckGLcall("glReadPixels");
4367 glReadBuffer(prev_read);
4368 vcheckGLcall("glReadBuffer");
4371 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4372 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4373 nAttribs = 0;
4374 PUSH2(GLX_PBUFFER_WIDTH, Width);
4375 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4376 PUSH1(None);
4377 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4379 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4380 if (NULL == This->render_ctx) {
4381 ERR("cannot create glxContext\n");
4384 glFlush();
4385 glXSwapBuffers(This->display, This->drawable);
4386 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4387 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4389 checkGLcall("glXMakeContextCurrent");
4392 tmp = This->renderTarget;
4393 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4394 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4395 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4397 tmp = This->stencilBufferTarget;
4398 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4399 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4400 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4402 ret = D3D_OK;
4404 } else {
4405 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4408 #undef PUSH1
4409 #undef PUSH2
4411 LEAVE_GL();
4413 #endif
4415 return ret;