wined3d: Prevent crash in setup_light.
[wine.git] / dlls / d3d8 / device.c
blob25afed762d7231ef6f1ed46e604bdf9a44adcf01
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2004 Christian Costa
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <math.h>
25 #include <stdarg.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "wingdi.h"
33 #include "wine/debug.h"
35 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
36 /*#define GL_GLEXT_PROTOTYPES*/
37 /*#undef GLX_GLXEXT_LEGACY*/
38 #include "d3d8_private.h"
40 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
41 #undef GL_VERSION_1_4
43 /* Uncomment the next line to get extra traces, important but impact speed */
44 /* #define EXTRA_TRACES */
46 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
47 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
48 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
50 IDirect3DVertexShaderImpl* VertexShaders[64];
51 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
52 IDirect3DPixelShaderImpl* PixelShaders[64];
54 /* Debugging aids: */
55 #ifdef FRAME_DEBUGGING
56 BOOL isOn = FALSE;
57 BOOL isDumpingFrames = FALSE;
58 LONG primCounter = 0;
59 #endif
62 * Utility functions or macros
64 #define conv_mat(mat,gl_mat) \
65 do { \
66 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
68 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
69 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
70 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
71 } while (0)
73 /* Apply the current values to the specified texture stage */
74 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
75 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
76 int i = 0;
77 float col[4];
78 BOOL changeTexture = TRUE;
80 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
81 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
83 BOOL skip = FALSE;
85 switch (i) {
86 /* Performance: For texture states where multiples effect the outcome, only bother
87 applying the last one as it will pick up all the other values */
88 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
89 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
90 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
91 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
92 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
93 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
94 skip = TRUE;
95 break;
97 /* Performance: If the texture states only impact settings for the texture unit
98 (compared to the texture object) then there is no need to reapply them. The
99 only time they need applying is the first time, since we cheat and put the
100 values into the stateblock without applying.
101 Per-texture unit: texture function (eg. combine), ops and args
102 texture env color
103 texture generation settings
104 Note: Due to some special conditions there may be a need to do particular ones
105 of these, which is what the Flags allows */
106 case D3DTSS_COLOROP:
107 case D3DTSS_TEXCOORDINDEX:
108 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
109 break;
111 case D3DTSS_ALPHAOP:
112 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
113 break;
115 default:
116 skip = FALSE;
119 if (skip == FALSE) {
120 /* Performance: Only change to this texture if we have to */
121 if (changeTexture) {
122 /* Make appropriate texture active */
123 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
124 #if defined(GL_VERSION_1_3)
125 glActiveTexture(GL_TEXTURE0 + Stage);
126 checkGLcall("glActiveTexture");
127 #else
128 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
129 checkGLcall("glActiveTextureARB");
130 #endif
131 } else if (Stage > 0) {
132 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
134 changeTexture = FALSE;
137 /* Now apply the change */
138 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
142 /* Note the D3DRS value applies to all textures, but GL has one
143 * per texture, so apply it now ready to be used!
145 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
146 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
147 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
149 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
152 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
153 static void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
155 float quad_att;
156 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
157 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
159 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
160 glMatrixMode(GL_MODELVIEW);
161 glPushMatrix();
162 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
164 /* Diffuse: */
165 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
166 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
167 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
168 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
169 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
170 checkGLcall("glLightfv");
172 /* Specular */
173 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
174 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
175 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
176 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
177 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
178 checkGLcall("glLightfv");
180 /* Ambient */
181 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
182 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
183 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
184 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
185 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
186 checkGLcall("glLightfv");
188 /* Attenuation - Are these right? guessing... */
189 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
190 checkGLcall("glLightf");
191 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
192 checkGLcall("glLightf");
194 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
195 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
196 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
197 checkGLcall("glLightf");
199 switch (lightInfo->OriginalParms.Type) {
200 case D3DLIGHT_POINT:
201 /* Position */
202 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
203 checkGLcall("glLightfv");
204 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
205 checkGLcall("glLightf");
206 /* FIXME: Range */
207 break;
209 case D3DLIGHT_SPOT:
210 /* Position */
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
213 /* Direction */
214 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
215 checkGLcall("glLightfv");
216 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
217 checkGLcall("glLightf");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
219 checkGLcall("glLightf");
220 /* FIXME: Range */
221 break;
223 case D3DLIGHT_DIRECTIONAL:
224 /* Direction */
225 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
226 checkGLcall("glLightfv");
227 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228 checkGLcall("glLightf");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
230 checkGLcall("glLightf");
231 break;
233 default:
234 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
237 /* Restore the modelview matrix */
238 glPopMatrix();
241 /* Setup this textures matrix */
242 static void set_texture_matrix(const float *smat, DWORD flags)
244 float mat[16];
246 glMatrixMode(GL_TEXTURE);
248 if (flags == D3DTTFF_DISABLE) {
249 glLoadIdentity();
250 checkGLcall("glLoadIdentity()");
251 return;
254 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
255 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
256 checkGLcall("glLoadIdentity()");
257 return;
260 memcpy(mat, smat, 16*sizeof(float));
262 switch (flags & ~D3DTTFF_PROJECTED) {
263 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
264 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
265 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
268 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
269 case D3DTTFF_COUNT2:
270 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
271 mat[1] = mat[5] = mat[9] = mat[13] = 0;
272 break;
273 case D3DTTFF_COUNT3:
274 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
275 mat[2] = mat[6] = mat[10] = mat[14] = 0;
276 break;
278 glLoadMatrixf(mat);
279 checkGLcall("glLoadMatrixf(mat)");
282 /* IDirect3D IUnknown parts follow: */
283 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
285 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
287 if (IsEqualGUID(riid, &IID_IUnknown)
288 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
289 IDirect3DDevice8Impl_AddRef(iface);
290 *ppobj = This;
291 return D3D_OK;
294 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
295 return E_NOINTERFACE;
298 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
299 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
300 ULONG ref = InterlockedIncrement(&This->ref);
302 TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
304 return ref;
307 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
308 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
309 ULONG ref = InterlockedDecrement(&This->ref);
311 TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
313 if (ref == 0) {
314 IDirect3DDevice8Impl_CleanRender(iface);
315 IDirect3D8_Release((LPDIRECT3D8) This->direct3d8);
316 IWineD3DDevice_Release(This->WineD3DDevice);
318 if (glXGetCurrentContext() == This->glCtx) {
319 glXMakeCurrent(This->display, None, NULL);
321 glXDestroyContext(This->display, This->glCtx);
323 HeapFree(GetProcessHeap(), 0, This);
325 return ref;
328 /* IDirect3DDevice Interface follow: */
329 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
330 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
331 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
332 return D3D_OK;
335 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
336 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
337 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
339 * pretend we have 32MB of any type of memory queried.
341 return (1024*1024*32);
344 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
345 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
346 FIXME("(%p) : stub\n", This);
347 return D3D_OK;
349 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
350 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
351 TRACE("(%p) : returning %p\n", This, This->direct3d8);
353 /* Inc ref count */
354 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
356 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
357 return D3D_OK;
359 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
360 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
361 FIXME("(%p) : stub, calling idirect3d for now\n", This);
362 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
363 return D3D_OK;
365 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
367 HDC hdc;
368 int bpp = 0;
370 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
371 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
372 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
373 pMode->RefreshRate = 85; /*FIXME: How to identify? */
375 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
376 bpp = GetDeviceCaps(hdc, BITSPIXEL);
377 DeleteDC(hdc);
379 switch (bpp) {
380 case 8: pMode->Format = D3DFMT_R8G8B8; break;
381 case 16: pMode->Format = D3DFMT_R5G6B5; break;
382 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
383 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
384 default:
385 FIXME("Unrecognized display mode format\n");
386 pMode->Format = D3DFMT_UNKNOWN;
389 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
390 pMode->Format, debug_d3dformat(pMode->Format));
391 return D3D_OK;
393 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
394 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
395 TRACE("(%p) copying to %p\n", This, pParameters);
396 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
397 return D3D_OK;
399 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
400 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
401 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
402 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
404 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
405 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
406 return D3DERR_INVALIDCALL;
408 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
409 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
410 return D3DERR_INVALIDCALL;
413 This->xHotSpot = XHotSpot;
414 This->yHotSpot = YHotSpot;
415 return D3D_OK;
417 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
418 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
419 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
420 This->xScreenSpace = XScreenSpace;
421 This->yScreenSpace = YScreenSpace;
422 return;
424 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
425 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
426 TRACE("(%p) : visible(%d)\n", This, bShow);
427 This->bCursorVisible = bShow;
428 return D3D_OK;
430 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
431 IDirect3DSwapChain8Impl* object;
432 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
433 FIXME("(%p) : stub\n", This);
435 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
436 if (NULL == object) {
437 return D3DERR_OUTOFVIDEOMEMORY;
439 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
440 object->ref = 1;
442 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
443 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
444 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
446 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
447 (pPresentationParameters->BackBufferHeight == 0))) {
448 RECT Rect;
450 GetClientRect(This->win_handle, &Rect);
452 if (pPresentationParameters->BackBufferWidth == 0) {
453 pPresentationParameters->BackBufferWidth = Rect.right;
454 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
456 if (pPresentationParameters->BackBufferHeight == 0) {
457 pPresentationParameters->BackBufferHeight = Rect.bottom;
458 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
462 /* Save the presentation parms now filled in correctly */
463 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
465 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
466 pPresentationParameters->BackBufferWidth,
467 pPresentationParameters->BackBufferHeight,
468 pPresentationParameters->BackBufferFormat,
469 pPresentationParameters->MultiSampleType,
470 TRUE,
471 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
473 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
474 pPresentationParameters->BackBufferWidth,
475 pPresentationParameters->BackBufferHeight,
476 pPresentationParameters->BackBufferFormat,
477 pPresentationParameters->MultiSampleType,
478 TRUE,
479 (LPDIRECT3DSURFACE8*) &object->backBuffer);
481 if (pPresentationParameters->EnableAutoDepthStencil) {
482 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
483 pPresentationParameters->BackBufferWidth,
484 pPresentationParameters->BackBufferHeight,
485 pPresentationParameters->AutoDepthStencilFormat,
486 D3DMULTISAMPLE_NONE,
487 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
488 } else {
489 object->depthStencilBuffer = NULL;
492 *pSwapChain = (IDirect3DSwapChain8*) object;
493 return D3D_OK;
495 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
496 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
497 FIXME("(%p) : stub\n", This);
498 return D3D_OK;
500 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
501 CONST RECT* pSourceRect, CONST RECT* pDestRect,
502 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
503 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
504 TRACE("(%p) : complete stub!\n", This);
506 ENTER_GL();
508 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
511 glXSwapBuffers(This->display, This->drawable);
512 /* Don't call checkGLcall, as glGetError is not applicable here */
513 TRACE("glXSwapBuffers called, Starting new frame\n");
515 /* FPS support */
516 if (TRACE_ON(d3d_fps))
518 static long prev_time, frames;
520 DWORD time = GetTickCount();
521 frames++;
522 /* every 1.5 seconds */
523 if (time - prev_time > 1500) {
524 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
525 prev_time = time;
526 frames = 0;
530 #if defined(FRAME_DEBUGGING)
532 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
533 if (!isOn) {
534 isOn = TRUE;
535 FIXME("Enabling D3D Trace\n");
536 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
537 #if defined(SHOW_FRAME_MAKEUP)
538 FIXME("Singe Frame snapshots Starting\n");
539 isDumpingFrames = TRUE;
540 glClear(GL_COLOR_BUFFER_BIT);
541 #endif
543 #if defined(SINGLE_FRAME_DEBUGGING)
544 } else {
545 #if defined(SHOW_FRAME_MAKEUP)
546 FIXME("Singe Frame snapshots Finishing\n");
547 isDumpingFrames = FALSE;
548 #endif
549 FIXME("Singe Frame trace complete\n");
550 DeleteFileA("C:\\D3DTRACE");
551 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
552 #endif
554 } else {
555 if (isOn) {
556 isOn = FALSE;
557 #if defined(SHOW_FRAME_MAKEUP)
558 FIXME("Singe Frame snapshots Finishing\n");
559 isDumpingFrames = FALSE;
560 #endif
561 FIXME("Disabling D3D Trace\n");
562 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
566 #endif
568 LEAVE_GL();
569 /* Although this is not strictly required, a simple demo showed this does occur
570 on (at least non-debug) d3d */
571 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
572 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
575 return D3D_OK;
577 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
578 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
579 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
580 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
582 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
583 FIXME("Only one backBuffer currently supported\n");
584 return D3DERR_INVALIDCALL;
587 /* Note inc ref on returned surface */
588 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
590 return D3D_OK;
592 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
593 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
594 FIXME("(%p) : stub\n", This);
595 return D3D_OK;
597 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
598 HDC hDC;
599 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
601 FIXME("(%p) : pRamp@%p\n", This, pRamp);
602 hDC = GetDC(This->win_handle);
603 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
604 ReleaseDC(This->win_handle, hDC);
605 return;
607 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
608 HDC hDC;
609 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
611 FIXME("(%p) : pRamp@%p\n", This, pRamp);
612 hDC = GetDC(This->win_handle);
613 GetDeviceGammaRamp(hDC, pRamp);
614 ReleaseDC(This->win_handle, hDC);
615 return;
617 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
618 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
619 IDirect3DTexture8Impl *object;
620 unsigned int i;
621 UINT tmpW;
622 UINT tmpH;
624 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
626 /* Allocate the storage for the device */
627 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);
628 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
629 object->lpVtbl = &Direct3DTexture8_Vtbl;
630 object->Device = This;
631 object->ResourceType = D3DRTYPE_TEXTURE;
632 object->ref = 1;
633 object->width = Width;
634 object->height = Height;
635 object->levels = Levels;
636 object->usage = Usage;
637 object->format = Format;
639 /* Calculate levels for mip mapping */
640 if (Levels == 0) {
641 object->levels++;
642 tmpW = Width;
643 tmpH = Height;
644 while (tmpW > 1 && tmpH > 1) {
645 tmpW = max(1, tmpW / 2);
646 tmpH = max(1, tmpH / 2);
647 object->levels++;
649 TRACE("Calculated levels = %d\n", object->levels);
652 /* Generate all the surfaces */
653 tmpW = Width;
654 tmpH = Height;
655 for (i = 0; i < object->levels; i++)
657 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
658 object->surfaces[i]->Container = (IUnknown*) object;
659 object->surfaces[i]->myDesc.Usage = Usage;
660 object->surfaces[i]->myDesc.Pool = Pool;
661 /**
662 * As written in msdn in IDirect3DTexture8::LockRect
663 * Textures created in D3DPOOL_DEFAULT are not lockable.
665 if (D3DPOOL_DEFAULT == Pool) {
666 object->surfaces[i]->lockable = FALSE;
669 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
670 tmpW = max(1, tmpW / 2);
671 tmpH = max(1, tmpH / 2);
674 *ppTexture = (LPDIRECT3DTEXTURE8) object;
675 TRACE("(%p) : Created texture %p\n", This, object);
676 return D3D_OK;
678 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
679 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
680 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
682 IDirect3DVolumeTexture8Impl *object;
683 unsigned int i;
684 UINT tmpW;
685 UINT tmpH;
686 UINT tmpD;
688 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
690 /* Allocate the storage for it */
691 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));
692 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
693 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
694 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
695 object->Device = This;
696 object->ref = 1;
698 object->width = Width;
699 object->height = Height;
700 object->depth = Depth;
701 object->levels = Levels;
702 object->usage = Usage;
703 object->format = Format;
705 /* Calculate levels for mip mapping */
706 if (Levels == 0) {
707 object->levels++;
708 tmpW = Width;
709 tmpH = Height;
710 tmpD = Depth;
711 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
712 tmpW = max(1, tmpW / 2);
713 tmpH = max(1, tmpH / 2);
714 tmpD = max(1, tmpD / 2);
715 object->levels++;
717 TRACE("Calculated levels = %d\n", object->levels);
720 /* Generate all the surfaces */
721 tmpW = Width;
722 tmpH = Height;
723 tmpD = Depth;
725 for (i = 0; i < object->levels; i++)
727 IDirect3DVolume8Impl* volume;
729 /* Create the volume - No entry point for this seperately?? */
730 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
731 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
733 volume->lpVtbl = &Direct3DVolume8_Vtbl;
734 volume->Device = This;
735 volume->ResourceType = D3DRTYPE_VOLUME;
736 volume->Container = (IUnknown*) object;
737 volume->ref = 1;
739 volume->myDesc.Width = Width;
740 volume->myDesc.Height = Height;
741 volume->myDesc.Depth = Depth;
742 volume->myDesc.Format = Format;
743 volume->myDesc.Type = D3DRTYPE_VOLUME;
744 volume->myDesc.Pool = Pool;
745 volume->myDesc.Usage = Usage;
746 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
747 /* Note: Volume textures cannot be dxtn, hence no need to check here */
748 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
749 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
751 volume->lockable = TRUE;
752 volume->locked = FALSE;
753 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
754 volume->Dirty = FALSE;
755 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
757 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
758 This, Width, Height, Depth, Format, debug_d3dformat(Format),
759 volume, volume->allocatedMemory, volume->myDesc.Size);
761 tmpW = max(1, tmpW / 2);
762 tmpH = max(1, tmpH / 2);
763 tmpD = max(1, tmpD / 2);
766 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
767 TRACE("(%p) : Created volume texture %p\n", This, object);
768 return D3D_OK;
770 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
771 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
773 IDirect3DCubeTexture8Impl *object;
774 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
775 unsigned int i,j;
776 UINT tmpW;
778 /* Allocate the storage for it */
779 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));
780 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
781 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
782 object->ref = 1;
783 object->Device = This;
784 object->ResourceType = D3DRTYPE_CUBETEXTURE;
786 object->edgeLength = EdgeLength;
787 object->levels = Levels;
788 object->usage = Usage;
789 object->format = Format;
791 /* Calculate levels for mip mapping */
792 if (Levels == 0) {
793 object->levels++;
794 tmpW = EdgeLength;
795 while (tmpW > 1) {
796 tmpW = max(1, tmpW / 2);
797 object->levels++;
799 TRACE("Calculated levels = %d\n", object->levels);
802 /* Generate all the surfaces */
803 tmpW = EdgeLength;
804 for (i = 0; i < object->levels; i++) {
805 /* Create the 6 faces */
806 for (j = 0; j < 6; j++) {
807 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
808 object->surfaces[j][i]->Container = (IUnknown*) object;
809 object->surfaces[j][i]->myDesc.Usage = Usage;
810 object->surfaces[j][i]->myDesc.Pool = Pool;
811 /**
812 * As written in msdn in IDirect3DCubeTexture8::LockRect
813 * Textures created in D3DPOOL_DEFAULT are not lockable.
815 if (D3DPOOL_DEFAULT == Pool) {
816 object->surfaces[j][i]->lockable = FALSE;
819 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
821 tmpW = max(1, tmpW / 2);
824 TRACE("(%p) : Iface@%p\n", This, object);
825 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
826 return D3D_OK;
828 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
829 IDirect3DVertexBuffer8Impl *object;
831 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
833 /* Allocate the storage for the device */
834 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
835 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
836 object->Device = This;
837 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
838 object->ref = 1;
839 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
840 object->currentDesc.Usage = Usage;
841 object->currentDesc.Pool = Pool;
842 object->currentDesc.FVF = FVF;
843 object->currentDesc.Size = Size;
845 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
847 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
849 return D3D_OK;
851 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
852 IDirect3DIndexBuffer8Impl *object;
854 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
855 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
857 /* Allocate the storage for the device */
858 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
859 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
860 object->Device = This;
861 object->ref = 1;
862 object->ResourceType = D3DRTYPE_INDEXBUFFER;
864 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
865 object->currentDesc.Usage = Usage;
866 object->currentDesc.Pool = Pool;
867 object->currentDesc.Format = Format;
868 object->currentDesc.Size = Length;
870 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
872 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
874 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
876 return D3D_OK;
878 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
879 IDirect3DSurface8Impl *object;
880 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
882 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
883 if (NULL == object) {
884 *ppSurface = NULL;
885 return D3DERR_OUTOFVIDEOMEMORY;
887 *ppSurface = (LPDIRECT3DSURFACE8) object;
888 object->lpVtbl = &Direct3DSurface8_Vtbl;
889 object->Device = This;
890 object->ResourceType = D3DRTYPE_SURFACE;
891 object->Container = (IUnknown*) This;
893 object->ref = 1;
894 object->myDesc.Width = Width;
895 object->myDesc.Height = Height;
896 object->myDesc.Format = Format;
897 object->myDesc.Type = D3DRTYPE_SURFACE;
898 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
899 object->myDesc.Pool = D3DPOOL_DEFAULT;
900 object->myDesc.MultiSampleType = MultiSample;
901 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
902 if (Format == D3DFMT_DXT1) {
903 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
904 } else {
905 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
907 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
908 object->lockable = Lockable;
909 object->locked = FALSE;
910 memset(&object->lockedRect, 0, sizeof(RECT));
911 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
913 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);
914 return D3D_OK;
916 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
917 IDirect3DSurface8Impl *object;
919 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
921 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
922 if (NULL == object) {
923 *ppSurface = NULL;
924 return D3DERR_OUTOFVIDEOMEMORY;
926 *ppSurface = (LPDIRECT3DSURFACE8) object;
927 object->lpVtbl = &Direct3DSurface8_Vtbl;
928 object->Device = This;
929 object->ResourceType = D3DRTYPE_SURFACE;
930 object->Container = (IUnknown*) This;
932 object->ref = 1;
933 object->myDesc.Width = Width;
934 object->myDesc.Height = Height;
935 object->myDesc.Format = Format;
936 object->myDesc.Type = D3DRTYPE_SURFACE;
937 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
938 object->myDesc.Pool = D3DPOOL_DEFAULT;
939 object->myDesc.MultiSampleType = MultiSample;
940 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
941 if (Format == D3DFMT_DXT1) {
942 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
943 } else {
944 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
946 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
947 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
948 object->locked = FALSE;
949 memset(&object->lockedRect, 0, sizeof(RECT));
950 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
952 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);
953 return D3D_OK;
955 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
956 IDirect3DSurface8Impl *object;
958 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
960 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
961 *ppSurface = (LPDIRECT3DSURFACE8) object;
962 object->lpVtbl = &Direct3DSurface8_Vtbl;
963 object->Device = This;
964 object->ResourceType = D3DRTYPE_SURFACE;
965 object->Container = (IUnknown*) This;
967 object->ref = 1;
968 object->myDesc.Width = Width;
969 object->myDesc.Height = Height;
970 object->myDesc.Format = Format;
971 object->myDesc.Type = D3DRTYPE_SURFACE;
972 object->myDesc.Usage = 0;
973 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
974 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
975 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
976 it is based around 4x4 pixel blocks it requires padding, so allocate enough
977 space! */
978 if (Format == D3DFMT_DXT1) {
979 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
980 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
981 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
982 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
983 } else {
984 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
986 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
987 object->lockable = TRUE;
988 object->locked = FALSE;
989 memset(&object->lockedRect, 0, sizeof(RECT));
990 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
992 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);
993 return D3D_OK;
995 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
996 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
997 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
999 HRESULT rc = D3D_OK;
1000 IDirect3DBaseTexture8* texture = NULL;
1003 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
1004 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1006 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1007 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1008 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1010 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1011 a sample and doesn't seem to break anything as far as I can tell */
1012 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1013 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1014 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1015 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1016 rc = D3DERR_INVALIDCALL;
1018 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1019 TRACE("Converting dest to same format as source, since dest was unknown\n");
1020 dst->myDesc.Format = src->myDesc.Format;
1022 /* Convert container as well */
1023 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1024 if (SUCCEEDED(rc) && NULL != texture) {
1025 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1026 /** Releasing texture after GetContainer */
1027 IDirect3DBaseTexture8_Release(texture);
1028 texture = NULL;
1032 /* Quick if complete copy ... */
1033 if (SUCCEEDED(rc)) {
1034 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1036 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1038 D3DLOCKED_RECT lrSrc;
1039 D3DLOCKED_RECT lrDst;
1040 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1041 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1042 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1044 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1046 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1047 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1048 TRACE("Unlocked src and dst\n");
1050 } else {
1052 FIXME("Wanted to copy all surfaces but size not compatible\n");
1053 rc = D3DERR_INVALIDCALL;
1057 } else {
1059 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1061 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1062 unsigned int i;
1064 /* Copy rect by rect */
1065 for (i = 0; i < cRects; i++) {
1066 CONST RECT* r = &pSourceRectsArray[i];
1067 CONST POINT* p = &pDestPointsArray[i];
1068 int copyperline;
1069 int j;
1070 D3DLOCKED_RECT lrSrc;
1071 D3DLOCKED_RECT lrDst;
1072 RECT dest_rect;
1074 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1075 if (src->myDesc.Format == D3DFMT_DXT1) {
1076 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1077 } else {
1078 copyperline = ((r->right - r->left) * bytesPerPixel);
1080 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1081 dest_rect.left = p->x;
1082 dest_rect.top = p->y;
1083 dest_rect.right = p->x + (r->right - r->left);
1084 dest_rect.bottom= p->y + (r->bottom - r->top);
1085 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1086 TRACE("Locked src and dst\n");
1088 /* Find where to start */
1089 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1090 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1092 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1093 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1094 TRACE("Unlocked src and dst\n");
1096 } else {
1097 FIXME("Wanted to copy partial surfaces not implemented\n");
1098 rc = D3DERR_INVALIDCALL;
1103 return rc;
1105 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1106 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1107 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1108 D3DRESOURCETYPE srcType;
1109 D3DRESOURCETYPE dstType;
1111 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1112 TRACE("(%p) : first try\n", This);
1114 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1115 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1117 if (srcType != dstType) {
1118 return D3DERR_INVALIDCALL;
1120 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1121 return D3DERR_INVALIDCALL;
1123 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1124 return D3DERR_INVALIDCALL;
1126 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1127 /** Only copy Dirty textures */
1128 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1129 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1130 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1131 UINT i, j;
1133 for (i = skipLevels; i < srcLevelCnt; ++i) {
1134 HRESULT hr;
1136 switch (srcType) {
1137 case D3DRTYPE_TEXTURE:
1139 IDirect3DSurface8* srcSur = NULL;
1140 IDirect3DSurface8* dstSur = NULL;
1141 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1142 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1144 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1145 about dst with less levels than the source?) */
1146 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1148 IDirect3DSurface8Impl_Release(srcSur);
1149 IDirect3DSurface8Impl_Release(dstSur);
1151 break;
1152 case D3DRTYPE_VOLUMETEXTURE:
1154 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1156 break;
1157 case D3DRTYPE_CUBETEXTURE:
1159 IDirect3DSurface8* srcSur = NULL;
1160 IDirect3DSurface8* dstSur = NULL;
1161 for (j = 0; j < 5; ++j) {
1162 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1163 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &dstSur);
1165 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1167 IDirect3DSurface8Impl_Release(srcSur);
1168 IDirect3DSurface8Impl_Release(dstSur);
1171 break;
1172 default:
1173 break;
1176 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1179 return D3D_OK;
1181 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1182 HRESULT hr;
1183 D3DLOCKED_RECT lockedRect;
1184 RECT wantedRect;
1185 GLint prev_store;
1186 GLint prev_read;
1188 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1190 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1192 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1193 ERR("(%p) : surface(%p) has an invalid format\n", This, pDestSurface);
1194 return D3DERR_INVALIDCALL;
1197 wantedRect.left = 0;
1198 wantedRect.top = 0;
1199 wantedRect.right = This->PresentParms.BackBufferWidth;
1200 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1202 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1203 if (FAILED(hr)) {
1204 ERR("(%p) : cannot lock surface\n", This);
1205 return D3DERR_INVALIDCALL;
1208 ENTER_GL();
1210 glFlush();
1211 vcheckGLcall("glFlush");
1212 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1213 vcheckGLcall("glIntegerv");
1214 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1215 vcheckGLcall("glIntegerv");
1217 glReadBuffer(GL_FRONT);
1218 vcheckGLcall("glReadBuffer");
1219 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1220 vcheckGLcall("glPixelStorei");
1221 /* stupid copy */
1223 unsigned long j;
1224 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1225 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1226 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1227 vcheckGLcall("glReadPixels");
1230 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1231 vcheckGLcall("glPixelStorei");
1232 glReadBuffer(prev_read);
1233 vcheckGLcall("glReadBuffer");
1235 LEAVE_GL();
1237 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1238 return hr;
1240 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1241 HRESULT hr = D3D_OK;
1242 D3DVIEWPORT8 viewport;
1244 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1246 /* If pRenderTarget == NULL, it seems to default to back buffer */
1247 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1249 /* For ease of code later on, handle a null depth as leave alone
1250 - Have not tested real d3d for this case but doing this avoids
1251 numerous null pointer checks */
1252 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1254 /* If we are trying to set what we already have, don't bother */
1255 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1256 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1257 } else {
1258 /* Otherwise, set the render target up */
1259 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1260 IDirect3DDevice8Impl_CleanRender(iface);
1261 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1264 if (SUCCEEDED(hr)) {
1265 /* Finally, reset the viewport as the MSDN states. */
1266 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1267 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1268 viewport.X = 0;
1269 viewport.Y = 0;
1270 viewport.MaxZ = 1.0f;
1271 viewport.MinZ = 0.0f;
1272 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1275 return hr;
1278 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1279 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1281 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1283 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1284 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1286 return D3D_OK;
1289 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1290 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1292 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1294 /* Note inc ref on returned surface */
1295 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1296 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1298 return D3D_OK;
1301 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1302 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1303 return IWineD3DDevice_BeginScene(This->WineD3DDevice);
1306 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1307 IDirect3DBaseTexture8* cont = NULL;
1308 HRESULT hr;
1309 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1310 TRACE("(%p)\n", This);
1312 ENTER_GL();
1314 glFlush();
1315 checkGLcall("glFlush");
1317 #if 0 /* Useful for debugging sometimes! */
1318 printf("Hit Enter ...\n");
1319 getchar();
1320 #endif
1322 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1323 #if 0
1324 GLenum prev_read;
1325 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1326 vcheckGLcall("glIntegerv");
1327 glReadBuffer(GL_FRONT);
1328 vcheckGLcall("glReadBuffer");
1330 long j;
1331 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1333 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1334 pitch = pitch / 2;
1336 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1337 glReadPixels(0,
1338 This->renderTarget->myDesc.Height - j - 1,
1339 This->renderTarget->myDesc.Width,
1341 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1342 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1343 This->renderTarget->allocatedMemory + j * pitch);
1344 vcheckGLcall("glReadPixels");
1347 glReadBuffer(prev_read);
1348 vcheckGLcall("glReadBuffer");
1349 #endif
1351 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1352 if (SUCCEEDED(hr) && NULL != cont) {
1353 /** always dirtify for now. we must find a better way to see that surface have been modified */
1354 This->renderTarget->inPBuffer = TRUE;
1355 This->renderTarget->inTexture = FALSE;
1356 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1357 IDirect3DBaseTexture8_PreLoad(cont);
1358 This->renderTarget->inPBuffer = FALSE;
1359 IDirect3DBaseTexture8Impl_Release(cont);
1360 cont = NULL;
1364 LEAVE_GL();
1365 return D3D_OK;
1367 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1368 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1370 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1371 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1372 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1373 GLbitfield glMask = 0;
1374 GLboolean old_ztest;
1375 GLfloat old_z_clear_value;
1376 GLint old_stencil_clear_value;
1377 GLfloat old_color_clear_value[4];
1378 unsigned int i;
1379 CONST D3DRECT* curRect;
1381 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1382 Count, pRects, Flags, Z, Stencil);
1384 ENTER_GL();
1385 glEnable(GL_SCISSOR_TEST);
1386 checkGLcall("glEnable GL_SCISSOR_TEST");
1387 if (Count > 0 && pRects) {
1388 curRect = pRects;
1389 } else {
1390 curRect = NULL;
1393 /* Only set the values up once, as they are not changing */
1394 if (Flags & D3DCLEAR_STENCIL) {
1395 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1396 glClearStencil(Stencil);
1397 checkGLcall("glClearStencil");
1398 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1399 glStencilMask(0xFFFFFFFF);
1402 if (Flags & D3DCLEAR_ZBUFFER) {
1403 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1404 glDepthMask(GL_TRUE);
1405 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1406 glClearDepth(Z);
1407 checkGLcall("glClearDepth");
1408 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1411 if (Flags & D3DCLEAR_TARGET) {
1412 TRACE("Clearing screen with glClear to color %lx\n", Color);
1413 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1414 glClearColor(D3DCOLOR_R(Color),
1415 D3DCOLOR_G(Color),
1416 D3DCOLOR_B(Color),
1417 D3DCOLOR_A(Color));
1418 checkGLcall("glClearColor");
1420 /* Clear ALL colors! */
1421 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1422 glMask = glMask | GL_COLOR_BUFFER_BIT;
1425 /* Now process each rect in turn */
1426 for (i = 0; i < Count || i == 0; i++) {
1428 if (curRect) {
1429 /* Note gl uses lower left, width/height */
1430 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1431 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1432 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1433 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1434 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1435 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1436 checkGLcall("glScissor");
1437 } else {
1438 glScissor(This->StateBlock->viewport.X,
1439 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1440 This->StateBlock->viewport.Width,
1441 This->StateBlock->viewport.Height);
1442 checkGLcall("glScissor");
1445 /* Clear the selected rectangle (or full screen) */
1446 glClear(glMask);
1447 checkGLcall("glClear");
1449 /* Step to the next rectangle */
1450 if (curRect) curRect = curRect + sizeof(D3DRECT);
1453 /* Restore the old values (why..?) */
1454 if (Flags & D3DCLEAR_STENCIL) {
1455 glClearStencil(old_stencil_clear_value);
1456 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1458 if (Flags & D3DCLEAR_ZBUFFER) {
1459 glDepthMask(old_ztest);
1460 glClearDepth(old_z_clear_value);
1462 if (Flags & D3DCLEAR_TARGET) {
1463 glClearColor(old_color_clear_value[0],
1464 old_color_clear_value[1],
1465 old_color_clear_value[2],
1466 old_color_clear_value[3]);
1467 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1468 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1469 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1470 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1473 glDisable(GL_SCISSOR_TEST);
1474 checkGLcall("glDisable");
1475 LEAVE_GL();
1477 return D3D_OK;
1479 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1480 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1481 unsigned int k;
1483 /* Most of this routine, comments included copied from ddraw tree initially: */
1484 TRACE("(%p) : State=%d\n", This, d3dts);
1486 /* Handle recording of state blocks */
1487 if (This->isRecordingState) {
1488 TRACE("Recording... not performing anything\n");
1489 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1490 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1491 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1492 return D3D_OK;
1496 * if the new matrix is the same as the current one,
1497 * we cut off any further processing. this seems to be a reasonable
1498 * optimization because as was noticed, some apps (warcraft3 for example)
1499 * tend towards setting the same matrix repeatedly for some dumb reason.
1501 * From here on we assume that the new matrix is different, wherever it matters
1502 * but note
1504 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1505 TRACE("The app is setting the same matrix over again\n");
1506 return D3D_OK;
1507 } else {
1508 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1512 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1513 where ViewMat = Camera space, WorldMat = world space.
1515 In OpenGL, camera and world space is combined into GL_MODELVIEW
1516 matrix. The Projection matrix stay projection matrix.
1519 /* Capture the times we can just ignore the change */
1520 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1521 This->modelview_valid = FALSE;
1522 return D3D_OK;
1524 } else if (d3dts == D3DTS_PROJECTION) {
1525 This->proj_valid = FALSE;
1526 return D3D_OK;
1528 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1529 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1530 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1531 return D3D_OK;
1534 /* Chances are we really are going to have to change a matrix */
1535 ENTER_GL();
1537 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1538 if (d3dts < GL_LIMITS(textures)) {
1539 int tex = d3dts - D3DTS_TEXTURE0;
1540 #if defined(GL_VERSION_1_3)
1541 glActiveTexture(GL_TEXTURE0 + tex);
1542 checkGLcall("glActiveTexture");
1543 #else
1544 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1545 checkGLcall("glActiveTextureARB");
1546 #endif
1547 set_texture_matrix((const float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1550 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1552 PLIGHTINFOEL *lightChain = NULL;
1553 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1554 This->modelview_valid = FALSE;
1555 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1556 glMatrixMode(GL_MODELVIEW);
1557 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1558 glPushMatrix();
1559 glLoadMatrixf((const float *)lpmatrix);
1560 checkGLcall("glLoadMatrixf(...)");
1562 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1563 * NOTE: We have to reset the positions even if the light/plane is not currently
1564 * enabled, since the call to enable it will not reset the position.
1565 * NOTE2: Apparently texture transforms do NOT need reapplying
1568 /* Reset lights */
1569 lightChain = This->StateBlock->lights;
1570 while (lightChain && lightChain->glIndex != -1) {
1571 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1572 checkGLcall("glLightfv posn");
1573 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1574 checkGLcall("glLightfv dirn");
1575 lightChain = lightChain->next;
1577 /* Reset Clipping Planes if clipping is enabled */
1578 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1579 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1580 checkGLcall("glClipPlane");
1582 glPopMatrix();
1584 } else { /* What was requested!?? */
1585 WARN("invalid matrix specified: %i\n", d3dts);
1589 /* Release lock, all done */
1590 LEAVE_GL();
1591 return D3D_OK;
1594 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1595 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1596 TRACE("(%p) : for State %d\n", This, State);
1597 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1598 return D3D_OK;
1601 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1602 D3DMATRIX *mat = NULL;
1603 D3DMATRIX temp;
1605 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1606 but works regardless of recording being on.
1607 If this is found to be wrong, change to StateBlock. */
1608 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1609 TRACE("(%p) : For state %u\n", This, State);
1611 if (State < HIGHEST_TRANSFORMSTATE)
1613 mat = &This->UpdateStateBlock->transforms[State];
1614 } else {
1615 FIXME("Unhandled transform state!!\n");
1618 /* Copied from ddraw code: */
1619 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);
1620 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);
1621 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);
1622 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);
1624 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);
1625 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);
1626 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);
1627 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);
1629 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);
1630 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);
1631 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);
1632 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);
1634 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);
1635 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);
1636 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);
1637 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);
1639 /* Apply change via set transform - will reapply to eg. lights this way */
1640 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1641 return D3D_OK;
1643 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1644 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1646 TRACE("(%p)\n", This);
1647 This->UpdateStateBlock->Changed.viewport = TRUE;
1648 This->UpdateStateBlock->Set.viewport = TRUE;
1649 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1651 /* Handle recording of state blocks */
1652 if (This->isRecordingState) {
1653 TRACE("Recording... not performing anything\n");
1654 return D3D_OK;
1657 ENTER_GL();
1659 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1660 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1662 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1663 checkGLcall("glDepthRange");
1664 /* Note: GL requires lower left, DirectX supplies upper left */
1665 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1666 pViewport->Width, pViewport->Height);
1667 checkGLcall("glViewport");
1669 LEAVE_GL();
1671 return D3D_OK;
1674 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1675 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1676 TRACE("(%p)\n", This);
1677 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1678 return D3D_OK;
1681 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1682 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1684 This->UpdateStateBlock->Changed.material = TRUE;
1685 This->UpdateStateBlock->Set.material = TRUE;
1686 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1688 /* Handle recording of state blocks */
1689 if (This->isRecordingState) {
1690 TRACE("Recording... not performing anything\n");
1691 return D3D_OK;
1694 ENTER_GL();
1695 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1696 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1697 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1698 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1699 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1701 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1702 checkGLcall("glMaterialfv");
1703 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1704 checkGLcall("glMaterialfv");
1706 /* Only change material color if specular is enabled, otherwise it is set to black */
1707 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1708 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1709 checkGLcall("glMaterialfv");
1710 } else {
1711 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1712 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1713 checkGLcall("glMaterialfv");
1715 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1716 checkGLcall("glMaterialfv");
1717 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1718 checkGLcall("glMaterialf");
1720 LEAVE_GL();
1721 return D3D_OK;
1723 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1724 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1725 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1726 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1727 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1728 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1729 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1730 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1731 return D3D_OK;
1734 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1735 you can reference any indexes you want as long as that number max are enabled are any
1736 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1737 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1738 but when recording, just build a chain pretty much of commands to be replayed. */
1740 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1741 float rho;
1742 PLIGHTINFOEL *object, *temp;
1744 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1745 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1747 /* If recording state block, just add to end of lights chain */
1748 if (This->isRecordingState) {
1749 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1750 if (NULL == object) {
1751 return D3DERR_OUTOFVIDEOMEMORY;
1753 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1754 object->OriginalIndex = Index;
1755 object->glIndex = -1;
1756 object->changed = TRUE;
1758 /* Add to the END of the chain of lights changes to be replayed */
1759 if (This->UpdateStateBlock->lights == NULL) {
1760 This->UpdateStateBlock->lights = object;
1761 } else {
1762 temp = This->UpdateStateBlock->lights;
1763 while (temp->next != NULL) temp=temp->next;
1764 temp->next = object;
1766 TRACE("Recording... not performing anything more\n");
1767 return D3D_OK;
1770 /* Ok, not recording any longer so do real work */
1771 object = This->StateBlock->lights;
1772 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1774 /* If we didn't find it in the list of lights, time to add it */
1775 if (object == NULL) {
1776 PLIGHTINFOEL *insertAt,*prevPos;
1778 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1779 if (NULL == object) {
1780 return D3DERR_OUTOFVIDEOMEMORY;
1782 object->OriginalIndex = Index;
1783 object->glIndex = -1;
1785 /* Add it to the front of list with the idea that lights will be changed as needed
1786 BUT after any lights currently assigned GL indexes */
1787 insertAt = This->StateBlock->lights;
1788 prevPos = NULL;
1789 while (insertAt != NULL && insertAt->glIndex != -1) {
1790 prevPos = insertAt;
1791 insertAt = insertAt->next;
1794 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1795 This->StateBlock->lights = object;
1796 } else if (insertAt == NULL) { /* End of list */
1797 prevPos->next = object;
1798 object->prev = prevPos;
1799 } else { /* Middle of chain */
1800 if (prevPos == NULL) {
1801 This->StateBlock->lights = object;
1802 } else {
1803 prevPos->next = object;
1805 object->prev = prevPos;
1806 object->next = insertAt;
1807 insertAt->prev = object;
1811 /* Initialze the object */
1812 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,
1813 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1814 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1815 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1816 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1817 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1818 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1820 /* Save away the information */
1821 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1823 switch (pLight->Type) {
1824 case D3DLIGHT_POINT:
1825 /* Position */
1826 object->lightPosn[0] = pLight->Position.x;
1827 object->lightPosn[1] = pLight->Position.y;
1828 object->lightPosn[2] = pLight->Position.z;
1829 object->lightPosn[3] = 1.0f;
1830 object->cutoff = 180.0f;
1831 /* FIXME: Range */
1832 break;
1834 case D3DLIGHT_DIRECTIONAL:
1835 /* Direction */
1836 object->lightPosn[0] = -pLight->Direction.x;
1837 object->lightPosn[1] = -pLight->Direction.y;
1838 object->lightPosn[2] = -pLight->Direction.z;
1839 object->lightPosn[3] = 0.0;
1840 object->exponent = 0.0f;
1841 object->cutoff = 180.0f;
1842 break;
1844 case D3DLIGHT_SPOT:
1845 /* Position */
1846 object->lightPosn[0] = pLight->Position.x;
1847 object->lightPosn[1] = pLight->Position.y;
1848 object->lightPosn[2] = pLight->Position.z;
1849 object->lightPosn[3] = 1.0;
1851 /* Direction */
1852 object->lightDirn[0] = pLight->Direction.x;
1853 object->lightDirn[1] = pLight->Direction.y;
1854 object->lightDirn[2] = pLight->Direction.z;
1855 object->lightDirn[3] = 1.0;
1858 * opengl-ish and d3d-ish spot lights use too different models for the
1859 * light "intensity" as a function of the angle towards the main light direction,
1860 * so we only can approximate very roughly.
1861 * however spot lights are rather rarely used in games (if ever used at all).
1862 * furthermore if still used, probably nobody pays attention to such details.
1864 if (pLight->Falloff == 0) {
1865 rho = 6.28f;
1866 } else {
1867 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1869 if (rho < 0.0001) rho = 0.0001f;
1870 object->exponent = -0.3/log(cos(rho/2));
1871 object->cutoff = pLight->Phi*90/M_PI;
1873 /* FIXME: Range */
1874 break;
1876 default:
1877 FIXME("Unrecognized light type %d\n", pLight->Type);
1880 /* Update the live definitions if the light is currently assigned a glIndex */
1881 if (object->glIndex != -1) {
1882 setup_light(iface, object->glIndex, object);
1884 return D3D_OK;
1886 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1887 PLIGHTINFOEL *lightInfo = NULL;
1888 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1889 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1891 /* Locate the light in the live lights */
1892 lightInfo = This->StateBlock->lights;
1893 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1895 if (lightInfo == NULL) {
1896 TRACE("Light information requested but light not defined\n");
1897 return D3DERR_INVALIDCALL;
1900 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1901 return D3D_OK;
1903 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1904 PLIGHTINFOEL *lightInfo = NULL;
1905 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1906 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1908 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1909 if (This->isRecordingState) {
1910 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1911 if (NULL == lightInfo) {
1912 return D3DERR_OUTOFVIDEOMEMORY;
1914 lightInfo->OriginalIndex = Index;
1915 lightInfo->glIndex = -1;
1916 lightInfo->enabledChanged = TRUE;
1918 /* Add to the END of the chain of lights changes to be replayed */
1919 if (This->UpdateStateBlock->lights == NULL) {
1920 This->UpdateStateBlock->lights = lightInfo;
1921 } else {
1922 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1923 while (temp->next != NULL) temp=temp->next;
1924 temp->next = lightInfo;
1926 TRACE("Recording... not performing anything more\n");
1927 return D3D_OK;
1930 /* Not recording... So, locate the light in the live lights */
1931 lightInfo = This->StateBlock->lights;
1932 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1934 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1935 if (lightInfo == NULL) {
1936 D3DLIGHT8 lightParms;
1937 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1938 wait until someone confirms it seems to work! */
1939 TRACE("Light enabled requested but light not defined, so defining one!\n");
1940 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1941 lightParms.Diffuse.r = 1.0;
1942 lightParms.Diffuse.g = 1.0;
1943 lightParms.Diffuse.b = 1.0;
1944 lightParms.Diffuse.a = 0.0;
1945 lightParms.Specular.r = 0.0;
1946 lightParms.Specular.g = 0.0;
1947 lightParms.Specular.b = 0.0;
1948 lightParms.Specular.a = 0.0;
1949 lightParms.Ambient.r = 0.0;
1950 lightParms.Ambient.g = 0.0;
1951 lightParms.Ambient.b = 0.0;
1952 lightParms.Ambient.a = 0.0;
1953 lightParms.Position.x = 0.0;
1954 lightParms.Position.y = 0.0;
1955 lightParms.Position.z = 0.0;
1956 lightParms.Direction.x = 0.0;
1957 lightParms.Direction.y = 0.0;
1958 lightParms.Direction.z = 1.0;
1959 lightParms.Range = 0.0;
1960 lightParms.Falloff = 0.0;
1961 lightParms.Attenuation0 = 0.0;
1962 lightParms.Attenuation1 = 0.0;
1963 lightParms.Attenuation2 = 0.0;
1964 lightParms.Theta = 0.0;
1965 lightParms.Phi = 0.0;
1966 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1968 /* Search for it again! Should be fairly quick as near head of list */
1969 lightInfo = This->StateBlock->lights;
1970 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1971 if (lightInfo == NULL) {
1972 FIXME("Adding default lights has failed dismally\n");
1973 return D3DERR_INVALIDCALL;
1977 /* OK, we now have a light... */
1978 if (Enable == FALSE) {
1980 /* If we are disabling it, check it was enabled, and
1981 still only do something if it has assigned a glIndex (which it should have!) */
1982 if (lightInfo->lightEnabled && (lightInfo->glIndex != -1)) {
1983 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1984 ENTER_GL();
1985 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1986 checkGLcall("glDisable GL_LIGHT0+Index");
1987 LEAVE_GL();
1988 } else {
1989 TRACE("Nothing to do as light was not enabled\n");
1991 lightInfo->lightEnabled = FALSE;
1992 } else {
1994 /* We are enabling it. If it is enabled, its really simple */
1995 if (lightInfo->lightEnabled) {
1996 /* nop */
1997 TRACE("Nothing to do as light was enabled\n");
1999 /* If it already has a glIndex, its still simple */
2000 } else if (lightInfo->glIndex != -1) {
2001 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2002 lightInfo->lightEnabled = TRUE;
2003 ENTER_GL();
2004 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2005 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2006 LEAVE_GL();
2008 /* Otherwise got to find space - lights are ordered gl indexes first */
2009 } else {
2010 PLIGHTINFOEL *bsf = NULL;
2011 PLIGHTINFOEL *pos = This->StateBlock->lights;
2012 PLIGHTINFOEL *prev = NULL;
2013 int Index= 0;
2014 int glIndex = -1;
2016 /* Try to minimize changes as much as possible */
2017 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2019 /* Try to remember which index can be replaced if necessary */
2020 if (bsf==NULL && pos->lightEnabled == FALSE) {
2021 /* Found a light we can replace, save as best replacement */
2022 bsf = pos;
2025 /* Step to next space */
2026 prev = pos;
2027 pos = pos->next;
2028 Index ++;
2031 /* If we have too many active lights, fail the call */
2032 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2033 FIXME("Program requests too many concurrent lights\n");
2034 return D3DERR_INVALIDCALL;
2036 /* If we have allocated all lights, but not all are enabled,
2037 reuse one which is not enabled */
2038 } else if (Index == This->maxConcurrentLights) {
2039 /* use bsf - Simply swap the new light and the BSF one */
2040 PLIGHTINFOEL *bsfNext = bsf->next;
2041 PLIGHTINFOEL *bsfPrev = bsf->prev;
2043 /* Sort out ends */
2044 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2045 if (bsf->prev != NULL) {
2046 bsf->prev->next = lightInfo;
2047 } else {
2048 This->StateBlock->lights = lightInfo;
2051 /* If not side by side, lots of chains to update */
2052 if (bsf->next != lightInfo) {
2053 lightInfo->prev->next = bsf;
2054 bsf->next->prev = lightInfo;
2055 bsf->next = lightInfo->next;
2056 bsf->prev = lightInfo->prev;
2057 lightInfo->next = bsfNext;
2058 lightInfo->prev = bsfPrev;
2060 } else {
2061 /* Simple swaps */
2062 bsf->prev = lightInfo;
2063 bsf->next = lightInfo->next;
2064 lightInfo->next = bsf;
2065 lightInfo->prev = bsfPrev;
2069 /* Update states */
2070 glIndex = bsf->glIndex;
2071 bsf->glIndex = -1;
2072 lightInfo->glIndex = glIndex;
2073 lightInfo->lightEnabled = TRUE;
2075 /* Finally set up the light in gl itself */
2076 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2077 ENTER_GL();
2078 setup_light(iface, glIndex, lightInfo);
2079 glEnable(GL_LIGHT0 + glIndex);
2080 checkGLcall("glEnable GL_LIGHT0 new setup");
2081 LEAVE_GL();
2083 /* If we reached the end of the allocated lights, with space in the
2084 gl lights, setup a new light */
2085 } else if (pos->glIndex == -1) {
2087 /* We reached the end of the allocated gl lights, so already
2088 know the index of the next one! */
2089 glIndex = Index;
2090 lightInfo->glIndex = glIndex;
2091 lightInfo->lightEnabled = TRUE;
2093 /* In an ideal world, its already in the right place */
2094 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2095 /* No need to move it */
2096 } else {
2097 /* Remove this light from the list */
2098 lightInfo->prev->next = lightInfo->next;
2099 if (lightInfo->next != NULL) {
2100 lightInfo->next->prev = lightInfo->prev;
2103 /* Add in at appropriate place (inbetween prev and pos) */
2104 lightInfo->prev = prev;
2105 lightInfo->next = pos;
2106 if (prev == NULL) {
2107 This->StateBlock->lights = lightInfo;
2108 } else {
2109 prev->next = lightInfo;
2111 if (pos != NULL) {
2112 pos->prev = lightInfo;
2116 /* Finally set up the light in gl itself */
2117 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2118 ENTER_GL();
2119 setup_light(iface, glIndex, lightInfo);
2120 glEnable(GL_LIGHT0 + glIndex);
2121 checkGLcall("glEnable GL_LIGHT0 new setup");
2122 LEAVE_GL();
2127 return D3D_OK;
2129 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2131 PLIGHTINFOEL *lightInfo = NULL;
2132 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2133 TRACE("(%p) : for idx(%ld)\n", This, Index);
2135 /* Locate the light in the live lights */
2136 lightInfo = This->StateBlock->lights;
2137 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2139 if (lightInfo == NULL) {
2140 TRACE("Light enabled state requested but light not defined\n");
2141 return D3DERR_INVALIDCALL;
2143 *pEnable = lightInfo->lightEnabled;
2144 return D3D_OK;
2146 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2147 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2148 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2150 /* Validate Index */
2151 if (Index >= GL_LIMITS(clipplanes)) {
2152 TRACE("Application has requested clipplane this device doesn't support\n");
2153 return D3DERR_INVALIDCALL;
2156 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2157 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2158 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2159 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2160 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2161 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2163 /* Handle recording of state blocks */
2164 if (This->isRecordingState) {
2165 TRACE("Recording... not performing anything\n");
2166 return D3D_OK;
2169 /* Apply it */
2171 ENTER_GL();
2173 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2174 glMatrixMode(GL_MODELVIEW);
2175 glPushMatrix();
2176 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2178 TRACE("Clipplane [%f,%f,%f,%f]\n",
2179 This->UpdateStateBlock->clipplane[Index][0],
2180 This->UpdateStateBlock->clipplane[Index][1],
2181 This->UpdateStateBlock->clipplane[Index][2],
2182 This->UpdateStateBlock->clipplane[Index][3]);
2183 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2184 checkGLcall("glClipPlane");
2186 glPopMatrix();
2188 LEAVE_GL();
2190 return D3D_OK;
2192 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2193 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2194 TRACE("(%p) : for idx %ld\n", This, Index);
2196 /* Validate Index */
2197 if (Index >= GL_LIMITS(clipplanes)) {
2198 TRACE("Application has requested clipplane this device doesn't support\n");
2199 return D3DERR_INVALIDCALL;
2202 pPlane[0] = This->StateBlock->clipplane[Index][0];
2203 pPlane[1] = This->StateBlock->clipplane[Index][1];
2204 pPlane[2] = This->StateBlock->clipplane[Index][2];
2205 pPlane[3] = This->StateBlock->clipplane[Index][3];
2206 return D3D_OK;
2208 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2209 union {
2210 DWORD d;
2211 float f;
2212 } tmpvalue;
2213 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2214 DWORD OldValue = This->StateBlock->renderstate[State];
2216 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2217 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2218 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2219 This->UpdateStateBlock->renderstate[State] = Value;
2221 /* Handle recording of state blocks */
2222 if (This->isRecordingState) {
2223 TRACE("Recording... not performing anything\n");
2224 return D3D_OK;
2227 ENTER_GL();
2229 switch (State) {
2230 case D3DRS_FILLMODE :
2231 switch ((D3DFILLMODE) Value) {
2232 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2233 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2234 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2235 default:
2236 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2238 checkGLcall("glPolygonMode (fillmode)");
2239 break;
2241 case D3DRS_LIGHTING :
2242 if (Value) {
2243 glEnable(GL_LIGHTING);
2244 checkGLcall("glEnable GL_LIGHTING");
2245 } else {
2246 glDisable(GL_LIGHTING);
2247 checkGLcall("glDisable GL_LIGHTING");
2249 break;
2251 case D3DRS_ZENABLE :
2252 switch ((D3DZBUFFERTYPE) Value) {
2253 case D3DZB_FALSE:
2254 glDisable(GL_DEPTH_TEST);
2255 checkGLcall("glDisable GL_DEPTH_TEST");
2256 break;
2257 case D3DZB_TRUE:
2258 glEnable(GL_DEPTH_TEST);
2259 checkGLcall("glEnable GL_DEPTH_TEST");
2260 break;
2261 case D3DZB_USEW:
2262 glEnable(GL_DEPTH_TEST);
2263 checkGLcall("glEnable GL_DEPTH_TEST");
2264 FIXME("W buffer is not well handled\n");
2265 break;
2266 default:
2267 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2269 break;
2271 case D3DRS_CULLMODE :
2273 /* If we are culling "back faces with clockwise vertices" then
2274 set front faces to be counter clockwise and enable culling
2275 of back faces */
2276 switch ((D3DCULL) Value) {
2277 case D3DCULL_NONE:
2278 glDisable(GL_CULL_FACE);
2279 checkGLcall("glDisable GL_CULL_FACE");
2280 break;
2281 case D3DCULL_CW:
2282 glEnable(GL_CULL_FACE);
2283 checkGLcall("glEnable GL_CULL_FACE");
2284 if (This->renderUpsideDown) {
2285 glFrontFace(GL_CW);
2286 checkGLcall("glFrontFace GL_CW");
2287 } else {
2288 glFrontFace(GL_CCW);
2289 checkGLcall("glFrontFace GL_CCW");
2291 glCullFace(GL_BACK);
2292 break;
2293 case D3DCULL_CCW:
2294 glEnable(GL_CULL_FACE);
2295 checkGLcall("glEnable GL_CULL_FACE");
2296 if (This->renderUpsideDown) {
2297 glFrontFace(GL_CCW);
2298 checkGLcall("glFrontFace GL_CCW");
2299 } else {
2300 glFrontFace(GL_CW);
2301 checkGLcall("glFrontFace GL_CW");
2303 glCullFace(GL_BACK);
2304 break;
2305 default:
2306 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2308 break;
2310 case D3DRS_SHADEMODE :
2311 switch ((D3DSHADEMODE) Value) {
2312 case D3DSHADE_FLAT:
2313 glShadeModel(GL_FLAT);
2314 checkGLcall("glShadeModel");
2315 break;
2316 case D3DSHADE_GOURAUD:
2317 glShadeModel(GL_SMOOTH);
2318 checkGLcall("glShadeModel");
2319 break;
2320 case D3DSHADE_PHONG:
2321 FIXME("D3DSHADE_PHONG isn't supported?\n");
2323 LEAVE_GL();
2324 return D3DERR_INVALIDCALL;
2325 default:
2326 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2328 break;
2330 case D3DRS_DITHERENABLE :
2331 if (Value) {
2332 glEnable(GL_DITHER);
2333 checkGLcall("glEnable GL_DITHER");
2334 } else {
2335 glDisable(GL_DITHER);
2336 checkGLcall("glDisable GL_DITHER");
2338 break;
2340 case D3DRS_ZWRITEENABLE :
2341 if (Value) {
2342 glDepthMask(1);
2343 checkGLcall("glDepthMask");
2344 } else {
2345 glDepthMask(0);
2346 checkGLcall("glDepthMask");
2348 break;
2350 case D3DRS_ZFUNC :
2352 int glParm = GL_LESS;
2354 switch ((D3DCMPFUNC) Value) {
2355 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2356 case D3DCMP_LESS: glParm=GL_LESS; break;
2357 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2358 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2359 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2360 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2361 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2362 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2363 default:
2364 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2366 glDepthFunc(glParm);
2367 checkGLcall("glDepthFunc");
2369 break;
2371 case D3DRS_AMBIENT :
2373 float col[4];
2374 D3DCOLORTOGLFLOAT4(Value, col);
2375 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2376 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2377 checkGLcall("glLightModel for MODEL_AMBIENT");
2380 break;
2382 case D3DRS_ALPHABLENDENABLE :
2383 if (Value) {
2384 glEnable(GL_BLEND);
2385 checkGLcall("glEnable GL_BLEND");
2386 } else {
2387 glDisable(GL_BLEND);
2388 checkGLcall("glDisable GL_BLEND");
2390 break;
2392 case D3DRS_SRCBLEND :
2393 case D3DRS_DESTBLEND :
2395 int newVal = GL_ZERO;
2396 switch (Value) {
2397 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2398 case D3DBLEND_ONE : newVal = GL_ONE; break;
2399 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2400 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2401 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2402 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2403 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2404 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2405 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2406 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2407 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2409 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2410 This->srcBlend = newVal;
2411 This->dstBlend = newVal;
2412 break;
2414 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2415 This->srcBlend = newVal;
2416 This->dstBlend = newVal;
2417 break;
2418 default:
2419 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2422 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2423 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2424 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2425 glBlendFunc(This->srcBlend, This->dstBlend);
2427 checkGLcall("glBlendFunc");
2429 break;
2431 case D3DRS_ALPHATESTENABLE :
2432 if (Value) {
2433 glEnable(GL_ALPHA_TEST);
2434 checkGLcall("glEnable GL_ALPHA_TEST");
2435 } else {
2436 glDisable(GL_ALPHA_TEST);
2437 checkGLcall("glDisable GL_ALPHA_TEST");
2439 break;
2441 case D3DRS_ALPHAFUNC :
2443 int glParm = GL_LESS;
2444 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2446 switch ((D3DCMPFUNC) Value) {
2447 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2448 case D3DCMP_LESS: glParm = GL_LESS; break;
2449 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2450 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2451 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2452 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2453 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2454 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2455 default:
2456 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2458 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2459 glAlphaFunc(glParm, ref);
2460 This->alphafunc = glParm;
2461 checkGLcall("glAlphaFunc");
2463 break;
2465 case D3DRS_ALPHAREF :
2467 int glParm = This->alphafunc;
2468 float ref = 1.0f;
2470 ref = ((float) Value) / 255.0f;
2471 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2472 glAlphaFunc(glParm, ref);
2473 checkGLcall("glAlphaFunc");
2475 break;
2477 case D3DRS_CLIPPLANEENABLE :
2478 case D3DRS_CLIPPING :
2480 /* Ensure we only do the changed clip planes */
2481 DWORD enable = 0xFFFFFFFF;
2482 DWORD disable = 0x00000000;
2484 /* If enabling / disabling all */
2485 if (State == D3DRS_CLIPPING) {
2486 if (Value) {
2487 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2488 disable = 0x00;
2489 } else {
2490 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2491 enable = 0x00;
2493 } else {
2494 enable = Value & ~OldValue;
2495 disable = ~Value & OldValue;
2498 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2499 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2500 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2501 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2502 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2503 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2505 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2506 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2507 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2508 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2509 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2510 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2512 /** update clipping status */
2513 if (enable) {
2514 This->StateBlock->clip_status.ClipUnion = 0;
2515 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2516 } else {
2517 This->StateBlock->clip_status.ClipUnion = 0;
2518 This->StateBlock->clip_status.ClipIntersection = 0;
2521 break;
2523 case D3DRS_BLENDOP :
2525 int glParm = GL_FUNC_ADD;
2527 switch ((D3DBLENDOP) Value) {
2528 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2529 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2530 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2531 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2532 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2533 default:
2534 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2536 TRACE("glBlendEquation(%x)\n", glParm);
2537 glBlendEquation(glParm);
2538 checkGLcall("glBlendEquation");
2540 break;
2542 case D3DRS_TEXTUREFACTOR :
2544 unsigned int i;
2546 /* Note the texture color applies to all textures whereas
2547 GL_TEXTURE_ENV_COLOR applies to active only */
2548 float col[4];
2549 D3DCOLORTOGLFLOAT4(Value, col);
2550 /* Set the default alpha blend color */
2551 glBlendColor(col[0], col[1], col[2], col[3]);
2552 checkGLcall("glBlendColor");
2554 /* And now the default texture color as well */
2555 for (i = 0; i < GL_LIMITS(textures); i++) {
2557 /* Note the D3DRS value applies to all textures, but GL has one
2558 per texture, so apply it now ready to be used! */
2559 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2560 #if defined(GL_VERSION_1_3)
2561 glActiveTexture(GL_TEXTURE0 + i);
2562 #else
2563 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2564 #endif
2565 checkGLcall("Activate texture.. to update const color");
2566 } else if (i>0) {
2567 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2570 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2571 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2574 break;
2576 case D3DRS_SPECULARENABLE :
2578 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2579 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2580 specular color. This is wrong:
2581 Separate specular color means the specular colour is maintained separately, whereas
2582 single color means it is merged in. However in both cases they are being used to
2583 some extent.
2584 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2585 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2586 running 1.4 yet!
2588 if (Value) {
2589 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2590 checkGLcall("glMaterialfv");
2591 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2592 glEnable(GL_COLOR_SUM_EXT);
2593 } else {
2594 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2596 checkGLcall("glEnable(GL_COLOR_SUM)");
2597 } else {
2598 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2600 /* for the case of enabled lighting: */
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2602 checkGLcall("glMaterialfv");
2604 /* for the case of disabled lighting: */
2605 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2606 glDisable(GL_COLOR_SUM_EXT);
2607 } else {
2608 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2610 checkGLcall("glDisable(GL_COLOR_SUM)");
2613 break;
2615 case D3DRS_STENCILENABLE :
2616 if (Value) {
2617 glEnable(GL_STENCIL_TEST);
2618 checkGLcall("glEnable GL_STENCIL_TEST");
2619 } else {
2620 glDisable(GL_STENCIL_TEST);
2621 checkGLcall("glDisable GL_STENCIL_TEST");
2623 break;
2625 case D3DRS_STENCILFUNC :
2627 int glParm = GL_ALWAYS;
2628 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2629 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2631 switch ((D3DCMPFUNC) Value) {
2632 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2633 case D3DCMP_LESS: glParm=GL_LESS; break;
2634 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2635 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2636 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2637 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2638 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2639 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2640 default:
2641 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2643 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2644 This->stencilfunc = glParm;
2645 glStencilFunc(glParm, ref, mask);
2646 checkGLcall("glStencilFunc");
2648 break;
2650 case D3DRS_STENCILREF :
2652 int glParm = This->stencilfunc;
2653 int ref = 0;
2654 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2656 ref = Value;
2657 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2658 glStencilFunc(glParm, ref, mask);
2659 checkGLcall("glStencilFunc");
2661 break;
2663 case D3DRS_STENCILMASK :
2665 int glParm = This->stencilfunc;
2666 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2667 GLuint mask = Value;
2669 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2670 glStencilFunc(glParm, ref, mask);
2671 checkGLcall("glStencilFunc");
2673 break;
2675 case D3DRS_STENCILFAIL :
2677 GLenum fail ;
2678 GLint zpass ;
2679 GLint zfail ;
2681 fail = StencilOp(Value);
2682 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2683 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2684 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2685 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2687 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2688 glStencilOp(fail, zfail, zpass);
2689 checkGLcall("glStencilOp(fail, zfail, zpass);");
2691 break;
2692 case D3DRS_STENCILZFAIL :
2694 GLint fail ;
2695 GLint zpass ;
2696 GLenum zfail ;
2698 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2699 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2700 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2701 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2702 zfail = StencilOp(Value);
2704 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2705 glStencilOp(fail, zfail, zpass);
2706 checkGLcall("glStencilOp(fail, zfail, zpass);");
2708 break;
2709 case D3DRS_STENCILPASS :
2711 GLint fail ;
2712 GLenum zpass ;
2713 GLint zfail ;
2715 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2716 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2717 zpass = StencilOp(Value);
2718 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2719 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2721 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2722 glStencilOp(fail, zfail, zpass);
2723 checkGLcall("glStencilOp(fail, zfail, zpass);");
2725 break;
2727 case D3DRS_STENCILWRITEMASK :
2729 glStencilMask(Value);
2730 TRACE("glStencilMask(%lu)\n", Value);
2731 checkGLcall("glStencilMask");
2733 break;
2735 case D3DRS_FOGENABLE :
2737 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2738 glEnable(GL_FOG);
2739 checkGLcall("glEnable GL_FOG");
2740 } else {
2741 glDisable(GL_FOG);
2742 checkGLcall("glDisable GL_FOG");
2745 break;
2747 case D3DRS_RANGEFOGENABLE :
2749 if (Value) {
2750 TRACE("Enabled RANGEFOG");
2751 } else {
2752 TRACE("Disabled RANGEFOG");
2755 break;
2757 case D3DRS_FOGCOLOR :
2759 float col[4];
2760 D3DCOLORTOGLFLOAT4(Value, col);
2761 /* Set the default alpha blend color */
2762 glFogfv(GL_FOG_COLOR, &col[0]);
2763 checkGLcall("glFog GL_FOG_COLOR");
2765 break;
2767 case D3DRS_FOGTABLEMODE :
2769 glHint(GL_FOG_HINT, GL_NICEST);
2770 switch (Value) {
2771 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2772 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2773 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2774 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2775 default:
2776 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2778 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2779 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2782 break;
2784 case D3DRS_FOGVERTEXMODE :
2786 glHint(GL_FOG_HINT, GL_FASTEST);
2787 switch (Value) {
2788 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2789 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2790 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2791 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2792 default:
2793 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2795 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2796 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2799 break;
2801 case D3DRS_FOGSTART :
2803 tmpvalue.d = Value;
2804 glFogfv(GL_FOG_START, &tmpvalue.f);
2805 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2806 TRACE("Fog Start == %f\n", tmpvalue.f);
2808 break;
2810 case D3DRS_FOGEND :
2812 tmpvalue.d = Value;
2813 glFogfv(GL_FOG_END, &tmpvalue.f);
2814 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2815 TRACE("Fog End == %f\n", tmpvalue.f);
2817 break;
2819 case D3DRS_FOGDENSITY :
2821 tmpvalue.d = Value;
2822 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2823 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2825 break;
2827 case D3DRS_VERTEXBLEND :
2829 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2830 TRACE("Vertex Blending state to %ld\n", Value);
2832 break;
2834 case D3DRS_TWEENFACTOR :
2836 tmpvalue.d = Value;
2837 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2838 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2840 break;
2842 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2844 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2846 break;
2848 case D3DRS_COLORVERTEX :
2849 case D3DRS_DIFFUSEMATERIALSOURCE :
2850 case D3DRS_SPECULARMATERIALSOURCE :
2851 case D3DRS_AMBIENTMATERIALSOURCE :
2852 case D3DRS_EMISSIVEMATERIALSOURCE :
2854 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2856 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2857 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2858 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2859 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2860 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2861 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2863 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2864 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2865 Parm = GL_AMBIENT_AND_DIFFUSE;
2866 } else {
2867 Parm = GL_DIFFUSE;
2869 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2870 Parm = GL_AMBIENT;
2871 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2872 Parm = GL_EMISSION;
2873 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2874 Parm = GL_SPECULAR;
2875 } else {
2876 Parm = -1;
2879 if (Parm == -1) {
2880 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2881 } else {
2882 This->tracking_color = NEEDS_TRACKING;
2883 This->tracking_parm = Parm;
2886 } else {
2887 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2890 break;
2892 case D3DRS_LINEPATTERN :
2894 union {
2895 DWORD d;
2896 D3DLINEPATTERN lp;
2897 } tmppattern;
2898 tmppattern.d = Value;
2900 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2902 if (tmppattern.lp.wRepeatFactor) {
2903 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2904 checkGLcall("glLineStipple(repeat, linepattern)");
2905 glEnable(GL_LINE_STIPPLE);
2906 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2907 } else {
2908 glDisable(GL_LINE_STIPPLE);
2909 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2912 break;
2914 case D3DRS_ZBIAS :
2916 if (Value) {
2917 tmpvalue.d = Value;
2918 TRACE("ZBias value %f\n", tmpvalue.f);
2919 glPolygonOffset(0, -tmpvalue.f);
2920 checkGLcall("glPolygonOffset(0, -Value)");
2921 glEnable(GL_POLYGON_OFFSET_FILL);
2922 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2923 glEnable(GL_POLYGON_OFFSET_LINE);
2924 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2925 glEnable(GL_POLYGON_OFFSET_POINT);
2926 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2927 } else {
2928 glDisable(GL_POLYGON_OFFSET_FILL);
2929 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2930 glDisable(GL_POLYGON_OFFSET_LINE);
2931 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2932 glDisable(GL_POLYGON_OFFSET_POINT);
2933 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2936 break;
2938 case D3DRS_NORMALIZENORMALS :
2939 if (Value) {
2940 glEnable(GL_NORMALIZE);
2941 checkGLcall("glEnable(GL_NORMALIZE);");
2942 } else {
2943 glDisable(GL_NORMALIZE);
2944 checkGLcall("glDisable(GL_NORMALIZE);");
2946 break;
2948 case D3DRS_POINTSIZE :
2949 tmpvalue.d = Value;
2950 TRACE("Set point size to %f\n", tmpvalue.f);
2951 glPointSize(tmpvalue.f);
2952 checkGLcall("glPointSize(...);");
2953 break;
2955 case D3DRS_POINTSIZE_MIN :
2956 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2957 tmpvalue.d = Value;
2958 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2959 checkGLcall("glPointParameterfEXT(...);");
2960 } else {
2961 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2963 break;
2965 case D3DRS_POINTSIZE_MAX :
2966 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2967 tmpvalue.d = Value;
2968 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2969 checkGLcall("glPointParameterfEXT(...);");
2970 } else {
2971 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2973 break;
2975 case D3DRS_POINTSCALE_A :
2976 case D3DRS_POINTSCALE_B :
2977 case D3DRS_POINTSCALE_C :
2978 case D3DRS_POINTSCALEENABLE :
2981 * POINTSCALEENABLE controls how point size value is treated. If set to
2982 * true, the point size is scaled with respect to height of viewport.
2983 * When set to false point size is in pixels.
2985 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
2988 /* Default values */
2989 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2992 * Minium valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
2993 * This means that OpenGL will clamp really small point sizes to 1.0f.
2994 * To correct for this we need to multiply by the scale factor when sizes
2995 * are less than 1.0f. scale_factor = 1.0f / point_size.
2997 GLfloat pointSize = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSIZE]);
2998 GLfloat scaleFactor;
2999 if(pointSize < 1.0f) {
3000 scaleFactor = pointSize * pointSize;
3001 } else {
3002 scaleFactor = 1.0f;
3005 if(This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
3006 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]) /
3007 (This->StateBlock->viewport.Height * This->StateBlock->viewport.Height * scaleFactor);
3008 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]) /
3009 (This->StateBlock->viewport.Height * This->StateBlock->viewport.Height * scaleFactor);
3010 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]) /
3011 (This->StateBlock->viewport.Height * This->StateBlock->viewport.Height * scaleFactor);
3014 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
3015 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
3016 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3018 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3019 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3020 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3022 else {
3023 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3025 break;
3027 case D3DRS_COLORWRITEENABLE :
3029 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3030 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3031 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3032 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3033 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3034 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3035 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3036 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3037 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3038 checkGLcall("glColorMask(...)");
3040 break;
3042 case D3DRS_LOCALVIEWER :
3044 GLint state = (Value) ? 1 : 0;
3045 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3046 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3048 break;
3050 case D3DRS_LASTPIXEL :
3052 if (Value) {
3053 TRACE("Last Pixel Drawing Enabled\n");
3054 } else {
3055 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3058 break;
3060 case D3DRS_SOFTWAREVERTEXPROCESSING :
3062 if (Value) {
3063 TRACE("Software Processing Enabled\n");
3064 } else {
3065 TRACE("Software Processing Disabled\n");
3068 break;
3070 /** not supported */
3071 case D3DRS_ZVISIBLE :
3073 LEAVE_GL();
3074 return D3DERR_INVALIDCALL;
3077 /* Unhandled yet...! */
3078 case D3DRS_EDGEANTIALIAS :
3080 if(Value) {
3081 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3082 glEnable(GL_BLEND);
3083 checkGLcall("glEnable GL_BLEND");
3084 glEnable(GL_LINE_SMOOTH);
3085 checkGLcall("glEnable Gl_LINE_SMOOTH");
3086 } else {
3087 glDisable(GL_BLEND);
3088 checkGLcall("glDisable GL_BLEND");
3089 glDisable(GL_LINE_SMOOTH);
3090 checkGLcall("glDisable GL_LINE_SMOOTH");
3092 break;
3094 case D3DRS_WRAP0 :
3095 case D3DRS_WRAP1 :
3096 case D3DRS_WRAP2 :
3097 case D3DRS_WRAP3 :
3098 case D3DRS_WRAP4 :
3099 case D3DRS_WRAP5 :
3100 case D3DRS_WRAP6 :
3101 case D3DRS_WRAP7 :
3103 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3104 break;
3106 case D3DRS_POINTSPRITEENABLE :
3108 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3109 TRACE("Point sprites not supported\n");
3110 break;
3114 * Point sprites are always enabled. Value controls texture coordinate
3115 * replacement mode. Must be set true for point sprites to use
3116 * textures.
3118 glEnable(GL_POINT_SPRITE_ARB);
3119 checkGLcall("glEnable GL_POINT_SPRITE_ARB");
3121 if (Value) {
3122 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
3123 } else {
3124 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
3126 break;
3128 case D3DRS_MULTISAMPLEANTIALIAS :
3130 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3131 TRACE("Multisample antialiasing not supported\n");
3132 break;
3135 if(Value) {
3136 glEnable(GL_MULTISAMPLE_ARB);
3137 checkGLcall("glEnable GL_MULTISAMPLE_ARB");
3138 } else {
3139 glDisable(GL_MULTISAMPLE_ARB);
3140 checkGLcall("glDisable GL_MULTISAMPLE_ARB");
3142 break;
3144 case D3DRS_MULTISAMPLEMASK :
3145 case D3DRS_PATCHEDGESTYLE :
3146 case D3DRS_PATCHSEGMENTS :
3147 case D3DRS_DEBUGMONITORTOKEN :
3148 case D3DRS_POSITIONORDER :
3149 case D3DRS_NORMALORDER :
3150 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3151 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3152 break;
3153 default:
3154 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3157 LEAVE_GL();
3159 return D3D_OK;
3161 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3162 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3163 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3164 *pValue = This->StateBlock->renderstate[State];
3165 return D3D_OK;
3167 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3168 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3170 TRACE("(%p)\n", This);
3172 return IDirect3DDeviceImpl_BeginStateBlock(This);
3174 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3175 IDirect3DStateBlockImpl* pSB;
3176 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3177 HRESULT res;
3179 TRACE("(%p)\n", This);
3181 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3182 *pToken = (DWORD) pSB;
3183 return res;
3186 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3187 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3188 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3190 TRACE("(%p)\n", This);
3192 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3195 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3196 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3197 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3199 TRACE("(%p)\n", This);
3201 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3203 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3204 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3205 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3207 TRACE("(%p)\n", This);
3209 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3212 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3213 IDirect3DStateBlockImpl* pSB;
3214 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3215 HRESULT res;
3217 TRACE("(%p) : for type %d\n", This, Type);
3219 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3220 *pToken = (DWORD) pSB;
3221 return res;
3224 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3225 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3226 FIXME("(%p) : stub\n", This);
3227 if (NULL == pClipStatus) {
3228 return D3DERR_INVALIDCALL;
3230 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3231 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3232 return D3D_OK;
3234 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3235 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3236 FIXME("(%p) : stub\n", This);
3237 if (NULL == pClipStatus) {
3238 return D3DERR_INVALIDCALL;
3240 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3241 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3242 return D3D_OK;
3244 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3245 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3246 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3247 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3248 if (*ppTexture)
3249 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3250 return D3D_OK;
3252 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3254 IDirect3DBaseTexture8 *oldTxt;
3255 BOOL reapplyStates = TRUE;
3256 INT oldTextureDimensions = -1;
3257 DWORD reapplyFlags = 0;
3259 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3260 D3DRESOURCETYPE textureType;
3262 oldTxt = This->UpdateStateBlock->textures[Stage];
3263 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3265 /* Reject invalid texture units */
3266 if (Stage >= GL_LIMITS(textures)) {
3267 TRACE("Attempt to access invalid texture rejected\n");
3268 return D3DERR_INVALIDCALL;
3271 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3272 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3273 This->UpdateStateBlock->textures[Stage] = pTexture;
3275 /* Handle recording of state blocks */
3276 if (This->isRecordingState) {
3277 TRACE("Recording... not performing anything\n");
3278 return D3D_OK;
3281 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3282 ENTER_GL();
3284 /* Make appropriate texture active */
3285 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3286 #if defined(GL_VERSION_1_3)
3287 glActiveTexture(GL_TEXTURE0 + Stage);
3288 checkGLcall("glActiveTexture");
3289 #else
3290 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3291 checkGLcall("glActiveTextureARB");
3292 #endif
3293 } else if (Stage>0) {
3294 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3297 /* Decrement the count of the previous texture */
3298 if (NULL != oldTxt) {
3299 IDirect3DBaseTexture8Impl_Release(oldTxt);
3302 if (NULL != pTexture) {
3303 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3305 /* Now setup the texture appropraitly */
3306 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3308 if (textureType == D3DRTYPE_TEXTURE) {
3309 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3310 TRACE("Skipping setting texture as old == new\n");
3311 reapplyStates = FALSE;
3312 } else {
3313 /* Standard 2D texture */
3314 TRACE("Standard 2d texture\n");
3315 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3317 /* Load up the texture now */
3318 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3320 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3321 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3322 TRACE("Skipping setting texture as old == new\n");
3323 reapplyStates = FALSE;
3324 } else {
3325 /* Standard 3D (volume) texture */
3326 TRACE("Standard 3d texture\n");
3327 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3329 /* Load up the texture now */
3330 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3332 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3333 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3334 TRACE("Skipping setting texture as old == new\n");
3335 reapplyStates = FALSE;
3336 } else {
3337 /* Standard Cube texture */
3338 TRACE("Standard Cube texture\n");
3339 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3341 /* Load up the texture now */
3342 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3344 } else {
3345 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3347 } else {
3348 TRACE("Setting to no texture (ie default texture)\n");
3349 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3350 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3351 checkGLcall("glBindTexture");
3352 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3355 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3356 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3357 glDisable(oldTextureDimensions);
3358 checkGLcall("Disable oldTextureDimensions");
3359 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3360 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3361 checkGLcall("glEnable new texture dimensions");
3364 /* If Alpha arg1 is texture then handle the special case when there changes between a
3365 texture and no texture - See comments in set_tex_op */
3366 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3367 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3369 reapplyFlags |= REAPPLY_ALPHAOP;
3374 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3375 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3376 if (reapplyStates) {
3377 setupTextureStates(iface, Stage, reapplyFlags);
3380 LEAVE_GL();
3382 return D3D_OK;
3385 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3386 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3387 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3388 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3389 return D3D_OK;
3392 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3393 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3394 union {
3395 float f;
3396 DWORD d;
3397 } tmpvalue;
3399 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3401 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3403 /* Reject invalid texture units */
3404 if (Stage >= GL_LIMITS(textures)) {
3405 TRACE("Attempt to access invalid texture rejected\n");
3406 return D3DERR_INVALIDCALL;
3409 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3410 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3411 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3413 /* Handle recording of state blocks */
3414 if (This->isRecordingState) {
3415 TRACE("Recording... not performing anything\n");
3416 return D3D_OK;
3419 ENTER_GL();
3421 /* Make appropriate texture active */
3422 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3423 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3424 #if defined(GL_VERSION_1_3)
3425 glActiveTexture(GL_TEXTURE0 + Stage);
3426 vcheckGLcall("glActiveTexture");
3427 #else
3428 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3429 vcheckGLcall("glActiveTextureARB");
3430 #endif
3431 } else if (Stage > 0) {
3432 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3435 switch (Type) {
3437 case D3DTSS_MINFILTER :
3438 case D3DTSS_MIPFILTER :
3440 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3441 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3442 GLint realVal = GL_LINEAR;
3444 if (ValueMIN == D3DTEXF_NONE) {
3445 /* Doesn't really make sense - Windows just seems to disable
3446 mipmapping when this occurs */
3447 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3448 realVal = GL_LINEAR;
3449 } else if (ValueMIN == D3DTEXF_POINT) {
3450 /* GL_NEAREST_* */
3451 if (ValueMIP == D3DTEXF_NONE) {
3452 realVal = GL_NEAREST;
3453 } else if (ValueMIP == D3DTEXF_POINT) {
3454 realVal = GL_NEAREST_MIPMAP_NEAREST;
3455 } else if (ValueMIP == D3DTEXF_LINEAR) {
3456 realVal = GL_NEAREST_MIPMAP_LINEAR;
3457 } else {
3458 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3459 realVal = GL_NEAREST;
3461 } else if (ValueMIN == D3DTEXF_LINEAR) {
3462 /* GL_LINEAR_* */
3463 if (ValueMIP == D3DTEXF_NONE) {
3464 realVal = GL_LINEAR;
3465 } else if (ValueMIP == D3DTEXF_POINT) {
3466 realVal = GL_LINEAR_MIPMAP_NEAREST;
3467 } else if (ValueMIP == D3DTEXF_LINEAR) {
3468 realVal = GL_LINEAR_MIPMAP_LINEAR;
3469 } else {
3470 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3471 realVal = GL_LINEAR;
3473 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3474 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3475 if (ValueMIP == D3DTEXF_NONE) {
3476 realVal = GL_LINEAR_MIPMAP_LINEAR;
3477 } else if (ValueMIP == D3DTEXF_POINT) {
3478 realVal = GL_LINEAR_MIPMAP_NEAREST;
3479 } else if (ValueMIP == D3DTEXF_LINEAR) {
3480 realVal = GL_LINEAR_MIPMAP_LINEAR;
3481 } else {
3482 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3483 realVal = GL_LINEAR;
3485 } else {
3486 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3487 realVal = GL_LINEAR;
3489 } else {
3490 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3491 realVal = GL_LINEAR_MIPMAP_LINEAR;
3494 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3495 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3496 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3498 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3500 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3501 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3502 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3503 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3504 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3507 break;
3509 case D3DTSS_MAGFILTER :
3511 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3512 GLint realVal = GL_NEAREST;
3514 if (ValueMAG == D3DTEXF_POINT) {
3515 realVal = GL_NEAREST;
3516 } else if (ValueMAG == D3DTEXF_LINEAR) {
3517 realVal = GL_LINEAR;
3518 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3519 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3520 realVal = GL_LINEAR;
3521 } else {
3522 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3523 realVal = GL_NEAREST;
3525 } else {
3526 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3527 realVal = GL_NEAREST;
3529 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3530 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3531 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3533 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3535 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3536 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3537 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3538 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3539 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3542 break;
3544 case D3DTSS_MAXMIPLEVEL :
3547 * Not really the same, but the more apprioprate than nothing
3549 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3550 GL_TEXTURE_BASE_LEVEL,
3551 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3552 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3554 break;
3556 case D3DTSS_MAXANISOTROPY :
3558 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3559 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3560 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3561 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3562 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3565 break;
3567 case D3DTSS_MIPMAPLODBIAS :
3569 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3570 tmpvalue.d = Value;
3571 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3572 GL_TEXTURE_LOD_BIAS_EXT,
3573 tmpvalue.f);
3574 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3577 break;
3579 case D3DTSS_ALPHAOP :
3580 case D3DTSS_COLOROP :
3583 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3584 /* TODO: Disable by making this and all later levels disabled */
3585 glDisable(GL_TEXTURE_1D);
3586 checkGLcall("Disable GL_TEXTURE_1D");
3587 glDisable(GL_TEXTURE_2D);
3588 checkGLcall("Disable GL_TEXTURE_2D");
3589 glDisable(GL_TEXTURE_3D);
3590 checkGLcall("Disable GL_TEXTURE_3D");
3591 break; /* Don't bother setting the texture operations */
3592 } else {
3593 /* Enable only the appropriate texture dimension */
3594 if (Type == D3DTSS_COLOROP) {
3595 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3596 glEnable(GL_TEXTURE_1D);
3597 checkGLcall("Enable GL_TEXTURE_1D");
3598 } else {
3599 glDisable(GL_TEXTURE_1D);
3600 checkGLcall("Disable GL_TEXTURE_1D");
3602 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3603 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3604 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3605 checkGLcall("Enable GL_TEXTURE_2D");
3606 } else {
3607 glEnable(GL_TEXTURE_2D);
3608 checkGLcall("Enable GL_TEXTURE_2D");
3610 } else {
3611 glDisable(GL_TEXTURE_2D);
3612 checkGLcall("Disable GL_TEXTURE_2D");
3614 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3615 glEnable(GL_TEXTURE_3D);
3616 checkGLcall("Enable GL_TEXTURE_3D");
3617 } else {
3618 glDisable(GL_TEXTURE_3D);
3619 checkGLcall("Disable GL_TEXTURE_3D");
3621 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3622 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3623 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3624 } else {
3625 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3626 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3630 /* Drop through... (Except disable case) */
3631 case D3DTSS_COLORARG0 :
3632 case D3DTSS_COLORARG1 :
3633 case D3DTSS_COLORARG2 :
3634 case D3DTSS_ALPHAARG0 :
3635 case D3DTSS_ALPHAARG1 :
3636 case D3DTSS_ALPHAARG2 :
3638 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3639 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3640 if (isAlphaArg) {
3641 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3642 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3643 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3644 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3645 } else {
3646 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3647 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3648 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3649 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3652 break;
3655 case D3DTSS_ADDRESSU :
3656 case D3DTSS_ADDRESSV :
3657 case D3DTSS_ADDRESSW :
3659 GLint wrapParm = GL_REPEAT;
3661 switch (Value) {
3662 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3663 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3664 case D3DTADDRESS_BORDER:
3666 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3667 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3668 } else {
3669 /* FIXME: Not right, but better */
3670 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3671 wrapParm = GL_REPEAT;
3674 break;
3675 case D3DTADDRESS_MIRROR:
3677 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3678 wrapParm = GL_MIRRORED_REPEAT_ARB;
3679 } else {
3680 /* Unsupported in OpenGL pre-1.4 */
3681 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3682 wrapParm = GL_REPEAT;
3685 break;
3686 case D3DTADDRESS_MIRRORONCE:
3688 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3689 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3690 } else {
3691 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3692 wrapParm = GL_REPEAT;
3695 break;
3697 default:
3698 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3699 wrapParm = GL_REPEAT;
3702 switch (Type) {
3703 case D3DTSS_ADDRESSU:
3704 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3705 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3706 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3707 break;
3708 case D3DTSS_ADDRESSV:
3709 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3710 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3711 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3712 break;
3713 case D3DTSS_ADDRESSW:
3714 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3715 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3716 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3717 break;
3718 default: /* nop */
3719 break; /** stupic compilator */
3722 break;
3724 case D3DTSS_BORDERCOLOR :
3726 float col[4];
3727 D3DCOLORTOGLFLOAT4(Value, col);
3728 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3729 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3730 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3732 break;
3734 case D3DTSS_TEXCOORDINDEX :
3736 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3738 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3739 one flag, you can still specify an index value, which the system uses to
3740 determine the texture wrapping mode.
3741 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3742 means use the vertex position (camera-space) as the input texture coordinates
3743 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3744 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3745 to the TEXCOORDINDEX value */
3747 /**
3748 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3750 switch (Value & 0xFFFF0000) {
3751 case D3DTSS_TCI_PASSTHRU:
3752 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3753 glDisable(GL_TEXTURE_GEN_S);
3754 glDisable(GL_TEXTURE_GEN_T);
3755 glDisable(GL_TEXTURE_GEN_R);
3756 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3757 break;
3759 case D3DTSS_TCI_CAMERASPACEPOSITION:
3760 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3761 as the input texture coordinates for this stage's texture transformation. This
3762 equates roughly to EYE_LINEAR */
3764 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3765 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3766 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3767 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3768 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3770 glMatrixMode(GL_MODELVIEW);
3771 glPushMatrix();
3772 glLoadIdentity();
3773 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3774 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3775 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3776 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3777 glPopMatrix();
3779 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3780 glEnable(GL_TEXTURE_GEN_S);
3781 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3782 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3783 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3784 glEnable(GL_TEXTURE_GEN_T);
3785 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3786 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3787 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3788 glEnable(GL_TEXTURE_GEN_R);
3789 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3790 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3791 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3793 break;
3795 case D3DTSS_TCI_CAMERASPACENORMAL:
3797 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3798 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3799 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3800 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3801 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3802 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3804 glMatrixMode(GL_MODELVIEW);
3805 glPushMatrix();
3806 glLoadIdentity();
3807 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3808 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3809 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3810 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3811 glPopMatrix();
3813 glEnable(GL_TEXTURE_GEN_S);
3814 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3815 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3816 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3817 glEnable(GL_TEXTURE_GEN_T);
3818 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3819 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3820 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3821 glEnable(GL_TEXTURE_GEN_R);
3822 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3823 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3824 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3827 break;
3829 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3831 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3832 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3833 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3834 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3835 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3836 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3838 glMatrixMode(GL_MODELVIEW);
3839 glPushMatrix();
3840 glLoadIdentity();
3841 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3842 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3843 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3844 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3845 glPopMatrix();
3847 glEnable(GL_TEXTURE_GEN_S);
3848 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3849 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3850 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3851 glEnable(GL_TEXTURE_GEN_T);
3852 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3853 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3854 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3855 glEnable(GL_TEXTURE_GEN_R);
3856 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3857 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3858 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3861 break;
3863 /* Unhandled types: */
3864 default:
3865 /* Todo: */
3866 /* ? disable GL_TEXTURE_GEN_n ? */
3867 glDisable(GL_TEXTURE_GEN_S);
3868 glDisable(GL_TEXTURE_GEN_T);
3869 glDisable(GL_TEXTURE_GEN_R);
3870 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3871 break;
3874 break;
3876 /* Unhandled */
3877 case D3DTSS_TEXTURETRANSFORMFLAGS :
3878 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3879 break;
3881 case D3DTSS_BUMPENVMAT00 :
3882 case D3DTSS_BUMPENVMAT01 :
3883 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3884 break;
3885 case D3DTSS_BUMPENVMAT10 :
3886 case D3DTSS_BUMPENVMAT11 :
3887 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3888 break;
3890 case D3DTSS_BUMPENVLSCALE :
3891 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3892 break;
3894 case D3DTSS_BUMPENVLOFFSET :
3895 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3896 break;
3898 case D3DTSS_RESULTARG :
3899 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3900 break;
3902 default:
3903 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3904 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3907 LEAVE_GL();
3909 return D3D_OK;
3911 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3912 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3913 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3914 return D3D_OK;
3916 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3917 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3918 FIXME("(%p) : stub\n", This);
3919 return D3D_OK;
3921 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3922 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3923 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3924 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3925 if (PaletteNumber >= MAX_PALETTES) {
3926 return D3DERR_INVALIDCALL;
3928 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3929 return D3D_OK;
3931 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3932 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3933 if (PaletteNumber >= MAX_PALETTES) {
3934 return D3DERR_INVALIDCALL;
3936 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3937 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3938 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3939 return D3D_OK;
3941 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3942 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3943 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3944 if (PaletteNumber >= MAX_PALETTES) {
3945 return D3DERR_INVALIDCALL;
3947 This->currentPalette = PaletteNumber;
3949 #if defined(GL_EXT_paletted_texture)
3950 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3952 ENTER_GL();
3954 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3955 GL_RGBA, /* internal format */
3956 256, /* table size */
3957 GL_RGBA, /* table format */
3958 GL_UNSIGNED_BYTE, /* table type */
3959 This->palettes[PaletteNumber]);
3960 checkGLcall("glColorTableEXT");
3962 LEAVE_GL();
3964 } else {
3965 /* Delayed palette handling ... waiting for software emulation into preload code */
3967 #endif
3968 return D3D_OK;
3970 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3971 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3972 *PaletteNumber = This->currentPalette;
3973 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3974 return D3D_OK;
3976 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3978 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3979 This->StateBlock->streamIsUP = FALSE;
3981 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3982 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3984 return D3D_OK;
3986 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3987 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3988 UINT idxStride = 2;
3989 IDirect3DIndexBuffer8 *pIB;
3990 D3DINDEXBUFFER_DESC IdxBufDsc;
3992 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3993 pIB = This->StateBlock->pIndexData;
3994 This->StateBlock->streamIsUP = FALSE;
3996 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
3997 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3998 minIndex, NumVertices, startIndex, primCount);
4000 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
4001 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
4002 idxStride = 2;
4003 } else {
4004 idxStride = 4;
4007 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
4008 minIndex);
4010 return D3D_OK;
4012 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
4013 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4015 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4016 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4018 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4020 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
4021 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
4022 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4023 This->StateBlock->streamIsUP = TRUE;
4024 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4025 This->StateBlock->stream_stride[0] = 0;
4026 This->StateBlock->stream_source[0] = NULL;
4028 /*stream zero settings set to null at end */
4029 return D3D_OK;
4031 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4032 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4033 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4034 UINT VertexStreamZeroStride) {
4035 int idxStride;
4036 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4037 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),
4038 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4040 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4041 if (IndexDataFormat == D3DFMT_INDEX16) {
4042 idxStride = 2;
4043 } else {
4044 idxStride = 4;
4047 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
4048 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
4049 This->StateBlock->streamIsUP = TRUE;
4050 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4051 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4053 /*stream zero settings set to null at end */
4054 This->StateBlock->stream_source[0] = NULL;
4055 This->StateBlock->stream_stride[0] = 0;
4056 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4058 return D3D_OK;
4060 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4061 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4062 FIXME("(%p) : stub\n", This); return D3D_OK;
4064 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4065 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4066 IDirect3DVertexShaderImpl* object;
4067 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4068 HRESULT res;
4069 UINT i;
4071 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
4072 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4073 return D3DERR_INVALIDCALL;
4075 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4076 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4077 return D3DERR_OUTOFVIDEOMEMORY;
4080 /** Create the Vertex Shader */
4081 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4082 /** TODO: check FAILED(res) */
4084 /** Create and Bind the Vertex Shader Declaration */
4085 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4086 /** TODO: check FAILED(res) */
4088 VertexShaders[i] = object;
4089 VertexShaderDeclarations[i] = attached_decl;
4090 *pHandle = VS_HIGHESTFIXEDFXF + i;
4091 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4093 return D3D_OK;
4095 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4096 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4098 This->UpdateStateBlock->VertexShader = Handle;
4099 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4100 This->UpdateStateBlock->Set.vertexShader = TRUE;
4102 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4103 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4104 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4105 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4106 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4107 } else { /* use a fvf, so desactivate the vshader decl */
4108 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4109 This->UpdateStateBlock->vertexShaderDecl = NULL;
4110 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4111 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4113 /* Handle recording of state blocks */
4114 if (This->isRecordingState) {
4115 TRACE("Recording... not performing anything\n");
4116 return D3D_OK;
4119 * TODO: merge HAL shaders context switching from prototype
4121 return D3D_OK;
4123 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4124 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4125 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4126 *pHandle = This->StateBlock->VertexShader;
4127 return D3D_OK;
4130 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4131 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4132 IDirect3DVertexShaderImpl* object;
4133 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4135 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4136 return D3DERR_INVALIDCALL;
4140 * Delete Vertex Shader
4142 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4143 if (NULL == object) {
4144 return D3DERR_INVALIDCALL;
4146 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4147 /* TODO: check validity of object */
4148 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4149 if (object->prgId != 0) {
4150 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4152 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4153 HeapFree(GetProcessHeap(), 0, (void *)object);
4154 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4157 * Delete Vertex Shader Declaration
4159 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4160 if (NULL == attached_decl) {
4161 return D3DERR_INVALIDCALL;
4163 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4164 /* TODO: check validity of object */
4165 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4166 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4167 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4169 return D3D_OK;
4172 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4173 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4175 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4176 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4177 return D3DERR_INVALIDCALL;
4179 if (NULL == pConstantData) {
4180 return D3DERR_INVALIDCALL;
4182 if (ConstantCount > 1) {
4183 const FLOAT* f = (const FLOAT*)pConstantData;
4184 UINT i;
4185 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4186 for (i = 0; i < ConstantCount; ++i) {
4187 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4188 f += 4;
4190 } else {
4191 const FLOAT* f = (const FLOAT*) pConstantData;
4192 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4194 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4195 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4196 return D3D_OK;
4198 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4199 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4201 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4202 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4203 return D3DERR_INVALIDCALL;
4205 if (NULL == pConstantData) {
4206 return D3DERR_INVALIDCALL;
4208 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4209 return D3D_OK;
4211 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4212 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4213 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4215 attached_decl = VERTEX_SHADER_DECL(Handle);
4216 if (NULL == attached_decl) {
4217 return D3DERR_INVALIDCALL;
4219 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4221 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4222 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4223 IDirect3DVertexShaderImpl* object;
4225 object = VERTEX_SHADER(Handle);
4226 if (NULL == object) {
4227 return D3DERR_INVALIDCALL;
4229 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4232 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4233 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4234 IDirect3DIndexBuffer8 *oldIdxs;
4236 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4237 oldIdxs = This->StateBlock->pIndexData;
4239 This->UpdateStateBlock->Changed.Indices = TRUE;
4240 This->UpdateStateBlock->Set.Indices = TRUE;
4241 This->UpdateStateBlock->pIndexData = pIndexData;
4242 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4244 /* Handle recording of state blocks */
4245 if (This->isRecordingState) {
4246 TRACE("Recording... not performing anything\n");
4247 return D3D_OK;
4250 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRefInt(This->StateBlock->pIndexData);
4251 if (oldIdxs) IDirect3DIndexBuffer8Impl_ReleaseInt(oldIdxs);
4252 return D3D_OK;
4254 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4255 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4256 FIXME("(%p) : stub\n", This);
4258 *ppIndexData = This->StateBlock->pIndexData;
4259 /* up ref count on ppindexdata */
4260 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4261 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4263 return D3D_OK;
4265 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4266 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4267 IDirect3DPixelShaderImpl* object;
4268 HRESULT res;
4269 UINT i;
4271 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4272 if (NULL == pFunction || NULL == pHandle) {
4273 return D3DERR_INVALIDCALL;
4275 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4276 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4277 return D3DERR_OUTOFVIDEOMEMORY;
4280 /** Create the Pixel Shader */
4281 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4282 if (SUCCEEDED(res)) {
4283 PixelShaders[i] = object;
4284 *pHandle = VS_HIGHESTFIXEDFXF + i;
4285 return D3D_OK;
4287 *pHandle = 0xFFFFFFFF;
4288 return res;
4291 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4292 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4294 This->UpdateStateBlock->PixelShader = Handle;
4295 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4296 This->UpdateStateBlock->Set.pixelShader = TRUE;
4298 /* Handle recording of state blocks */
4299 if (This->isRecordingState) {
4300 TRACE_(d3d_shader)("Recording... not performing anything\n");
4301 return D3D_OK;
4304 if (Handle != 0) {
4305 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4306 } else {
4307 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4310 return D3D_OK;
4313 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4314 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4315 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4316 *pHandle = This->StateBlock->PixelShader;
4317 return D3D_OK;
4320 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4321 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4322 IDirect3DPixelShaderImpl* object;
4324 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4325 return D3DERR_INVALIDCALL;
4327 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4328 if (NULL == object) {
4329 return D3DERR_INVALIDCALL;
4331 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4332 /* TODO: check validity of object before free */
4333 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4334 if (object->prgId != 0) {
4335 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4337 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4338 HeapFree(GetProcessHeap(), 0, (void *)object);
4339 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4341 return D3D_OK;
4344 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4345 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4347 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4348 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4349 return D3DERR_INVALIDCALL;
4351 if (NULL == pConstantData) {
4352 return D3DERR_INVALIDCALL;
4354 if (ConstantCount > 1) {
4355 const FLOAT* f = (const FLOAT*)pConstantData;
4356 UINT i;
4357 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4358 for (i = 0; i < ConstantCount; ++i) {
4359 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4360 f += 4;
4362 } else {
4363 const FLOAT* f = (const FLOAT*) pConstantData;
4364 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4366 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4367 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4368 return D3D_OK;
4370 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4371 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4373 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4374 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4375 return D3DERR_INVALIDCALL;
4377 if (NULL == pConstantData) {
4378 return D3DERR_INVALIDCALL;
4380 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4381 return D3D_OK;
4383 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4384 IDirect3DPixelShaderImpl* object;
4386 object = PIXEL_SHADER(Handle);
4387 if (NULL == object) {
4388 return D3DERR_INVALIDCALL;
4390 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4392 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4393 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4394 FIXME("(%p) : stub\n", This); return D3D_OK;
4396 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4397 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4398 FIXME("(%p) : stub\n", This); return D3D_OK;
4400 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4401 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4402 FIXME("(%p) : stub\n", This); return D3D_OK;
4405 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4406 IDirect3DVertexBuffer8 *oldSrc;
4407 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4409 oldSrc = This->StateBlock->stream_source[StreamNumber];
4410 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4412 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4413 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4414 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4415 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4417 /* Handle recording of state blocks */
4418 if (This->isRecordingState) {
4419 TRACE("Recording... not performing anything\n");
4420 return D3D_OK;
4423 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRefInt(pStreamData);
4424 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_ReleaseInt(oldSrc);
4425 return D3D_OK;
4427 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4428 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4429 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4430 *pStream = This->StateBlock->stream_source[StreamNumber];
4431 *pStride = This->StateBlock->stream_stride[StreamNumber];
4432 if (*pStream != NULL) IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4433 return D3D_OK;
4437 const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4439 IDirect3DDevice8Impl_QueryInterface,
4440 IDirect3DDevice8Impl_AddRef,
4441 IDirect3DDevice8Impl_Release,
4442 IDirect3DDevice8Impl_TestCooperativeLevel,
4443 IDirect3DDevice8Impl_GetAvailableTextureMem,
4444 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4445 IDirect3DDevice8Impl_GetDirect3D,
4446 IDirect3DDevice8Impl_GetDeviceCaps,
4447 IDirect3DDevice8Impl_GetDisplayMode,
4448 IDirect3DDevice8Impl_GetCreationParameters,
4449 IDirect3DDevice8Impl_SetCursorProperties,
4450 IDirect3DDevice8Impl_SetCursorPosition,
4451 IDirect3DDevice8Impl_ShowCursor,
4452 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4453 IDirect3DDevice8Impl_Reset,
4454 IDirect3DDevice8Impl_Present,
4455 IDirect3DDevice8Impl_GetBackBuffer,
4456 IDirect3DDevice8Impl_GetRasterStatus,
4457 IDirect3DDevice8Impl_SetGammaRamp,
4458 IDirect3DDevice8Impl_GetGammaRamp,
4459 IDirect3DDevice8Impl_CreateTexture,
4460 IDirect3DDevice8Impl_CreateVolumeTexture,
4461 IDirect3DDevice8Impl_CreateCubeTexture,
4462 IDirect3DDevice8Impl_CreateVertexBuffer,
4463 IDirect3DDevice8Impl_CreateIndexBuffer,
4464 IDirect3DDevice8Impl_CreateRenderTarget,
4465 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4466 IDirect3DDevice8Impl_CreateImageSurface,
4467 IDirect3DDevice8Impl_CopyRects,
4468 IDirect3DDevice8Impl_UpdateTexture,
4469 IDirect3DDevice8Impl_GetFrontBuffer,
4470 IDirect3DDevice8Impl_SetRenderTarget,
4471 IDirect3DDevice8Impl_GetRenderTarget,
4472 IDirect3DDevice8Impl_GetDepthStencilSurface,
4473 IDirect3DDevice8Impl_BeginScene,
4474 IDirect3DDevice8Impl_EndScene,
4475 IDirect3DDevice8Impl_Clear,
4476 IDirect3DDevice8Impl_SetTransform,
4477 IDirect3DDevice8Impl_GetTransform,
4478 IDirect3DDevice8Impl_MultiplyTransform,
4479 IDirect3DDevice8Impl_SetViewport,
4480 IDirect3DDevice8Impl_GetViewport,
4481 IDirect3DDevice8Impl_SetMaterial,
4482 IDirect3DDevice8Impl_GetMaterial,
4483 IDirect3DDevice8Impl_SetLight,
4484 IDirect3DDevice8Impl_GetLight,
4485 IDirect3DDevice8Impl_LightEnable,
4486 IDirect3DDevice8Impl_GetLightEnable,
4487 IDirect3DDevice8Impl_SetClipPlane,
4488 IDirect3DDevice8Impl_GetClipPlane,
4489 IDirect3DDevice8Impl_SetRenderState,
4490 IDirect3DDevice8Impl_GetRenderState,
4491 IDirect3DDevice8Impl_BeginStateBlock,
4492 IDirect3DDevice8Impl_EndStateBlock,
4493 IDirect3DDevice8Impl_ApplyStateBlock,
4494 IDirect3DDevice8Impl_CaptureStateBlock,
4495 IDirect3DDevice8Impl_DeleteStateBlock,
4496 IDirect3DDevice8Impl_CreateStateBlock,
4497 IDirect3DDevice8Impl_SetClipStatus,
4498 IDirect3DDevice8Impl_GetClipStatus,
4499 IDirect3DDevice8Impl_GetTexture,
4500 IDirect3DDevice8Impl_SetTexture,
4501 IDirect3DDevice8Impl_GetTextureStageState,
4502 IDirect3DDevice8Impl_SetTextureStageState,
4503 IDirect3DDevice8Impl_ValidateDevice,
4504 IDirect3DDevice8Impl_GetInfo,
4505 IDirect3DDevice8Impl_SetPaletteEntries,
4506 IDirect3DDevice8Impl_GetPaletteEntries,
4507 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4508 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4509 IDirect3DDevice8Impl_DrawPrimitive,
4510 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4511 IDirect3DDevice8Impl_DrawPrimitiveUP,
4512 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4513 IDirect3DDevice8Impl_ProcessVertices,
4514 IDirect3DDevice8Impl_CreateVertexShader,
4515 IDirect3DDevice8Impl_SetVertexShader,
4516 IDirect3DDevice8Impl_GetVertexShader,
4517 IDirect3DDevice8Impl_DeleteVertexShader,
4518 IDirect3DDevice8Impl_SetVertexShaderConstant,
4519 IDirect3DDevice8Impl_GetVertexShaderConstant,
4520 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4521 IDirect3DDevice8Impl_GetVertexShaderFunction,
4522 IDirect3DDevice8Impl_SetStreamSource,
4523 IDirect3DDevice8Impl_GetStreamSource,
4524 IDirect3DDevice8Impl_SetIndices,
4525 IDirect3DDevice8Impl_GetIndices,
4526 IDirect3DDevice8Impl_CreatePixelShader,
4527 IDirect3DDevice8Impl_SetPixelShader,
4528 IDirect3DDevice8Impl_GetPixelShader,
4529 IDirect3DDevice8Impl_DeletePixelShader,
4530 IDirect3DDevice8Impl_SetPixelShaderConstant,
4531 IDirect3DDevice8Impl_GetPixelShaderConstant,
4532 IDirect3DDevice8Impl_GetPixelShaderFunction,
4533 IDirect3DDevice8Impl_DrawRectPatch,
4534 IDirect3DDevice8Impl_DrawTriPatch,
4535 IDirect3DDevice8Impl_DeletePatch
4538 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4540 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4541 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4543 ENTER_GL();
4545 #if 0
4546 if (This->glCtx != This->render_ctx) {
4547 glXDestroyContext(This->display, This->render_ctx);
4548 This->render_ctx = This->glCtx;
4550 #endif
4551 if (This->win != This->drawable) {
4552 glXDestroyPbuffer(This->display, This->drawable);
4553 This->drawable = This->win;
4556 LEAVE_GL();
4558 #endif
4559 return D3D_OK;
4562 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4563 IDirect3DSurface8* RenderSurface,
4564 IDirect3DSurface8* StencilSurface) {
4566 HRESULT ret = D3DERR_INVALIDCALL;
4568 * Currently only active for GLX >= 1.3
4569 * for others versions we'll have to use GLXPixmaps
4571 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4572 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4573 * so only check OpenGL version
4575 #if defined(GL_VERSION_1_3)
4576 GLXFBConfig* cfgs = NULL;
4577 int nCfgs = 0;
4578 int attribs[256];
4579 int nAttribs = 0;
4580 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4581 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4582 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4583 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4584 IDirect3DSurface8Impl* tmp;
4586 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4588 #define PUSH1(att) attribs[nAttribs++] = (att);
4589 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4591 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4592 PUSH2(GLX_X_RENDERABLE, TRUE);
4593 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4595 switch (BackBufferFormat) {
4596 /* color buffer */
4597 case D3DFMT_P8:
4598 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4599 PUSH2(GLX_BUFFER_SIZE, 8);
4600 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4601 break;
4603 case D3DFMT_R3G3B2:
4604 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4605 PUSH2(GLX_RED_SIZE, 3);
4606 PUSH2(GLX_GREEN_SIZE, 3);
4607 PUSH2(GLX_BLUE_SIZE, 2);
4608 break;
4610 case D3DFMT_A1R5G5B5:
4611 PUSH2(GLX_ALPHA_SIZE, 1);
4612 case D3DFMT_X1R5G5B5:
4613 PUSH2(GLX_RED_SIZE, 5);
4614 PUSH2(GLX_GREEN_SIZE, 5);
4615 PUSH2(GLX_BLUE_SIZE, 5);
4616 break;
4618 case D3DFMT_R5G6B5:
4619 PUSH2(GLX_RED_SIZE, 5);
4620 PUSH2(GLX_GREEN_SIZE, 6);
4621 PUSH2(GLX_BLUE_SIZE, 5);
4622 break;
4624 case D3DFMT_A4R4G4B4:
4625 PUSH2(GLX_ALPHA_SIZE, 4);
4626 case D3DFMT_X4R4G4B4:
4627 PUSH2(GLX_RED_SIZE, 4);
4628 PUSH2(GLX_GREEN_SIZE, 4);
4629 PUSH2(GLX_BLUE_SIZE, 4);
4630 break;
4632 case D3DFMT_A8R8G8B8:
4633 PUSH2(GLX_ALPHA_SIZE, 8);
4634 case D3DFMT_R8G8B8:
4635 case D3DFMT_X8R8G8B8:
4636 PUSH2(GLX_RED_SIZE, 8);
4637 PUSH2(GLX_GREEN_SIZE, 8);
4638 PUSH2(GLX_BLUE_SIZE, 8);
4639 break;
4641 default:
4642 break;
4645 switch (StencilBufferFormat) {
4646 case D3DFMT_D16_LOCKABLE:
4647 case D3DFMT_D16:
4648 PUSH2(GLX_DEPTH_SIZE, 16);
4649 break;
4651 case D3DFMT_D15S1:
4652 PUSH2(GLX_DEPTH_SIZE, 15);
4653 break;
4655 case D3DFMT_D24X8:
4656 PUSH2(GLX_DEPTH_SIZE, 24);
4657 break;
4659 case D3DFMT_D24X4S4:
4660 PUSH2(GLX_DEPTH_SIZE, 24);
4661 PUSH2(GLX_STENCIL_SIZE, 4);
4662 break;
4664 case D3DFMT_D24S8:
4665 PUSH2(GLX_DEPTH_SIZE, 24);
4666 PUSH2(GLX_STENCIL_SIZE, 8);
4667 break;
4669 case D3DFMT_D32:
4670 PUSH2(GLX_DEPTH_SIZE, 24);
4671 break;
4673 default:
4674 break;
4677 PUSH1(None);
4679 ENTER_GL();
4681 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4682 if (NULL != cfgs) {
4683 #ifdef EXTRA_TRACES
4684 int i;
4685 for (i = 0; i < nCfgs; ++i) {
4686 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4688 #endif
4690 if (NULL != This->renderTarget) {
4691 /*GLenum prev_read; */
4692 glFlush();
4693 vcheckGLcall("glFlush");
4695 #ifdef EXTRA_TRACES
4696 /** very very useful debug code */
4697 glXSwapBuffers(This->display, This->drawable);
4698 printf("Hit Enter to get next frame ...\n");
4699 getchar();
4700 #endif
4702 #if 0
4703 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4704 vcheckGLcall("glIntegerv");
4705 glReadBuffer(GL_BACK);
4706 vcheckGLcall("glReadBuffer");
4708 long j;
4709 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4711 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4712 pitch = pitch / 2;
4714 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4715 glReadPixels(0,
4716 This->renderTarget->myDesc.Height - j - 1,
4717 This->renderTarget->myDesc.Width,
4719 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4720 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4721 This->renderTarget->allocatedMemory + j * pitch);
4722 vcheckGLcall("glReadPixels");
4725 glReadBuffer(prev_read);
4726 vcheckGLcall("glReadBuffer");
4727 #endif
4730 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4731 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4732 nAttribs = 0;
4733 PUSH2(GLX_PBUFFER_WIDTH, Width);
4734 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4735 PUSH1(None);
4736 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4738 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4739 if (NULL == This->render_ctx) {
4740 ERR("cannot create glxContext\n");
4743 glFlush();
4744 glXSwapBuffers(This->display, This->drawable);
4745 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4746 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4748 checkGLcall("glXMakeContextCurrent");
4751 tmp = This->renderTarget;
4752 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4753 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4754 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4756 tmp = This->stencilBufferTarget;
4757 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4758 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4759 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4762 DWORD value;
4763 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4764 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4765 /* Force updating the cull mode */
4766 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4767 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4768 /* Force updating projection matrix */
4769 This->last_was_rhw = FALSE;
4770 This->proj_valid = FALSE;
4773 ret = D3D_OK;
4775 } else {
4776 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4779 #undef PUSH1
4780 #undef PUSH2
4782 LEAVE_GL();
4784 #endif
4786 return ret;