- more Extensions work (begin to detect ATI extensions)
[wine/wine-kai.git] / dlls / d3d8 / device.c
blob9ddc4f6eb862763e5e033306bb1654210c72523f
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <math.h>
24 #include <stdarg.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
34 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
35 /*#define GL_GLEXT_PROTOTYPES*/
36 /*#undef GLX_GLXEXT_LEGACY*/
37 #include "d3d8_private.h"
39 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
40 #undef GL_VERSION_1_4
42 /* Uncomment the next line to get extra traces, important but impact speed */
43 /* #define EXTRA_TRACES */
45 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
46 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
47 WINE_DECLARE_DEBUG_CHANNEL(fps);
49 IDirect3DVertexShaderImpl* VertexShaders[64];
50 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
51 IDirect3DPixelShaderImpl* PixelShaders[64];
53 /* Debugging aids: */
54 #ifdef FRAME_DEBUGGING
55 BOOL isOn = FALSE;
56 BOOL isDumpingFrames = FALSE;
57 LONG primCounter = 0;
58 #endif
61 * Utility functions or macros
63 #define conv_mat(mat,gl_mat) \
64 do { \
65 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
66 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
68 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
69 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
70 } while (0)
72 /* Apply the current values to the specified texture stage */
73 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
74 ICOM_THIS(IDirect3DDevice8Impl,iface);
75 int i = 0;
76 float col[4];
77 BOOL changeTexture = TRUE;
79 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
80 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
82 BOOL skip = FALSE;
84 switch (i) {
85 /* Performance: For texture states where multiples effect the outcome, only bother
86 applying the last one as it will pick up all the other values */
87 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
88 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
89 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
90 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
91 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
92 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
93 skip = TRUE;
94 break;
96 /* Performance: If the texture states only impact settings for the texture unit
97 (compared to the texture object) then there is no need to reapply them. The
98 only time they need applying is the first time, since we cheat and put the
99 values into the stateblock without applying.
100 Per-texture unit: texture function (eg. combine), ops and args
101 texture env color
102 texture generation settings
103 Note: Due to some special conditions there may be a need to do particular ones
104 of these, which is what the Flags allows */
105 case D3DTSS_COLOROP:
106 case D3DTSS_TEXCOORDINDEX:
107 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
108 break;
110 case D3DTSS_ALPHAOP:
111 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
112 break;
114 default:
115 skip = FALSE;
118 if (skip == FALSE) {
119 /* Performance: Only change to this texture if we have to */
120 if (changeTexture) {
121 /* Make appropriate texture active */
122 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
123 #if defined(GL_VERSION_1_3)
124 glActiveTexture(GL_TEXTURE0 + Stage);
125 checkGLcall("glActiveTexture");
126 #else
127 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
128 checkGLcall("glActiveTextureARB");
129 #endif
130 } else if (Stage > 0) {
131 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
133 changeTexture = FALSE;
136 /* Now apply the change */
137 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
141 /* Note the D3DRS value applies to all textures, but GL has one
142 * per texture, so apply it now ready to be used!
144 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
145 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
146 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
148 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
151 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
152 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
154 float quad_att;
155 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
156 ICOM_THIS(IDirect3DDevice8Impl,iface);
158 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
159 glMatrixMode(GL_MODELVIEW);
160 glPushMatrix();
161 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
163 /* Diffuse: */
164 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
165 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
166 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
167 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
168 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
169 checkGLcall("glLightfv");
171 /* Specular */
172 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
173 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
174 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
175 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
176 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
177 checkGLcall("glLightfv");
179 /* Ambient */
180 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
181 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
182 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
183 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
184 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
185 checkGLcall("glLightfv");
187 /* Attenuation - Are these right? guessing... */
188 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
189 checkGLcall("glLightf");
190 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
191 checkGLcall("glLightf");
193 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
194 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
195 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
196 checkGLcall("glLightf");
198 switch (lightInfo->OriginalParms.Type) {
199 case D3DLIGHT_POINT:
200 /* Position */
201 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
202 checkGLcall("glLightfv");
203 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
204 checkGLcall("glLightf");
205 /* FIXME: Range */
206 break;
208 case D3DLIGHT_SPOT:
209 /* Position */
210 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
211 checkGLcall("glLightfv");
212 /* Direction */
213 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
214 checkGLcall("glLightfv");
215 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
216 checkGLcall("glLightf");
217 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
218 checkGLcall("glLightf");
219 /* FIXME: Range */
220 break;
222 case D3DLIGHT_DIRECTIONAL:
223 /* Direction */
224 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
225 checkGLcall("glLightfv");
226 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
227 checkGLcall("glLightf");
228 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
229 checkGLcall("glLightf");
230 break;
232 default:
233 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
236 /* Restore the modelview matrix */
237 glPopMatrix();
240 /* Setup this textures matrix */
241 static void set_texture_matrix(float *smat, DWORD flags)
243 float mat[16];
245 glMatrixMode(GL_TEXTURE);
247 if (flags == D3DTTFF_DISABLE) {
248 glLoadIdentity();
249 checkGLcall("glLoadIdentity()");
250 return;
253 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
254 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
255 checkGLcall("glLoadIdentity()");
256 return;
259 memcpy(mat, smat, 16*sizeof(float));
261 switch (flags & ~D3DTTFF_PROJECTED) {
262 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
263 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
264 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
267 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
268 case D3DTTFF_COUNT2:
269 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
270 mat[1] = mat[5] = mat[9] = mat[13] = 0;
271 break;
272 case D3DTTFF_COUNT3:
273 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
274 mat[2] = mat[6] = mat[10] = mat[14] = 0;
275 break;
277 glLoadMatrixf(mat);
278 checkGLcall("glLoadMatrixf(mat)");
281 /* IDirect3D IUnknown parts follow: */
282 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
284 ICOM_THIS(IDirect3DDevice8Impl,iface);
286 if (IsEqualGUID(riid, &IID_IUnknown)
287 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
288 IDirect3DDevice8Impl_AddRef(iface);
289 *ppobj = This;
290 return D3D_OK;
293 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
294 return E_NOINTERFACE;
297 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
298 ICOM_THIS(IDirect3DDevice8Impl,iface);
299 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
300 return ++(This->ref);
303 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
304 ICOM_THIS(IDirect3DDevice8Impl,iface);
305 ULONG ref = --This->ref;
306 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
307 if (ref == 0) {
308 IDirect3DDevice8Impl_CleanRender(iface);
309 HeapFree(GetProcessHeap(), 0, This);
311 return ref;
314 /* IDirect3DDevice Interface follow: */
315 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
316 ICOM_THIS(IDirect3DDevice8Impl,iface);
317 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
318 return D3D_OK;
321 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
322 ICOM_THIS(IDirect3DDevice8Impl,iface);
323 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
325 * pretend we have 32MB of any type of memory queried.
327 return (1024*1024*32);
330 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
331 ICOM_THIS(IDirect3DDevice8Impl,iface);
332 FIXME("(%p) : stub\n", This); return D3D_OK;
334 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
335 ICOM_THIS(IDirect3DDevice8Impl,iface);
336 TRACE("(%p) : returning %p\n", This, This->direct3d8);
338 /* Inc ref count */
339 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
341 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
342 return D3D_OK;
344 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
345 ICOM_THIS(IDirect3DDevice8Impl,iface);
346 FIXME("(%p) : stub, calling idirect3d for now\n", This);
347 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
348 return D3D_OK;
350 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
352 HDC hdc;
353 int bpp = 0;
355 ICOM_THIS(IDirect3DDevice8Impl,iface);
356 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
357 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
358 pMode->RefreshRate = 85; /*FIXME: How to identify? */
360 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
361 bpp = GetDeviceCaps(hdc, BITSPIXEL);
362 DeleteDC(hdc);
364 switch (bpp) {
365 case 8: pMode->Format = D3DFMT_R8G8B8; break;
366 case 16: pMode->Format = D3DFMT_R5G6B5; break;
367 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
368 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
369 default:
370 FIXME("Unrecognized display mode format\n");
371 pMode->Format = D3DFMT_UNKNOWN;
374 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
375 pMode->Format, debug_d3dformat(pMode->Format));
376 return D3D_OK;
378 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
379 ICOM_THIS(IDirect3DDevice8Impl,iface);
380 TRACE("(%p) copying to %p\n", This, pParameters);
381 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
382 return D3D_OK;
384 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
385 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
386 ICOM_THIS(IDirect3DDevice8Impl,iface);
387 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
389 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
390 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
391 return D3DERR_INVALIDCALL;
393 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
394 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
395 return D3DERR_INVALIDCALL;
398 This->xHotSpot = XHotSpot;
399 This->yHotSpot = YHotSpot;
400 return D3D_OK;
402 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
403 ICOM_THIS(IDirect3DDevice8Impl,iface);
404 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
405 This->xScreenSpace = XScreenSpace;
406 This->yScreenSpace = YScreenSpace;
407 return;
409 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
410 ICOM_THIS(IDirect3DDevice8Impl,iface);
411 TRACE("(%p) : visible(%d)\n", This, bShow);
412 This->bCursorVisible = bShow;
413 return D3D_OK;
415 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
416 IDirect3DSwapChain8Impl* object;
417 ICOM_THIS(IDirect3DDevice8Impl,iface);
418 FIXME("(%p) : stub\n", This);
420 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
421 if (NULL == object) {
422 return D3DERR_OUTOFVIDEOMEMORY;
424 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
425 object->ref = 1;
427 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
428 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
429 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
431 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
432 (pPresentationParameters->BackBufferHeight == 0))) {
433 RECT Rect;
435 GetClientRect(This->win_handle, &Rect);
437 if (pPresentationParameters->BackBufferWidth == 0) {
438 pPresentationParameters->BackBufferWidth = Rect.right;
439 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
441 if (pPresentationParameters->BackBufferHeight == 0) {
442 pPresentationParameters->BackBufferHeight = Rect.bottom;
443 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
447 /* Save the presentation parms now filled in correctly */
448 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
450 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
451 pPresentationParameters->BackBufferWidth,
452 pPresentationParameters->BackBufferHeight,
453 pPresentationParameters->BackBufferFormat,
454 pPresentationParameters->MultiSampleType,
455 TRUE,
456 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
458 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
459 pPresentationParameters->BackBufferWidth,
460 pPresentationParameters->BackBufferHeight,
461 pPresentationParameters->BackBufferFormat,
462 pPresentationParameters->MultiSampleType,
463 TRUE,
464 (LPDIRECT3DSURFACE8*) &object->backBuffer);
466 if (pPresentationParameters->EnableAutoDepthStencil) {
467 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
468 pPresentationParameters->BackBufferWidth,
469 pPresentationParameters->BackBufferHeight,
470 pPresentationParameters->AutoDepthStencilFormat,
471 D3DMULTISAMPLE_NONE,
472 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
473 } else {
474 object->depthStencilBuffer = NULL;
477 *pSwapChain = (IDirect3DSwapChain8*) object;
478 return D3D_OK;
480 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
481 ICOM_THIS(IDirect3DDevice8Impl,iface);
482 FIXME("(%p) : stub\n", This); return D3D_OK;
484 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
485 ICOM_THIS(IDirect3DDevice8Impl,iface);
486 TRACE("(%p) : complete stub!\n", This);
488 ENTER_GL();
490 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
493 glXSwapBuffers(This->display, This->drawable);
494 /* Don't call checkGLcall, as glGetError is not applicable here */
495 TRACE("glXSwapBuffers called, Starting new frame\n");
497 /* FPS support */
498 if (TRACE_ON(fps))
500 static long prev_time, frames;
502 DWORD time = GetTickCount();
503 frames++;
504 /* every 1.5 seconds */
505 if (time - prev_time > 1500) {
506 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
507 prev_time = time;
508 frames = 0;
512 #if defined(FRAME_DEBUGGING)
514 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
515 if (!isOn) {
516 isOn = TRUE;
517 FIXME("Enabling D3D Trace\n");
518 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
519 #if defined(SHOW_FRAME_MAKEUP)
520 FIXME("Singe Frame snapshots Starting\n");
521 isDumpingFrames = TRUE;
522 glClear(GL_COLOR_BUFFER_BIT);
523 #endif
525 #if defined(SINGLE_FRAME_DEBUGGING)
526 } else {
527 #if defined(SHOW_FRAME_MAKEUP)
528 FIXME("Singe Frame snapshots Finishing\n");
529 isDumpingFrames = FALSE;
530 #endif
531 FIXME("Singe Frame trace complete\n");
532 DeleteFileA("C:\\D3DTRACE");
533 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
534 #endif
536 } else {
537 if (isOn) {
538 isOn = FALSE;
539 #if defined(SHOW_FRAME_MAKEUP)
540 FIXME("Singe Frame snapshots Finishing\n");
541 isDumpingFrames = FALSE;
542 #endif
543 FIXME("Disabling D3D Trace\n");
544 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
548 #endif
550 LEAVE_GL();
551 /* Although this is not strictly required, a simple demo showed this does occur
552 on (at least non-debug) d3d */
553 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
554 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
557 return D3D_OK;
559 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
560 ICOM_THIS(IDirect3DDevice8Impl,iface);
561 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
562 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
564 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
565 FIXME("Only one backBuffer currently supported\n");
566 return D3DERR_INVALIDCALL;
569 /* Note inc ref on returned surface */
570 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
572 return D3D_OK;
574 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
575 ICOM_THIS(IDirect3DDevice8Impl,iface);
576 FIXME("(%p) : stub\n", This);
577 return D3D_OK;
579 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
580 HDC hDC;
581 ICOM_THIS(IDirect3DDevice8Impl,iface);
583 FIXME("(%p) : pRamp@%p\n", This, pRamp);
584 hDC = GetDC(This->win_handle);
585 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
586 ReleaseDC(This->win_handle, hDC);
587 return;
589 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
590 HDC hDC;
591 ICOM_THIS(IDirect3DDevice8Impl,iface);
593 FIXME("(%p) : pRamp@%p\n", This, pRamp);
594 hDC = GetDC(This->win_handle);
595 GetDeviceGammaRamp(hDC, pRamp);
596 ReleaseDC(This->win_handle, hDC);
597 return;
599 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
600 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
601 IDirect3DTexture8Impl *object;
602 int i;
603 UINT tmpW;
604 UINT tmpH;
606 ICOM_THIS(IDirect3DDevice8Impl,iface);
608 /* Allocate the storage for the device */
609 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);
610 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
611 object->lpVtbl = &Direct3DTexture8_Vtbl;
612 object->Device = This;
613 object->ResourceType = D3DRTYPE_TEXTURE;
614 object->ref = 1;
615 object->width = Width;
616 object->height = Height;
617 object->levels = Levels;
618 object->usage = Usage;
619 object->format = Format;
621 /* Calculate levels for mip mapping */
622 if (Levels == 0) {
623 object->levels++;
624 tmpW = Width;
625 tmpH = Height;
626 while (tmpW > 1 && tmpH > 1) {
627 tmpW = max(1, tmpW / 2);
628 tmpH = max(1, tmpH / 2);
629 object->levels++;
631 TRACE("Calculated levels = %d\n", object->levels);
634 /* Generate all the surfaces */
635 tmpW = Width;
636 tmpH = Height;
637 for (i = 0; i < object->levels; i++)
639 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
640 object->surfaces[i]->Container = (IUnknown*) object;
641 object->surfaces[i]->myDesc.Usage = Usage;
642 object->surfaces[i]->myDesc.Pool = Pool;
643 /**
644 * As written in msdn in IDirect3DTexture8::LockRect
645 * Textures created in D3DPOOL_DEFAULT are not lockable.
647 if (D3DPOOL_DEFAULT == Pool) {
648 object->surfaces[i]->lockable = FALSE;
651 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
652 tmpW = max(1, tmpW / 2);
653 tmpH = max(1, tmpH / 2);
656 *ppTexture = (LPDIRECT3DTEXTURE8) object;
657 TRACE("(%p) : Created texture %p\n", This, object);
658 return D3D_OK;
660 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
661 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
662 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
664 IDirect3DVolumeTexture8Impl *object;
665 int i;
666 UINT tmpW;
667 UINT tmpH;
668 UINT tmpD;
670 ICOM_THIS(IDirect3DDevice8Impl,iface);
672 /* Allocate the storage for it */
673 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));
674 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
675 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
676 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
677 object->Device = This;
678 object->ref = 1;
680 object->width = Width;
681 object->height = Height;
682 object->depth = Depth;
683 object->levels = Levels;
684 object->usage = Usage;
685 object->format = Format;
687 /* Calculate levels for mip mapping */
688 if (Levels == 0) {
689 object->levels++;
690 tmpW = Width;
691 tmpH = Height;
692 tmpD = Depth;
693 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
694 tmpW = max(1, tmpW / 2);
695 tmpH = max(1, tmpH / 2);
696 tmpD = max(1, tmpD / 2);
697 object->levels++;
699 TRACE("Calculated levels = %d\n", object->levels);
702 /* Generate all the surfaces */
703 tmpW = Width;
704 tmpH = Height;
705 tmpD = Depth;
707 for (i = 0; i < object->levels; i++)
709 IDirect3DVolume8Impl* volume;
711 /* Create the volume - No entry point for this seperately?? */
712 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
713 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
715 volume->lpVtbl = &Direct3DVolume8_Vtbl;
716 volume->Device = This;
717 volume->ResourceType = D3DRTYPE_VOLUME;
718 volume->Container = (IUnknown*) object;
719 volume->ref = 1;
721 volume->myDesc.Width = Width;
722 volume->myDesc.Height = Height;
723 volume->myDesc.Depth = Depth;
724 volume->myDesc.Format = Format;
725 volume->myDesc.Type = D3DRTYPE_VOLUME;
726 volume->myDesc.Pool = Pool;
727 volume->myDesc.Usage = Usage;
728 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
729 /* Note: Volume textures cannot be dxtn, hence no need to check here */
730 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
731 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
733 volume->lockable = TRUE;
734 volume->locked = FALSE;
735 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
736 volume->Dirty = FALSE;
737 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
739 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
740 This, Width, Height, Depth, Format, debug_d3dformat(Format),
741 volume, volume->allocatedMemory, volume->myDesc.Size);
743 tmpW = max(1, tmpW / 2);
744 tmpH = max(1, tmpH / 2);
745 tmpD = max(1, tmpD / 2);
748 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
749 TRACE("(%p) : Created volume texture %p\n", This, object);
750 return D3D_OK;
752 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
753 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
755 IDirect3DCubeTexture8Impl *object;
756 ICOM_THIS(IDirect3DDevice8Impl,iface);
757 int i,j;
758 UINT tmpW;
760 /* Allocate the storage for it */
761 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));
762 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
763 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
764 object->ref = 1;
765 object->Device = This;
766 object->ResourceType = D3DRTYPE_CUBETEXTURE;
768 object->edgeLength = EdgeLength;
769 object->levels = Levels;
770 object->usage = Usage;
771 object->format = Format;
773 /* Calculate levels for mip mapping */
774 if (Levels == 0) {
775 object->levels++;
776 tmpW = EdgeLength;
777 while (tmpW > 1) {
778 tmpW = max(1, tmpW / 2);
779 object->levels++;
781 TRACE("Calculated levels = %d\n", object->levels);
784 /* Generate all the surfaces */
785 tmpW = EdgeLength;
786 for (i = 0; i < object->levels; i++) {
787 /* Create the 6 faces */
788 for (j = 0; j < 6; j++) {
789 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
790 object->surfaces[j][i]->Container = (IUnknown*) object;
791 object->surfaces[j][i]->myDesc.Usage = Usage;
792 object->surfaces[j][i]->myDesc.Pool = Pool;
793 /**
794 * As written in msdn in IDirect3DCubeTexture8::LockRect
795 * Textures created in D3DPOOL_DEFAULT are not lockable.
797 if (D3DPOOL_DEFAULT == Pool) {
798 object->surfaces[j][i]->lockable = FALSE;
801 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
803 tmpW = max(1, tmpW / 2);
806 TRACE("(%p) : Iface@%p\n", This, object);
807 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
808 return D3D_OK;
810 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
811 IDirect3DVertexBuffer8Impl *object;
813 ICOM_THIS(IDirect3DDevice8Impl,iface);
815 /* Allocate the storage for the device */
816 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
817 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
818 object->Device = This;
819 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
820 object->ref = 1;
821 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
822 object->currentDesc.Usage = Usage;
823 object->currentDesc.Pool = Pool;
824 object->currentDesc.FVF = FVF;
825 object->currentDesc.Size = Size;
827 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
829 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
831 return D3D_OK;
833 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
834 IDirect3DIndexBuffer8Impl *object;
836 ICOM_THIS(IDirect3DDevice8Impl,iface);
837 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
839 /* Allocate the storage for the device */
840 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
841 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
842 object->Device = This;
843 object->ref = 1;
844 object->ResourceType = D3DRTYPE_INDEXBUFFER;
846 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
847 object->currentDesc.Usage = Usage;
848 object->currentDesc.Pool = Pool;
849 object->currentDesc.Format = Format;
850 object->currentDesc.Size = Length;
852 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
854 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
856 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
858 return D3D_OK;
860 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
861 IDirect3DSurface8Impl *object;
862 ICOM_THIS(IDirect3DDevice8Impl,iface);
864 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
865 if (NULL == object) {
866 *ppSurface = NULL;
867 return D3DERR_OUTOFVIDEOMEMORY;
869 *ppSurface = (LPDIRECT3DSURFACE8) object;
870 object->lpVtbl = &Direct3DSurface8_Vtbl;
871 object->Device = This;
872 object->ResourceType = D3DRTYPE_SURFACE;
873 object->Container = (IUnknown*) This;
875 object->ref = 1;
876 object->myDesc.Width = Width;
877 object->myDesc.Height = Height;
878 object->myDesc.Format = Format;
879 object->myDesc.Type = D3DRTYPE_SURFACE;
880 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
881 object->myDesc.Pool = D3DPOOL_DEFAULT;
882 object->myDesc.MultiSampleType = MultiSample;
883 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
884 if (Format == D3DFMT_DXT1) {
885 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
886 } else {
887 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
889 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
890 object->lockable = Lockable;
891 object->locked = FALSE;
892 memset(&object->lockedRect, 0, sizeof(RECT));
893 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
895 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);
896 return D3D_OK;
898 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
899 IDirect3DSurface8Impl *object;
901 ICOM_THIS(IDirect3DDevice8Impl,iface);
903 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
904 if (NULL == object) {
905 *ppSurface = NULL;
906 return D3DERR_OUTOFVIDEOMEMORY;
908 *ppSurface = (LPDIRECT3DSURFACE8) object;
909 object->lpVtbl = &Direct3DSurface8_Vtbl;
910 object->Device = This;
911 object->ResourceType = D3DRTYPE_SURFACE;
912 object->Container = (IUnknown*) This;
914 object->ref = 1;
915 object->myDesc.Width = Width;
916 object->myDesc.Height = Height;
917 object->myDesc.Format = Format;
918 object->myDesc.Type = D3DRTYPE_SURFACE;
919 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
920 object->myDesc.Pool = D3DPOOL_DEFAULT;
921 object->myDesc.MultiSampleType = MultiSample;
922 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
923 if (Format == D3DFMT_DXT1) {
924 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
925 } else {
926 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
928 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
929 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
930 object->locked = FALSE;
931 memset(&object->lockedRect, 0, sizeof(RECT));
932 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
934 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);
935 return D3D_OK;
937 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
938 IDirect3DSurface8Impl *object;
940 ICOM_THIS(IDirect3DDevice8Impl,iface);
942 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
943 *ppSurface = (LPDIRECT3DSURFACE8) object;
944 object->lpVtbl = &Direct3DSurface8_Vtbl;
945 object->Device = This;
946 object->ResourceType = D3DRTYPE_SURFACE;
947 object->Container = (IUnknown*) This;
949 object->ref = 1;
950 object->myDesc.Width = Width;
951 object->myDesc.Height = Height;
952 object->myDesc.Format = Format;
953 object->myDesc.Type = D3DRTYPE_SURFACE;
954 object->myDesc.Usage = 0;
955 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
956 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
957 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
958 it is based around 4x4 pixel blocks it requires padding, so allocate enough
959 space! */
960 if (Format == D3DFMT_DXT1) {
961 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
962 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
963 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
964 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
965 } else {
966 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
968 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
969 object->lockable = TRUE;
970 object->locked = FALSE;
971 memset(&object->lockedRect, 0, sizeof(RECT));
972 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
974 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);
975 return D3D_OK;
977 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
978 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
979 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
981 HRESULT rc = D3D_OK;
982 IDirect3DBaseTexture8* texture = NULL;
985 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
986 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
988 ICOM_THIS(IDirect3DDevice8Impl,iface);
989 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
990 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
992 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
993 a sample and doesn't seem to break anything as far as I can tell */
994 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
995 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
996 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
997 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
998 rc = D3DERR_INVALIDCALL;
1000 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1001 TRACE("Converting dest to same format as source, since dest was unknown\n");
1002 dst->myDesc.Format = src->myDesc.Format;
1004 /* Convert container as well */
1005 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1006 if (SUCCEEDED(rc) && NULL != texture) {
1007 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1008 /** Releasing texture after GetContainer */
1009 IDirect3DBaseTexture8_Release(texture);
1010 texture = NULL;
1014 /* Quick if complete copy ... */
1015 if (SUCCEEDED(rc)) {
1016 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1018 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1020 D3DLOCKED_RECT lrSrc;
1021 D3DLOCKED_RECT lrDst;
1022 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1023 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1024 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1026 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1028 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1029 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1030 TRACE("Unlocked src and dst\n");
1032 } else {
1034 FIXME("Wanted to copy all surfaces but size not compatible\n");
1035 rc = D3DERR_INVALIDCALL;
1039 } else {
1041 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1043 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1044 int i;
1046 /* Copy rect by rect */
1047 for (i = 0; i < cRects; i++) {
1048 CONST RECT* r = &pSourceRectsArray[i];
1049 CONST POINT* p = &pDestPointsArray[i];
1050 int copyperline;
1051 int j;
1052 D3DLOCKED_RECT lrSrc;
1053 D3DLOCKED_RECT lrDst;
1054 RECT dest_rect;
1056 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1057 if (src->myDesc.Format == D3DFMT_DXT1) {
1058 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1059 } else {
1060 copyperline = ((r->right - r->left) * bytesPerPixel);
1062 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1063 dest_rect.left = p->x;
1064 dest_rect.top = p->y;
1065 dest_rect.right = p->x + (r->right - r->left);
1066 dest_rect.bottom= p->y + (r->bottom - r->top);
1067 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1068 TRACE("Locked src and dst\n");
1070 /* Find where to start */
1071 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1072 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1074 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1075 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1076 TRACE("Unlocked src and dst\n");
1078 } else {
1079 FIXME("Wanted to copy partial surfaces not implemented\n");
1080 rc = D3DERR_INVALIDCALL;
1085 return rc;
1087 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1088 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1089 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1090 D3DRESOURCETYPE srcType;
1091 D3DRESOURCETYPE dstType;
1093 ICOM_THIS(IDirect3DDevice8Impl,iface);
1094 TRACE("(%p) : first try\n", This);
1096 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1097 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1099 if (srcType != dstType) {
1100 return D3DERR_INVALIDCALL;
1102 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1103 return D3DERR_INVALIDCALL;
1105 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1106 return D3DERR_INVALIDCALL;
1108 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1109 /** Only copy Dirty textures */
1110 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1111 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1112 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1113 UINT i, j;
1115 for (i = skipLevels; i < srcLevelCnt; ++i) {
1116 HRESULT hr;
1118 switch (srcType) {
1119 case D3DRTYPE_TEXTURE:
1121 IDirect3DSurface8* srcSur = NULL;
1122 IDirect3DSurface8* dstSur = NULL;
1123 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1124 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1126 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1127 about dst with less levels than the source?) */
1128 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1130 IDirect3DSurface8Impl_Release(srcSur);
1131 IDirect3DSurface8Impl_Release(dstSur);
1133 break;
1134 case D3DRTYPE_VOLUMETEXTURE:
1136 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1138 break;
1139 case D3DRTYPE_CUBETEXTURE:
1141 IDirect3DSurface8* srcSur = NULL;
1142 IDirect3DSurface8* dstSur = NULL;
1143 for (j = 0; j < 5; ++j) {
1144 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1145 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1146 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1147 IDirect3DSurface8Impl_Release(srcSur);
1148 IDirect3DSurface8Impl_Release(dstSur);
1151 break;
1152 default:
1153 break;
1156 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1159 return D3D_OK;
1161 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1162 HRESULT hr;
1163 D3DLOCKED_RECT lockedRect;
1164 RECT wantedRect;
1165 GLint prev_store;
1166 GLenum prev_read;
1168 ICOM_THIS(IDirect3DDevice8Impl,iface);
1170 FIXME("(%p) : see if behavior correct\n", This);
1172 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1173 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1174 return D3DERR_INVALIDCALL;
1177 wantedRect.left = 0;
1178 wantedRect.top = 0;
1179 wantedRect.right = This->PresentParms.BackBufferWidth;
1180 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1182 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1183 if (FAILED(hr)) {
1184 ERR("(%p) : cannot lock surface\n", This);
1185 return D3DERR_INVALIDCALL;
1188 ENTER_GL();
1190 glFlush();
1191 vcheckGLcall("glFlush");
1192 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1193 vcheckGLcall("glIntegerv");
1194 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1195 vcheckGLcall("glIntegerv");
1197 glReadBuffer(GL_FRONT);
1198 vcheckGLcall("glReadBuffer");
1199 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1200 vcheckGLcall("glPixelStorei");
1201 /* stupid copy */
1203 long j;
1204 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1205 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1206 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1207 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1208 vcheckGLcall("glReadPixels");
1211 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1212 vcheckGLcall("glPixelStorei");
1213 glReadBuffer(prev_read);
1214 vcheckGLcall("glReadBuffer");
1216 LEAVE_GL();
1218 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1219 return hr;
1221 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1222 HRESULT hr;
1224 ICOM_THIS(IDirect3DDevice8Impl,iface);
1226 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1227 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1228 return D3D_OK;
1231 IDirect3DDevice8Impl_CleanRender(iface);
1233 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1234 IDirect3DSurface8Impl* tmp;
1236 TRACE("retoring SetRenderTarget defaults\n");
1238 tmp = This->renderTarget;
1239 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1240 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1241 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1243 tmp = This->stencilBufferTarget;
1244 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1245 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1246 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1248 return D3D_OK;
1251 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1253 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1255 return hr;
1258 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1259 ICOM_THIS(IDirect3DDevice8Impl,iface);
1261 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1263 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1264 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1266 return D3D_OK;
1269 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1270 ICOM_THIS(IDirect3DDevice8Impl,iface);
1272 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1274 /* Note inc ref on returned surface */
1275 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1276 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1278 return D3D_OK;
1281 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1282 ICOM_THIS(IDirect3DDevice8Impl,iface);
1283 TRACE("(%p) : stub\n", This);
1284 return D3D_OK;
1286 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1287 IDirect3DBaseTexture8* cont = NULL;
1288 HRESULT hr;
1289 ICOM_THIS(IDirect3DDevice8Impl,iface);
1290 TRACE("(%p)\n", This);
1292 ENTER_GL();
1294 glFlush();
1295 checkGLcall("glFlush");
1297 /* Useful for debugging sometimes!
1298 printf("Hit Enter ...\n");
1299 getchar(); */
1301 if (This->frontBuffer != This->renderTarget) {
1303 GLenum prev_read;
1304 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1305 vcheckGLcall("glIntegerv");
1306 glReadBuffer(GL_BACK);
1307 vcheckGLcall("glReadBuffer");
1309 long j;
1310 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1312 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1313 pitch = pitch / 2;
1315 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1316 glReadPixels(0,
1317 This->renderTarget->myDesc.Height - j - 1,
1318 This->renderTarget->myDesc.Width,
1320 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1321 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1322 This->renderTarget->allocatedMemory + j * pitch);
1323 vcheckGLcall("glReadPixels");
1326 glReadBuffer(prev_read);
1327 vcheckGLcall("glReadBuffer");
1330 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1331 if (SUCCEEDED(hr) && NULL != cont) {
1332 /** always dirtify for now. we must find a better way to see that surface have been modified */
1333 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1334 IDirect3DBaseTexture8_PreLoad(cont);
1335 IDirect3DBaseTexture8Impl_Release(cont);
1336 cont = NULL;
1340 LEAVE_GL();
1341 return D3D_OK;
1343 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1344 ICOM_THIS(IDirect3DDevice8Impl,iface);
1346 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1347 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1348 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1349 GLbitfield glMask = 0;
1350 GLboolean old_ztest;
1351 GLfloat old_z_clear_value;
1352 GLint old_stencil_clear_value;
1353 GLfloat old_color_clear_value[4];
1354 int i;
1355 CONST D3DRECT* curRect;
1357 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1358 Count, pRects, Flags, Z, Stencil);
1360 ENTER_GL();
1361 glEnable(GL_SCISSOR_TEST);
1362 checkGLcall("glEnable GL_SCISSOR_TEST");
1363 if (Count > 0 && pRects) {
1364 curRect = pRects;
1365 } else {
1366 curRect = NULL;
1369 /* Only set the values up once, as they are not changing */
1370 if (Flags & D3DCLEAR_STENCIL) {
1371 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1372 glClearStencil(Stencil);
1373 checkGLcall("glClearStencil");
1374 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1375 glStencilMask(0xFFFFFFFF);
1378 if (Flags & D3DCLEAR_ZBUFFER) {
1379 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1380 glDepthMask(GL_TRUE);
1381 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1382 glClearDepth(Z);
1383 checkGLcall("glClearDepth");
1384 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1387 if (Flags & D3DCLEAR_TARGET) {
1388 TRACE("Clearing screen with glClear to color %lx\n", Color);
1389 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1390 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1391 ((Color >> 8) & 0xFF) / 255.0f,
1392 ((Color >> 0) & 0xFF) / 255.0f,
1393 ((Color >> 24) & 0xFF) / 255.0f);
1394 checkGLcall("glClearColor");
1396 /* Clear ALL colors! */
1397 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1398 glMask = glMask | GL_COLOR_BUFFER_BIT;
1401 /* Now process each rect in turn */
1402 for (i = 0; i < Count || i == 0; i++) {
1404 if (curRect) {
1405 /* Note gl uses lower left, width/height */
1406 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1407 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1408 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1409 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1410 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1411 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1412 checkGLcall("glScissor");
1413 } else {
1414 glScissor(This->StateBlock->viewport.X,
1415 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1416 This->StateBlock->viewport.Width,
1417 This->StateBlock->viewport.Height);
1418 checkGLcall("glScissor");
1421 /* Clear the selected rectangle (or full screen) */
1422 glClear(glMask);
1423 checkGLcall("glClear");
1425 /* Step to the next rectangle */
1426 if (curRect) curRect = curRect + sizeof(D3DRECT);
1429 /* Restore the old values (why..?) */
1430 if (Flags & D3DCLEAR_STENCIL) {
1431 glClearStencil(old_stencil_clear_value);
1432 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1434 if (Flags & D3DCLEAR_ZBUFFER) {
1435 glDepthMask(old_ztest);
1436 glClearDepth(old_z_clear_value);
1438 if (Flags & D3DCLEAR_TARGET) {
1439 glClearColor(old_color_clear_value[0],
1440 old_color_clear_value[1],
1441 old_color_clear_value[2],
1442 old_color_clear_value[3]);
1443 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1444 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1445 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1446 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1449 glDisable(GL_SCISSOR_TEST);
1450 checkGLcall("glDisable");
1451 LEAVE_GL();
1453 return D3D_OK;
1455 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1456 ICOM_THIS(IDirect3DDevice8Impl,iface);
1457 int k;
1459 /* Most of this routine, comments included copied from ddraw tree initially: */
1460 TRACE("(%p) : State=%d\n", This, d3dts);
1462 /* Handle recording of state blocks */
1463 if (This->isRecordingState) {
1464 TRACE("Recording... not performing anything\n");
1465 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1466 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1467 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1468 return D3D_OK;
1472 * if the new matrix is the same as the current one,
1473 * we cut off any further processing. this seems to be a reasonable
1474 * optimization because as was noticed, some apps (warcraft3 for example)
1475 * tend towards setting the same matrix repeatedly for some dumb reason.
1477 * From here on we assume that the new matrix is different, wherever it matters
1478 * but note
1480 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1481 TRACE("The app is setting the same matrix over again\n");
1482 return D3D_OK;
1483 } else {
1484 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1488 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1489 where ViewMat = Camera space, WorldMat = world space.
1491 In OpenGL, camera and world space is combined into GL_MODELVIEW
1492 matrix. The Projection matrix stay projection matrix.
1495 /* Capture the times we can just ignore the change */
1496 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1497 This->modelview_valid = FALSE;
1498 return D3D_OK;
1500 } else if (d3dts == D3DTS_PROJECTION) {
1501 This->proj_valid = FALSE;
1502 return D3D_OK;
1504 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1505 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1506 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1507 return D3D_OK;
1510 /* Chances are we really are going to have to change a matrix */
1511 ENTER_GL();
1513 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1514 if (d3dts < GL_LIMITS(textures)) {
1515 int tex = d3dts - D3DTS_TEXTURE0;
1516 #if defined(GL_VERSION_1_3)
1517 glActiveTexture(GL_TEXTURE0 + tex);
1518 checkGLcall("glActiveTexture");
1519 #else
1520 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1521 checkGLcall("glActiveTextureARB");
1522 #endif
1523 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1526 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1528 PLIGHTINFOEL *lightChain = NULL;
1529 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1530 This->modelview_valid = FALSE;
1531 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1532 glMatrixMode(GL_MODELVIEW);
1533 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1534 glPushMatrix();
1535 glLoadMatrixf((float *)lpmatrix);
1536 checkGLcall("glLoadMatrixf(...)");
1538 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1539 * NOTE: We have to reset the positions even if the light/plane is not currently
1540 * enabled, since the call to enable it will not reset the position.
1541 * NOTE2: Apparently texture transforms do NOT need reapplying
1544 /* Reset lights */
1545 lightChain = This->StateBlock->lights;
1546 while (lightChain && lightChain->glIndex != -1) {
1547 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1548 checkGLcall("glLightfv posn");
1549 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1550 checkGLcall("glLightfv dirn");
1551 lightChain = lightChain->next;
1553 /* Reset Clipping Planes if clipping is enabled */
1554 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1555 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1556 checkGLcall("glClipPlane");
1558 glPopMatrix();
1560 } else { /* What was requested!?? */
1561 WARN("invalid matrix specified: %i\n", d3dts);
1565 /* Release lock, all done */
1566 LEAVE_GL();
1567 return D3D_OK;
1570 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1571 ICOM_THIS(IDirect3DDevice8Impl,iface);
1572 TRACE("(%p) : for State %d\n", This, State);
1573 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1574 return D3D_OK;
1577 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1578 D3DMATRIX *mat = NULL;
1579 D3DMATRIX temp;
1581 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1582 but works regardless of recording being on.
1583 If this is found to be wrong, change to StateBlock. */
1584 ICOM_THIS(IDirect3DDevice8Impl,iface);
1585 TRACE("(%p) : For state %u\n", This, State);
1587 if (State < HIGHEST_TRANSFORMSTATE)
1589 mat = &This->UpdateStateBlock->transforms[State];
1590 } else {
1591 FIXME("Unhandled transform state!!\n");
1594 /* Copied from ddraw code: */
1595 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);
1596 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);
1597 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);
1598 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);
1600 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);
1601 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);
1602 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);
1603 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);
1605 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);
1606 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);
1607 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);
1608 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);
1610 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);
1611 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);
1612 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);
1613 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);
1615 /* Apply change via set transform - will reapply to eg. lights this way */
1616 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1617 return D3D_OK;
1619 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1620 ICOM_THIS(IDirect3DDevice8Impl,iface);
1622 TRACE("(%p)\n", This);
1623 This->UpdateStateBlock->Changed.viewport = TRUE;
1624 This->UpdateStateBlock->Set.viewport = TRUE;
1625 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1627 /* Handle recording of state blocks */
1628 if (This->isRecordingState) {
1629 TRACE("Recording... not performing anything\n");
1630 return D3D_OK;
1633 ENTER_GL();
1635 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1636 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1638 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1639 checkGLcall("glDepthRange");
1640 /* Note: GL requires lower left, DirectX supplies upper left */
1641 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1642 pViewport->Width, pViewport->Height);
1643 checkGLcall("glViewport");
1645 LEAVE_GL();
1647 return D3D_OK;
1650 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1651 ICOM_THIS(IDirect3DDevice8Impl,iface);
1652 TRACE("(%p)\n", This);
1653 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1654 return D3D_OK;
1657 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1658 ICOM_THIS(IDirect3DDevice8Impl,iface);
1660 This->UpdateStateBlock->Changed.material = TRUE;
1661 This->UpdateStateBlock->Set.material = TRUE;
1662 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1664 /* Handle recording of state blocks */
1665 if (This->isRecordingState) {
1666 TRACE("Recording... not performing anything\n");
1667 return D3D_OK;
1670 ENTER_GL();
1671 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1672 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1673 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1674 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1675 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1677 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1678 checkGLcall("glMaterialfv");
1679 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1680 checkGLcall("glMaterialfv");
1682 /* Only change material color if specular is enabled, otherwise it is set to black */
1683 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1684 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1685 checkGLcall("glMaterialfv");
1686 } else {
1687 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1688 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1689 checkGLcall("glMaterialfv");
1691 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1692 checkGLcall("glMaterialfv");
1693 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1694 checkGLcall("glMaterialf");
1696 LEAVE_GL();
1697 return D3D_OK;
1699 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1700 ICOM_THIS(IDirect3DDevice8Impl,iface);
1701 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1702 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1703 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1704 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1705 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1706 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1707 return D3D_OK;
1710 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1711 you can reference any indexes you want as long as that number max are enabled are any
1712 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1713 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1714 but when recording, just build a chain pretty much of commands to be replayed. */
1716 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1717 float rho;
1718 PLIGHTINFOEL *object, *temp;
1720 ICOM_THIS(IDirect3DDevice8Impl,iface);
1721 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1723 /* If recording state block, just add to end of lights chain */
1724 if (This->isRecordingState) {
1725 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1726 if (NULL == object) {
1727 return D3DERR_OUTOFVIDEOMEMORY;
1729 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1730 object->OriginalIndex = Index;
1731 object->glIndex = -1;
1732 object->changed = TRUE;
1734 /* Add to the END of the chain of lights changes to be replayed */
1735 if (This->UpdateStateBlock->lights == NULL) {
1736 This->UpdateStateBlock->lights = object;
1737 } else {
1738 temp = This->UpdateStateBlock->lights;
1739 while (temp->next != NULL) temp=temp->next;
1740 temp->next = object;
1742 TRACE("Recording... not performing anything more\n");
1743 return D3D_OK;
1746 /* Ok, not recording any longer so do real work */
1747 object = This->StateBlock->lights;
1748 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1750 /* If we didn't find it in the list of lights, time to add it */
1751 if (object == NULL) {
1752 PLIGHTINFOEL *insertAt,*prevPos;
1754 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1755 if (NULL == object) {
1756 return D3DERR_OUTOFVIDEOMEMORY;
1758 object->OriginalIndex = Index;
1759 object->glIndex = -1;
1761 /* Add it to the front of list with the idea that lights will be changed as needed
1762 BUT after any lights currently assigned GL indexes */
1763 insertAt = This->StateBlock->lights;
1764 prevPos = NULL;
1765 while (insertAt != NULL && insertAt->glIndex != -1) {
1766 prevPos = insertAt;
1767 insertAt = insertAt->next;
1770 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1771 This->StateBlock->lights = object;
1772 } else if (insertAt == NULL) { /* End of list */
1773 prevPos->next = object;
1774 object->prev = prevPos;
1775 } else { /* Middle of chain */
1776 if (prevPos == NULL) {
1777 This->StateBlock->lights = object;
1778 } else {
1779 prevPos->next = object;
1781 object->prev = prevPos;
1782 object->next = insertAt;
1783 insertAt->prev = object;
1787 /* Initialze the object */
1788 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,
1789 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1790 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1791 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1792 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1793 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1794 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1796 /* Save away the information */
1797 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1799 switch (pLight->Type) {
1800 case D3DLIGHT_POINT:
1801 /* Position */
1802 object->lightPosn[0] = pLight->Position.x;
1803 object->lightPosn[1] = pLight->Position.y;
1804 object->lightPosn[2] = pLight->Position.z;
1805 object->lightPosn[3] = 1.0f;
1806 object->cutoff = 180.0f;
1807 /* FIXME: Range */
1808 break;
1810 case D3DLIGHT_SPOT:
1811 /* Position */
1812 object->lightPosn[0] = pLight->Position.x;
1813 object->lightPosn[1] = pLight->Position.y;
1814 object->lightPosn[2] = pLight->Position.z;
1815 object->lightPosn[3] = 1.0;
1817 /* Direction */
1818 object->lightDirn[0] = pLight->Direction.x;
1819 object->lightDirn[1] = pLight->Direction.y;
1820 object->lightDirn[2] = pLight->Direction.z;
1821 object->lightDirn[3] = 1.0;
1824 * opengl-ish and d3d-ish spot lights use too different models for the
1825 * light "intensity" as a function of the angle towards the main light direction,
1826 * so we only can approximate very roughly.
1827 * however spot lights are rather rarely used in games (if ever used at all).
1828 * furthermore if still used, probably nobody pays attention to such details.
1830 if (pLight->Falloff == 0) {
1831 rho = 6.28f;
1832 } else {
1833 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1835 if (rho < 0.0001) rho = 0.0001f;
1836 object->exponent = -0.3/log(cos(rho/2));
1837 object->cutoff = pLight->Phi*90/M_PI;
1839 /* FIXME: Range */
1840 break;
1842 case D3DLIGHT_DIRECTIONAL:
1843 /* Direction */
1844 object->lightPosn[0] = -pLight->Direction.x;
1845 object->lightPosn[1] = -pLight->Direction.y;
1846 object->lightPosn[2] = -pLight->Direction.z;
1847 object->lightPosn[3] = 0.0;
1848 object->exponent = 0.0f;
1849 object->cutoff = 180.0f;
1850 break;
1852 default:
1853 FIXME("Unrecognized light type %d\n", pLight->Type);
1856 /* Update the live definitions if the light is currently assigned a glIndex */
1857 if (object->glIndex != -1) {
1858 setup_light(iface, object->glIndex, object);
1860 return D3D_OK;
1862 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1863 PLIGHTINFOEL *lightInfo = NULL;
1864 ICOM_THIS(IDirect3DDevice8Impl,iface);
1865 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1867 /* Locate the light in the live lights */
1868 lightInfo = This->StateBlock->lights;
1869 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1871 if (lightInfo == NULL) {
1872 TRACE("Light information requested but light not defined\n");
1873 return D3DERR_INVALIDCALL;
1876 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1877 return D3D_OK;
1879 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1880 PLIGHTINFOEL *lightInfo = NULL;
1881 ICOM_THIS(IDirect3DDevice8Impl,iface);
1882 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1884 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1885 if (This->isRecordingState) {
1886 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1887 if (NULL == lightInfo) {
1888 return D3DERR_OUTOFVIDEOMEMORY;
1890 lightInfo->OriginalIndex = Index;
1891 lightInfo->glIndex = -1;
1892 lightInfo->enabledChanged = TRUE;
1894 /* Add to the END of the chain of lights changes to be replayed */
1895 if (This->UpdateStateBlock->lights == NULL) {
1896 This->UpdateStateBlock->lights = lightInfo;
1897 } else {
1898 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1899 while (temp->next != NULL) temp=temp->next;
1900 temp->next = lightInfo;
1902 TRACE("Recording... not performing anything more\n");
1903 return D3D_OK;
1906 /* Not recording... So, locate the light in the live lights */
1907 lightInfo = This->StateBlock->lights;
1908 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1910 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1911 if (lightInfo == NULL) {
1912 D3DLIGHT8 lightParms;
1913 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1914 wait until someone confirms it seems to work! */
1915 TRACE("Light enabled requested but light not defined, so defining one!\n");
1916 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1917 lightParms.Diffuse.r = 1.0;
1918 lightParms.Diffuse.g = 1.0;
1919 lightParms.Diffuse.b = 1.0;
1920 lightParms.Diffuse.a = 0.0;
1921 lightParms.Specular.r = 0.0;
1922 lightParms.Specular.g = 0.0;
1923 lightParms.Specular.b = 0.0;
1924 lightParms.Specular.a = 0.0;
1925 lightParms.Ambient.r = 0.0;
1926 lightParms.Ambient.g = 0.0;
1927 lightParms.Ambient.b = 0.0;
1928 lightParms.Ambient.a = 0.0;
1929 lightParms.Position.x = 0.0;
1930 lightParms.Position.y = 0.0;
1931 lightParms.Position.z = 0.0;
1932 lightParms.Direction.x = 0.0;
1933 lightParms.Direction.y = 0.0;
1934 lightParms.Direction.z = 1.0;
1935 lightParms.Range = 0.0;
1936 lightParms.Falloff = 0.0;
1937 lightParms.Attenuation0 = 0.0;
1938 lightParms.Attenuation1 = 0.0;
1939 lightParms.Attenuation2 = 0.0;
1940 lightParms.Theta = 0.0;
1941 lightParms.Phi = 0.0;
1942 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1944 /* Search for it again! Should be fairly quick as near head of list */
1945 lightInfo = This->StateBlock->lights;
1946 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1947 if (lightInfo == NULL) {
1948 FIXME("Adding default lights has failed dismally\n");
1949 return D3DERR_INVALIDCALL;
1953 /* OK, we now have a light... */
1954 if (Enable == FALSE) {
1956 /* If we are disabling it, check it was enabled, and
1957 still only do something if it has assigned a glIndex (which it should have!) */
1958 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1959 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1960 ENTER_GL();
1961 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1962 checkGLcall("glDisable GL_LIGHT0+Index");
1963 LEAVE_GL();
1964 } else {
1965 TRACE("Nothing to do as light was not enabled\n");
1967 lightInfo->lightEnabled = FALSE;
1968 } else {
1970 /* We are enabling it. If it is enabled, its really simple */
1971 if (lightInfo->lightEnabled == TRUE) {
1972 /* nop */
1973 TRACE("Nothing to do as light was enabled\n");
1975 /* If it already has a glIndex, its still simple */
1976 } else if (lightInfo->glIndex != -1) {
1977 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1978 lightInfo->lightEnabled = TRUE;
1979 ENTER_GL();
1980 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1981 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1982 LEAVE_GL();
1984 /* Otherwise got to find space - lights are ordered gl indexes first */
1985 } else {
1986 PLIGHTINFOEL *bsf = NULL;
1987 PLIGHTINFOEL *pos = This->StateBlock->lights;
1988 PLIGHTINFOEL *prev = NULL;
1989 int Index= 0;
1990 int glIndex = -1;
1992 /* Try to minimize changes as much as possible */
1993 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1995 /* Try to remember which index can be replaced if necessary */
1996 if (bsf==NULL && pos->lightEnabled == FALSE) {
1997 /* Found a light we can replace, save as best replacement */
1998 bsf = pos;
2001 /* Step to next space */
2002 prev = pos;
2003 pos = pos->next;
2004 Index ++;
2007 /* If we have too many active lights, fail the call */
2008 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2009 FIXME("Program requests too many concurrent lights\n");
2010 return D3DERR_INVALIDCALL;
2012 /* If we have allocated all lights, but not all are enabled,
2013 reuse one which is not enabled */
2014 } else if (Index == This->maxConcurrentLights) {
2015 /* use bsf - Simply swap the new light and the BSF one */
2016 PLIGHTINFOEL *bsfNext = bsf->next;
2017 PLIGHTINFOEL *bsfPrev = bsf->prev;
2019 /* Sort out ends */
2020 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2021 if (bsf->prev != NULL) {
2022 bsf->prev->next = lightInfo;
2023 } else {
2024 This->StateBlock->lights = lightInfo;
2027 /* If not side by side, lots of chains to update */
2028 if (bsf->next != lightInfo) {
2029 lightInfo->prev->next = bsf;
2030 bsf->next->prev = lightInfo;
2031 bsf->next = lightInfo->next;
2032 bsf->prev = lightInfo->prev;
2033 lightInfo->next = bsfNext;
2034 lightInfo->prev = bsfPrev;
2036 } else {
2037 /* Simple swaps */
2038 bsf->prev = lightInfo;
2039 bsf->next = lightInfo->next;
2040 lightInfo->next = bsf;
2041 lightInfo->prev = bsfPrev;
2045 /* Update states */
2046 glIndex = bsf->glIndex;
2047 bsf->glIndex = -1;
2048 lightInfo->glIndex = glIndex;
2049 lightInfo->lightEnabled = TRUE;
2051 /* Finally set up the light in gl itself */
2052 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2053 ENTER_GL();
2054 setup_light(iface, glIndex, lightInfo);
2055 glEnable(GL_LIGHT0 + glIndex);
2056 checkGLcall("glEnable GL_LIGHT0 new setup");
2057 LEAVE_GL();
2059 /* If we reached the end of the allocated lights, with space in the
2060 gl lights, setup a new light */
2061 } else if (pos->glIndex == -1) {
2063 /* We reached the end of the allocated gl lights, so already
2064 know the index of the next one! */
2065 glIndex = Index;
2066 lightInfo->glIndex = glIndex;
2067 lightInfo->lightEnabled = TRUE;
2069 /* In an ideal world, its already in the right place */
2070 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2071 /* No need to move it */
2072 } else {
2073 /* Remove this light from the list */
2074 lightInfo->prev->next = lightInfo->next;
2075 if (lightInfo->next != NULL) {
2076 lightInfo->next->prev = lightInfo->prev;
2079 /* Add in at appropriate place (inbetween prev and pos) */
2080 lightInfo->prev = prev;
2081 lightInfo->next = pos;
2082 if (prev == NULL) {
2083 This->StateBlock->lights = lightInfo;
2084 } else {
2085 prev->next = lightInfo;
2087 if (pos != NULL) {
2088 pos->prev = lightInfo;
2092 /* Finally set up the light in gl itself */
2093 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2094 ENTER_GL();
2095 setup_light(iface, glIndex, lightInfo);
2096 glEnable(GL_LIGHT0 + glIndex);
2097 checkGLcall("glEnable GL_LIGHT0 new setup");
2098 LEAVE_GL();
2103 return D3D_OK;
2105 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2107 PLIGHTINFOEL *lightInfo = NULL;
2108 ICOM_THIS(IDirect3DDevice8Impl,iface);
2109 TRACE("(%p) : for idx(%ld)\n", This, Index);
2111 /* Locate the light in the live lights */
2112 lightInfo = This->StateBlock->lights;
2113 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2115 if (lightInfo == NULL) {
2116 TRACE("Light enabled state requested but light not defined\n");
2117 return D3DERR_INVALIDCALL;
2119 *pEnable = lightInfo->lightEnabled;
2120 return D3D_OK;
2122 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2123 ICOM_THIS(IDirect3DDevice8Impl,iface);
2124 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2126 /* Validate Index */
2127 if (Index >= GL_LIMITS(clipplanes)) {
2128 TRACE("Application has requested clipplane this device doesn't support\n");
2129 return D3DERR_INVALIDCALL;
2132 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2133 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2134 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2135 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2136 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2137 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2139 /* Handle recording of state blocks */
2140 if (This->isRecordingState) {
2141 TRACE("Recording... not performing anything\n");
2142 return D3D_OK;
2145 /* Apply it */
2147 ENTER_GL();
2149 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2150 glMatrixMode(GL_MODELVIEW);
2151 glPushMatrix();
2152 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2154 TRACE("Clipplane [%f,%f,%f,%f]\n",
2155 This->UpdateStateBlock->clipplane[Index][0],
2156 This->UpdateStateBlock->clipplane[Index][1],
2157 This->UpdateStateBlock->clipplane[Index][2],
2158 This->UpdateStateBlock->clipplane[Index][3]);
2159 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2160 checkGLcall("glClipPlane");
2162 glPopMatrix();
2164 LEAVE_GL();
2166 return D3D_OK;
2168 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2169 ICOM_THIS(IDirect3DDevice8Impl,iface);
2170 TRACE("(%p) : for idx %ld\n", This, Index);
2172 /* Validate Index */
2173 if (Index >= GL_LIMITS(clipplanes)) {
2174 TRACE("Application has requested clipplane this device doesn't support\n");
2175 return D3DERR_INVALIDCALL;
2178 pPlane[0] = This->StateBlock->clipplane[Index][0];
2179 pPlane[1] = This->StateBlock->clipplane[Index][1];
2180 pPlane[2] = This->StateBlock->clipplane[Index][2];
2181 pPlane[3] = This->StateBlock->clipplane[Index][3];
2182 return D3D_OK;
2184 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2185 ICOM_THIS(IDirect3DDevice8Impl,iface);
2186 DWORD OldValue = This->StateBlock->renderstate[State];
2188 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2189 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2190 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2191 This->UpdateStateBlock->renderstate[State] = Value;
2193 /* Handle recording of state blocks */
2194 if (This->isRecordingState) {
2195 TRACE("Recording... not performing anything\n");
2196 return D3D_OK;
2199 ENTER_GL();
2201 switch (State) {
2202 case D3DRS_FILLMODE :
2203 switch ((D3DFILLMODE) Value) {
2204 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2205 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2206 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2207 default:
2208 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2210 checkGLcall("glPolygonMode (fillmode)");
2211 break;
2213 case D3DRS_LIGHTING :
2214 if (Value) {
2215 glEnable(GL_LIGHTING);
2216 checkGLcall("glEnable GL_LIGHTING");
2217 } else {
2218 glDisable(GL_LIGHTING);
2219 checkGLcall("glDisable GL_LIGHTING");
2221 break;
2223 case D3DRS_ZENABLE :
2224 switch ((D3DZBUFFERTYPE) Value) {
2225 case D3DZB_FALSE:
2226 glDisable(GL_DEPTH_TEST);
2227 checkGLcall("glDisable GL_DEPTH_TEST");
2228 break;
2229 case D3DZB_TRUE:
2230 glEnable(GL_DEPTH_TEST);
2231 checkGLcall("glEnable GL_DEPTH_TEST");
2232 break;
2234 case D3DZB_USEW:
2235 default:
2236 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2238 break;
2240 case D3DRS_CULLMODE :
2242 /* If we are culling "back faces with clockwise vertices" then
2243 set front faces to be counter clockwise and enable culling
2244 of back faces */
2245 switch ((D3DCULL) Value) {
2246 case D3DCULL_NONE:
2247 glDisable(GL_CULL_FACE);
2248 checkGLcall("glDisable GL_CULL_FACE");
2249 break;
2250 case D3DCULL_CW:
2251 glEnable(GL_CULL_FACE);
2252 checkGLcall("glEnable GL_CULL_FACE");
2253 glFrontFace(GL_CCW);
2254 checkGLcall("glFrontFace GL_CCW");
2255 glCullFace(GL_BACK);
2256 break;
2257 case D3DCULL_CCW:
2258 glEnable(GL_CULL_FACE);
2259 checkGLcall("glEnable GL_CULL_FACE");
2260 glFrontFace(GL_CW);
2261 checkGLcall("glFrontFace GL_CW");
2262 glCullFace(GL_BACK);
2263 break;
2264 default:
2265 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2267 break;
2269 case D3DRS_SHADEMODE :
2270 switch ((D3DSHADEMODE) Value) {
2271 case D3DSHADE_FLAT:
2272 glShadeModel(GL_FLAT);
2273 checkGLcall("glShadeModel");
2274 break;
2275 case D3DSHADE_GOURAUD:
2276 glShadeModel(GL_SMOOTH);
2277 checkGLcall("glShadeModel");
2278 break;
2279 case D3DSHADE_PHONG:
2280 FIXME("D3DSHADE_PHONG isn't supported?\n");
2282 LEAVE_GL();
2283 return D3DERR_INVALIDCALL;
2284 default:
2285 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2287 break;
2289 case D3DRS_DITHERENABLE :
2290 if (Value) {
2291 glEnable(GL_DITHER);
2292 checkGLcall("glEnable GL_DITHER");
2293 } else {
2294 glDisable(GL_DITHER);
2295 checkGLcall("glDisable GL_DITHER");
2297 break;
2299 case D3DRS_ZWRITEENABLE :
2300 if (Value) {
2301 glDepthMask(1);
2302 checkGLcall("glDepthMask");
2303 } else {
2304 glDepthMask(0);
2305 checkGLcall("glDepthMask");
2307 break;
2309 case D3DRS_ZFUNC :
2311 int glParm = GL_LESS;
2313 switch ((D3DCMPFUNC) Value) {
2314 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2315 case D3DCMP_LESS: glParm=GL_LESS; break;
2316 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2317 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2318 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2319 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2320 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2321 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2322 default:
2323 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2325 glDepthFunc(glParm);
2326 checkGLcall("glDepthFunc");
2328 break;
2330 case D3DRS_AMBIENT :
2332 float col[4];
2333 D3DCOLORTOGLFLOAT4(Value, col);
2334 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2335 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2336 checkGLcall("glLightModel for MODEL_AMBIENT");
2339 break;
2341 case D3DRS_ALPHABLENDENABLE :
2342 if (Value) {
2343 glEnable(GL_BLEND);
2344 checkGLcall("glEnable GL_BLEND");
2345 } else {
2346 glDisable(GL_BLEND);
2347 checkGLcall("glDisable GL_BLEND");
2349 break;
2351 case D3DRS_SRCBLEND :
2352 case D3DRS_DESTBLEND :
2354 int newVal = GL_ZERO;
2355 switch (Value) {
2356 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2357 case D3DBLEND_ONE : newVal = GL_ONE; break;
2358 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2359 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2360 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2361 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2362 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2363 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2364 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2365 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2366 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2368 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2369 This->srcBlend = newVal;
2370 This->dstBlend = newVal;
2371 break;
2373 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2374 This->srcBlend = newVal;
2375 This->dstBlend = newVal;
2376 break;
2377 default:
2378 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2381 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2382 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2383 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2384 glBlendFunc(This->srcBlend, This->dstBlend);
2386 checkGLcall("glBlendFunc");
2388 break;
2390 case D3DRS_ALPHATESTENABLE :
2391 if (Value) {
2392 glEnable(GL_ALPHA_TEST);
2393 checkGLcall("glEnable GL_ALPHA_TEST");
2394 } else {
2395 glDisable(GL_ALPHA_TEST);
2396 checkGLcall("glDisable GL_ALPHA_TEST");
2398 break;
2400 case D3DRS_ALPHAFUNC :
2402 int glParm = GL_LESS;
2403 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2405 switch ((D3DCMPFUNC) Value) {
2406 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2407 case D3DCMP_LESS: glParm = GL_LESS; break;
2408 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2409 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2410 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2411 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2412 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2413 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2414 default:
2415 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2417 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2418 glAlphaFunc(glParm, ref);
2419 This->alphafunc = glParm;
2420 checkGLcall("glAlphaFunc");
2422 break;
2424 case D3DRS_ALPHAREF :
2426 int glParm = This->alphafunc;
2427 float ref = 1.0f;
2429 ref = ((float) Value) / 255.0f;
2430 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2431 glAlphaFunc(glParm, ref);
2432 checkGLcall("glAlphaFunc");
2434 break;
2436 case D3DRS_CLIPPLANEENABLE :
2437 case D3DRS_CLIPPING :
2439 /* Ensure we only do the changed clip planes */
2440 DWORD enable = 0xFFFFFFFF;
2441 DWORD disable = 0x00000000;
2443 /* If enabling / disabling all */
2444 if (State == D3DRS_CLIPPING) {
2445 if (Value) {
2446 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2447 disable = 0x00;
2448 } else {
2449 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2450 enable = 0x00;
2452 } else {
2453 enable = Value & ~OldValue;
2454 disable = ~Value & OldValue;
2457 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2458 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2459 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2460 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2461 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2462 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2464 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2465 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2466 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2467 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2468 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2469 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2471 break;
2473 case D3DRS_BLENDOP :
2475 int glParm = GL_FUNC_ADD;
2477 switch ((D3DBLENDOP) Value) {
2478 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2479 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2480 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2481 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2482 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2483 default:
2484 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2486 TRACE("glBlendEquation(%x)\n", glParm);
2487 glBlendEquation(glParm);
2488 checkGLcall("glBlendEquation");
2490 break;
2492 case D3DRS_TEXTUREFACTOR :
2494 int i;
2496 /* Note the texture color applies to all textures whereas
2497 GL_TEXTURE_ENV_COLOR applies to active only */
2498 float col[4];
2499 D3DCOLORTOGLFLOAT4(Value, col);
2500 /* Set the default alpha blend color */
2501 glBlendColor(col[0], col[1], col[2], col[3]);
2502 checkGLcall("glBlendColor");
2504 /* And now the default texture color as well */
2505 for (i = 0; i < GL_LIMITS(textures); i++) {
2507 /* Note the D3DRS value applies to all textures, but GL has one
2508 per texture, so apply it now ready to be used! */
2509 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2510 #if defined(GL_VERSION_1_3)
2511 glActiveTexture(GL_TEXTURE0 + i);
2512 #else
2513 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2514 #endif
2515 checkGLcall("Activate texture.. to update const color");
2516 } else if (i>0) {
2517 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2520 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2521 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2524 break;
2526 case D3DRS_SPECULARENABLE :
2528 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2529 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2530 specular color. This is wrong:
2531 Separate specular color means the specular colour is maintained separately, whereas
2532 single color means it is merged in. However in both cases they are being used to
2533 some extent.
2534 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2535 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2536 running 1.4 yet!
2538 if (Value) {
2539 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2540 checkGLcall("glMaterialfv");
2541 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2542 glEnable(GL_COLOR_SUM_EXT);
2543 } else {
2544 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2546 checkGLcall("glEnable(GL_COLOR_SUM)");
2547 } else {
2548 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2550 /* for the case of enabled lighting: */
2551 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2552 checkGLcall("glMaterialfv");
2554 /* for the case of disabled lighting: */
2555 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2556 glDisable(GL_COLOR_SUM_EXT);
2557 } else {
2558 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2560 checkGLcall("glDisable(GL_COLOR_SUM)");
2563 break;
2565 case D3DRS_STENCILENABLE :
2566 if (Value) {
2567 glEnable(GL_STENCIL_TEST);
2568 checkGLcall("glEnable GL_STENCIL_TEST");
2569 } else {
2570 glDisable(GL_STENCIL_TEST);
2571 checkGLcall("glDisable GL_STENCIL_TEST");
2573 break;
2575 case D3DRS_STENCILFUNC :
2577 int glParm = GL_ALWAYS;
2578 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2579 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2581 switch ((D3DCMPFUNC) Value) {
2582 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2583 case D3DCMP_LESS: glParm=GL_LESS; break;
2584 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2585 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2586 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2587 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2588 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2589 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2590 default:
2591 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2593 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2594 This->stencilfunc = glParm;
2595 glStencilFunc(glParm, ref, mask);
2596 checkGLcall("glStencilFunc");
2598 break;
2600 case D3DRS_STENCILREF :
2602 int glParm = This->stencilfunc;
2603 int ref = 0;
2604 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2606 ref = Value;
2607 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2608 glStencilFunc(glParm, ref, mask);
2609 checkGLcall("glStencilFunc");
2611 break;
2613 case D3DRS_STENCILMASK :
2615 int glParm = This->stencilfunc;
2616 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2617 GLuint mask = Value;
2619 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2620 glStencilFunc(glParm, ref, mask);
2621 checkGLcall("glStencilFunc");
2623 break;
2625 case D3DRS_STENCILFAIL :
2627 GLenum fail ;
2628 GLenum zpass ;
2629 GLenum zfail ;
2631 fail = StencilOp(Value);
2632 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2633 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2634 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2635 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2637 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2638 glStencilOp(fail, zfail, zpass);
2639 checkGLcall("glStencilOp(fail, zfail, zpass);");
2641 break;
2642 case D3DRS_STENCILZFAIL :
2644 GLenum fail ;
2645 GLenum zpass ;
2646 GLenum zfail ;
2648 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2649 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2650 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2651 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2652 zfail = StencilOp(Value);
2654 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2655 glStencilOp(fail, zfail, zpass);
2656 checkGLcall("glStencilOp(fail, zfail, zpass);");
2658 break;
2659 case D3DRS_STENCILPASS :
2661 GLenum fail ;
2662 GLenum zpass ;
2663 GLenum zfail ;
2665 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2666 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2667 zpass = StencilOp(Value);
2668 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2669 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2671 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2672 glStencilOp(fail, zfail, zpass);
2673 checkGLcall("glStencilOp(fail, zfail, zpass);");
2675 break;
2677 case D3DRS_STENCILWRITEMASK :
2679 glStencilMask(Value);
2680 TRACE("glStencilMask(%lu)\n", Value);
2681 checkGLcall("glStencilMask");
2683 break;
2685 case D3DRS_FOGENABLE :
2687 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2688 glEnable(GL_FOG);
2689 checkGLcall("glEnable GL_FOG");
2690 } else {
2691 glDisable(GL_FOG);
2692 checkGLcall("glDisable GL_FOG");
2695 break;
2697 case D3DRS_FOGCOLOR :
2699 float col[4];
2700 D3DCOLORTOGLFLOAT4(Value, col);
2701 /* Set the default alpha blend color */
2702 glFogfv(GL_FOG_COLOR, &col[0]);
2703 checkGLcall("glFog GL_FOG_COLOR");
2705 break;
2707 case D3DRS_FOGTABLEMODE :
2709 switch (Value) {
2710 case D3DFOG_NONE: /* I don't know what to do here */ break;
2711 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2712 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2713 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2714 default:
2715 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2718 break;
2720 case D3DRS_FOGSTART :
2722 float *f = (float*) &Value;
2723 glFogfv(GL_FOG_START, f);
2724 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2725 TRACE("Fog Start == %f\n", *f);
2727 break;
2729 case D3DRS_FOGEND :
2731 float *f = (float*) &Value;
2732 glFogfv(GL_FOG_END, f);
2733 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2734 TRACE("Fog End == %f\n", *f);
2736 break;
2738 case D3DRS_FOGDENSITY :
2740 float *f = (float*) &Value;
2741 glFogfv(GL_FOG_DENSITY, f);
2742 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2744 break;
2746 case D3DRS_VERTEXBLEND :
2748 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2749 TRACE("Vertex Blending state to %ld\n", Value);
2751 break;
2753 case D3DRS_TWEENFACTOR :
2755 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2756 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2758 break;
2760 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2762 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2764 break;
2766 case D3DRS_COLORVERTEX :
2767 case D3DRS_DIFFUSEMATERIALSOURCE :
2768 case D3DRS_SPECULARMATERIALSOURCE :
2769 case D3DRS_AMBIENTMATERIALSOURCE :
2770 case D3DRS_EMISSIVEMATERIALSOURCE :
2772 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2774 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2775 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2776 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2777 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2778 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2779 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2781 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2782 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2783 Parm = GL_AMBIENT_AND_DIFFUSE;
2784 } else {
2785 Parm = GL_DIFFUSE;
2787 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2788 Parm = GL_AMBIENT;
2789 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2790 Parm = GL_EMISSION;
2791 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2792 Parm = GL_SPECULAR;
2793 } else {
2794 Parm = -1;
2797 if (Parm == -1) {
2798 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2799 } else {
2800 This->tracking_color = NEEDS_TRACKING;
2801 This->tracking_parm = Parm;
2804 } else {
2805 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2808 break;
2810 case D3DRS_LINEPATTERN :
2812 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2813 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2815 if (pattern->wRepeatFactor) {
2816 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2817 checkGLcall("glLineStipple(repeat, linepattern)");
2818 glEnable(GL_LINE_STIPPLE);
2819 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2820 } else {
2821 glDisable(GL_LINE_STIPPLE);
2822 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2825 break;
2827 case D3DRS_ZBIAS :
2829 if (Value) {
2830 TRACE("ZBias value %f\n", *((float*)&Value));
2831 glPolygonOffset(0, -*((float*)&Value));
2832 checkGLcall("glPolygonOffset(0, -Value)");
2833 glEnable(GL_POLYGON_OFFSET_FILL);
2834 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2835 glEnable(GL_POLYGON_OFFSET_LINE);
2836 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2837 glEnable(GL_POLYGON_OFFSET_POINT);
2838 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2839 } else {
2840 glDisable(GL_POLYGON_OFFSET_FILL);
2841 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2842 glDisable(GL_POLYGON_OFFSET_LINE);
2843 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2844 glDisable(GL_POLYGON_OFFSET_POINT);
2845 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2848 break;
2850 case D3DRS_NORMALIZENORMALS :
2851 if (Value) {
2852 glEnable(GL_NORMALIZE);
2853 checkGLcall("glEnable(GL_NORMALIZE);");
2854 } else {
2855 glDisable(GL_NORMALIZE);
2856 checkGLcall("glDisable(GL_NORMALIZE);");
2858 break;
2860 case D3DRS_POINTSIZE :
2861 TRACE("Set point size to %f\n", *((float*)&Value));
2862 glPointSize(*((float*)&Value));
2863 checkGLcall("glPointSize(...);");
2864 break;
2866 case D3DRS_POINTSIZE_MIN :
2867 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2868 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2869 checkGLcall("glPointParameterfEXT(...);");
2870 } else {
2871 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2873 break;
2875 case D3DRS_POINTSIZE_MAX :
2876 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2877 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2878 checkGLcall("glPointParameterfEXT(...);");
2879 } else {
2880 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2882 break;
2884 case D3DRS_POINTSCALE_A :
2885 case D3DRS_POINTSCALE_B :
2886 case D3DRS_POINTSCALE_C :
2887 case D3DRS_POINTSCALEENABLE :
2889 /* If enabled, supply the parameters, otherwise fall back to defaults */
2890 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2891 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2892 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2893 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2894 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2896 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2897 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2898 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2899 } else {
2900 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2902 } else {
2903 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2904 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2905 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2906 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2907 } else {
2908 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2911 break;
2914 case D3DRS_COLORWRITEENABLE :
2915 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2916 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2917 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2918 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2919 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2920 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2921 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2922 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2923 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2924 checkGLcall("glColorMask(...)");
2925 break;
2927 /* Unhandled yet...! */
2928 case D3DRS_LASTPIXEL :
2929 case D3DRS_ZVISIBLE :
2930 case D3DRS_EDGEANTIALIAS :
2931 case D3DRS_RANGEFOGENABLE :
2932 case D3DRS_WRAP0 :
2933 case D3DRS_WRAP1 :
2934 case D3DRS_WRAP2 :
2935 case D3DRS_WRAP3 :
2936 case D3DRS_WRAP4 :
2937 case D3DRS_WRAP5 :
2938 case D3DRS_WRAP6 :
2939 case D3DRS_WRAP7 :
2940 case D3DRS_FOGVERTEXMODE :
2941 case D3DRS_LOCALVIEWER :
2942 case D3DRS_SOFTWAREVERTEXPROCESSING :
2943 case D3DRS_POINTSPRITEENABLE :
2944 case D3DRS_MULTISAMPLEANTIALIAS :
2945 case D3DRS_MULTISAMPLEMASK :
2946 case D3DRS_PATCHEDGESTYLE :
2947 case D3DRS_PATCHSEGMENTS :
2948 case D3DRS_DEBUGMONITORTOKEN :
2949 case D3DRS_POSITIONORDER :
2950 case D3DRS_NORMALORDER :
2951 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2952 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2953 break;
2954 default:
2955 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2958 LEAVE_GL();
2960 return D3D_OK;
2962 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2963 ICOM_THIS(IDirect3DDevice8Impl,iface);
2964 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2965 *pValue = This->StateBlock->renderstate[State];
2966 return D3D_OK;
2968 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2969 ICOM_THIS(IDirect3DDevice8Impl,iface);
2971 TRACE("(%p)\n", This);
2973 return IDirect3DDeviceImpl_BeginStateBlock(This);
2975 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2976 IDirect3DStateBlockImpl* pSB;
2977 ICOM_THIS(IDirect3DDevice8Impl,iface);
2978 HRESULT res;
2980 TRACE("(%p)\n", This);
2982 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2983 *pToken = (DWORD) pSB;
2984 return res;
2987 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2988 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2989 ICOM_THIS(IDirect3DDevice8Impl,iface);
2991 TRACE("(%p)\n", This);
2993 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2996 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2997 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2998 ICOM_THIS(IDirect3DDevice8Impl,iface);
3000 TRACE("(%p)\n", This);
3002 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3004 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3005 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3006 ICOM_THIS(IDirect3DDevice8Impl,iface);
3008 TRACE("(%p)\n", This);
3010 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3013 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3014 IDirect3DStateBlockImpl* pSB;
3015 ICOM_THIS(IDirect3DDevice8Impl,iface);
3016 HRESULT res;
3018 TRACE("(%p) : for type %d\n", This, Type);
3020 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3021 *pToken = (DWORD) pSB;
3022 return res;
3025 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3026 ICOM_THIS(IDirect3DDevice8Impl,iface);
3027 FIXME("(%p) : stub\n", This); return D3D_OK;
3029 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3030 ICOM_THIS(IDirect3DDevice8Impl,iface);
3031 FIXME("(%p) : stub\n", This); return D3D_OK;
3033 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3034 ICOM_THIS(IDirect3DDevice8Impl,iface);
3035 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3036 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3037 if (*ppTexture)
3038 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3039 return D3D_OK;
3041 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3043 IDirect3DBaseTexture8 *oldTxt;
3044 BOOL reapplyStates = TRUE;
3045 DWORD oldTextureDimensions = -1;
3046 DWORD reapplyFlags = 0;
3048 ICOM_THIS(IDirect3DDevice8Impl,iface);
3049 D3DRESOURCETYPE textureType;
3051 oldTxt = This->UpdateStateBlock->textures[Stage];
3052 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3054 /* Reject invalid texture units */
3055 if (Stage >= GL_LIMITS(textures)) {
3056 TRACE("Attempt to access invalid texture rejected\n");
3057 return D3DERR_INVALIDCALL;
3060 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3061 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3062 This->UpdateStateBlock->textures[Stage] = pTexture;
3064 /* Handle recording of state blocks */
3065 if (This->isRecordingState) {
3066 TRACE("Recording... not performing anything\n");
3067 return D3D_OK;
3070 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3071 ENTER_GL();
3073 /* Make appropriate texture active */
3074 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3075 #if defined(GL_VERSION_1_3)
3076 glActiveTexture(GL_TEXTURE0 + Stage);
3077 checkGLcall("glActiveTexture");
3078 #else
3079 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3080 checkGLcall("glActiveTextureARB");
3081 #endif
3082 } else if (Stage>0) {
3083 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3086 /* Decrement the count of the previous texture */
3087 if (NULL != oldTxt) {
3088 IDirect3DBaseTexture8Impl_Release(oldTxt);
3091 if (NULL != pTexture) {
3092 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3094 /* Now setup the texture appropraitly */
3095 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3097 if (textureType == D3DRTYPE_TEXTURE) {
3098 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3099 TRACE("Skipping setting texture as old == new\n");
3100 reapplyStates = FALSE;
3101 } else {
3102 /* Standard 2D texture */
3103 TRACE("Standard 2d texture\n");
3104 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3106 /* Load up the texture now */
3107 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3109 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3110 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3111 TRACE("Skipping setting texture as old == new\n");
3112 reapplyStates = FALSE;
3113 } else {
3114 /* Standard 3D (volume) texture */
3115 TRACE("Standard 3d texture\n");
3116 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3118 /* Load up the texture now */
3119 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3121 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3122 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3123 TRACE("Skipping setting texture as old == new\n");
3124 reapplyStates = FALSE;
3125 } else {
3126 /* Standard Cube texture */
3127 TRACE("Standard Cube texture\n");
3128 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3130 /* Load up the texture now */
3131 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3133 } else {
3134 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3136 } else {
3137 TRACE("Setting to no texture (ie default texture)\n");
3138 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3139 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3140 checkGLcall("glBindTexture");
3141 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3144 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3145 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3146 glDisable(oldTextureDimensions);
3147 checkGLcall("Disable oldTextureDimensions");
3148 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3149 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3150 checkGLcall("glEnable new texture dimensions");
3153 /* If Alpha arg1 is texture then handle the special case when there changes between a
3154 texture and no texture - See comments in set_tex_op */
3155 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3156 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3158 reapplyFlags |= REAPPLY_ALPHAOP;
3163 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3164 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3165 if (reapplyStates) {
3166 setupTextureStates(iface, Stage, reapplyFlags);
3169 LEAVE_GL();
3171 return D3D_OK;
3174 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3175 ICOM_THIS(IDirect3DDevice8Impl,iface);
3176 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3177 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3178 return D3D_OK;
3181 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3182 ICOM_THIS(IDirect3DDevice8Impl,iface);
3184 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3186 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3188 /* Reject invalid texture units */
3189 if (Stage >= GL_LIMITS(textures)) {
3190 TRACE("Attempt to access invalid texture rejected\n");
3191 return D3DERR_INVALIDCALL;
3194 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3195 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3196 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3198 /* Handle recording of state blocks */
3199 if (This->isRecordingState) {
3200 TRACE("Recording... not performing anything\n");
3201 return D3D_OK;
3204 ENTER_GL();
3206 /* Make appropriate texture active */
3207 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3208 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3209 #if defined(GL_VERSION_1_3)
3210 glActiveTexture(GL_TEXTURE0 + Stage);
3211 vcheckGLcall("glActiveTexture");
3212 #else
3213 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3214 vcheckGLcall("glActiveTextureARB");
3215 #endif
3216 } else if (Stage > 0) {
3217 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3220 switch (Type) {
3222 case D3DTSS_MINFILTER :
3223 case D3DTSS_MIPFILTER :
3225 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3226 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3227 GLint realVal = GL_LINEAR;
3229 if (ValueMIN == D3DTEXF_NONE) {
3230 /* Doesn't really make sense - Windows just seems to disable
3231 mipmapping when this occurs */
3232 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3233 realVal = GL_LINEAR;
3234 } else if (ValueMIN == D3DTEXF_POINT) {
3235 /* GL_NEAREST_* */
3236 if (ValueMIP == D3DTEXF_NONE) {
3237 realVal = GL_NEAREST;
3238 } else if (ValueMIP == D3DTEXF_POINT) {
3239 realVal = GL_NEAREST_MIPMAP_NEAREST;
3240 } else if (ValueMIP == D3DTEXF_LINEAR) {
3241 realVal = GL_NEAREST_MIPMAP_LINEAR;
3242 } else {
3243 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3244 realVal = GL_NEAREST;
3246 } else if (ValueMIN == D3DTEXF_LINEAR) {
3247 /* GL_LINEAR_* */
3248 if (ValueMIP == D3DTEXF_NONE) {
3249 realVal = GL_LINEAR;
3250 } else if (ValueMIP == D3DTEXF_POINT) {
3251 realVal = GL_LINEAR_MIPMAP_NEAREST;
3252 } else if (ValueMIP == D3DTEXF_LINEAR) {
3253 realVal = GL_LINEAR_MIPMAP_LINEAR;
3254 } else {
3255 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3256 realVal = GL_LINEAR;
3258 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3259 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3260 if (ValueMIP == D3DTEXF_NONE) {
3261 realVal = GL_LINEAR_MIPMAP_LINEAR;
3262 } else if (ValueMIP == D3DTEXF_POINT) {
3263 realVal = GL_LINEAR_MIPMAP_NEAREST;
3264 } else if (ValueMIP == D3DTEXF_LINEAR) {
3265 realVal = GL_LINEAR_MIPMAP_LINEAR;
3266 } else {
3267 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3268 realVal = GL_LINEAR;
3270 } else {
3271 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3272 realVal = GL_LINEAR;
3274 } else {
3275 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3276 realVal = GL_LINEAR_MIPMAP_LINEAR;
3279 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3280 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3281 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3283 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3285 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3286 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3287 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3288 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3289 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3292 break;
3294 case D3DTSS_MAGFILTER :
3296 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3297 GLint realVal = GL_NEAREST;
3299 if (ValueMAG == D3DTEXF_POINT) {
3300 realVal = GL_NEAREST;
3301 } else if (ValueMAG == D3DTEXF_LINEAR) {
3302 realVal = GL_LINEAR;
3303 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3304 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3305 realVal = GL_LINEAR;
3306 } else {
3307 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3308 realVal = GL_NEAREST;
3310 } else {
3311 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3312 realVal = GL_NEAREST;
3314 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3315 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3316 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3318 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3320 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3321 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3322 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3323 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3324 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3327 break;
3329 case D3DTSS_MAXMIPLEVEL :
3332 * Not really the same, but the more apprioprate than nothing
3334 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3335 GL_TEXTURE_BASE_LEVEL,
3336 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3337 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3339 break;
3341 case D3DTSS_MAXANISOTROPY :
3343 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3344 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3345 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3346 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3347 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3350 break;
3352 case D3DTSS_MIPMAPLODBIAS :
3354 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3355 float f = *(float*) &Value;
3356 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3357 GL_TEXTURE_LOD_BIAS_EXT,
3359 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3362 break;
3364 case D3DTSS_ALPHAOP :
3365 case D3DTSS_COLOROP :
3368 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3369 /* TODO: Disable by making this and all later levels disabled */
3370 glDisable(GL_TEXTURE_1D);
3371 checkGLcall("Disable GL_TEXTURE_1D");
3372 glDisable(GL_TEXTURE_2D);
3373 checkGLcall("Disable GL_TEXTURE_2D");
3374 glDisable(GL_TEXTURE_3D);
3375 checkGLcall("Disable GL_TEXTURE_3D");
3376 break; /* Don't bother setting the texture operations */
3377 } else {
3378 /* Enable only the appropriate texture dimension */
3379 if (Type == D3DTSS_COLOROP) {
3380 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3381 glEnable(GL_TEXTURE_1D);
3382 checkGLcall("Enable GL_TEXTURE_1D");
3383 } else {
3384 glDisable(GL_TEXTURE_1D);
3385 checkGLcall("Disable GL_TEXTURE_1D");
3387 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3388 glEnable(GL_TEXTURE_2D);
3389 checkGLcall("Enable GL_TEXTURE_2D");
3390 } else {
3391 glDisable(GL_TEXTURE_2D);
3392 checkGLcall("Disable GL_TEXTURE_2D");
3394 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3395 glEnable(GL_TEXTURE_3D);
3396 checkGLcall("Enable GL_TEXTURE_3D");
3397 } else {
3398 glDisable(GL_TEXTURE_3D);
3399 checkGLcall("Disable GL_TEXTURE_3D");
3401 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3402 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3403 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3404 } else {
3405 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3406 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3410 /* Drop through... (Except disable case) */
3411 case D3DTSS_COLORARG0 :
3412 case D3DTSS_COLORARG1 :
3413 case D3DTSS_COLORARG2 :
3414 case D3DTSS_ALPHAARG0 :
3415 case D3DTSS_ALPHAARG1 :
3416 case D3DTSS_ALPHAARG2 :
3418 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3419 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3420 if (isAlphaArg) {
3421 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3422 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3423 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3424 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3425 } else {
3426 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3427 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3428 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3429 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3432 break;
3435 case D3DTSS_ADDRESSU :
3436 case D3DTSS_ADDRESSV :
3437 case D3DTSS_ADDRESSW :
3439 GLint wrapParm = GL_REPEAT;
3441 switch (Value) {
3442 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3443 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3444 case D3DTADDRESS_BORDER:
3446 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3447 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3448 } else {
3449 /* FIXME: Not right, but better */
3450 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3451 wrapParm = GL_REPEAT;
3454 break;
3455 case D3DTADDRESS_MIRROR:
3457 #if defined(GL_VERSION_1_4)
3458 wrapParm = GL_MIRRORED_REPEAT;
3459 #elif defined(GL_ARB_texture_mirrored_repeat)
3460 wrapParm = GL_MIRRORED_REPEAT_ARB;
3461 #else
3462 /* Unsupported in OpenGL pre-1.4 */
3463 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3464 wrapParm = GL_REPEAT;
3465 #endif
3467 break;
3468 case D3DTADDRESS_MIRRORONCE:
3470 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3471 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3472 } else {
3473 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3474 wrapParm = GL_REPEAT;
3477 break;
3479 default:
3480 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3481 wrapParm = GL_REPEAT;
3484 switch (Type) {
3485 case D3DTSS_ADDRESSU:
3486 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3487 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3488 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3489 break;
3490 case D3DTSS_ADDRESSV:
3491 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3492 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3493 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3494 break;
3495 case D3DTSS_ADDRESSW:
3496 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3497 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3498 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3499 break;
3500 default: /* nop */
3501 break; /** stupic compilator */
3504 break;
3506 case D3DTSS_BORDERCOLOR :
3508 float col[4];
3509 D3DCOLORTOGLFLOAT4(Value, col);
3510 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3511 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3512 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3514 break;
3516 case D3DTSS_TEXCOORDINDEX :
3518 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3520 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3521 one flag, you can still specify an index value, which the system uses to
3522 determine the texture wrapping mode.
3523 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3524 means use the vertex position (camera-space) as the input texture coordinates
3525 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3526 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3527 to the TEXCOORDINDEX value */
3529 /**
3530 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3532 switch (Value & 0xFFFF0000) {
3533 case D3DTSS_TCI_PASSTHRU:
3534 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3535 glDisable(GL_TEXTURE_GEN_S);
3536 glDisable(GL_TEXTURE_GEN_T);
3537 glDisable(GL_TEXTURE_GEN_R);
3538 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3539 break;
3541 case D3DTSS_TCI_CAMERASPACEPOSITION:
3542 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3543 as the input texture coordinates for this stage's texture transformation. This
3544 equates roughly to EYE_LINEAR */
3546 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3547 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3548 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3549 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3550 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3552 glMatrixMode(GL_MODELVIEW);
3553 glPushMatrix();
3554 glLoadIdentity();
3555 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3556 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3557 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3558 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3559 glPopMatrix();
3561 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3562 glEnable(GL_TEXTURE_GEN_S);
3563 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3564 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3565 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3566 glEnable(GL_TEXTURE_GEN_T);
3567 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3568 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3569 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3570 glEnable(GL_TEXTURE_GEN_R);
3571 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3572 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3573 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3575 break;
3577 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3578 case D3DTSS_TCI_CAMERASPACENORMAL:
3580 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3581 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3582 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3583 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3584 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3586 glMatrixMode(GL_MODELVIEW);
3587 glPushMatrix();
3588 glLoadIdentity();
3589 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3590 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3591 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3592 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3593 glPopMatrix();
3595 glEnable(GL_TEXTURE_GEN_S);
3596 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3597 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3598 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3599 glEnable(GL_TEXTURE_GEN_T);
3600 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3601 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3602 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3603 glEnable(GL_TEXTURE_GEN_R);
3604 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3605 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3606 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3608 break;
3609 #endif
3611 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3612 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3615 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3616 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3617 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3618 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3619 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3621 glMatrixMode(GL_MODELVIEW);
3622 glPushMatrix();
3623 glLoadIdentity();
3624 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3625 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3626 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3627 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3628 glPopMatrix();
3630 glEnable(GL_TEXTURE_GEN_S);
3631 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3632 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3633 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3634 glEnable(GL_TEXTURE_GEN_T);
3635 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3636 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3637 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3638 glEnable(GL_TEXTURE_GEN_R);
3639 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3640 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3641 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3643 break;
3644 #endif
3646 /* Unhandled types: */
3647 default:
3648 /* Todo: */
3649 /* ? disable GL_TEXTURE_GEN_n ? */
3650 glDisable(GL_TEXTURE_GEN_S);
3651 glDisable(GL_TEXTURE_GEN_T);
3652 glDisable(GL_TEXTURE_GEN_R);
3653 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3654 break;
3657 break;
3659 /* Unhandled */
3660 case D3DTSS_BUMPENVMAT00 :
3661 case D3DTSS_BUMPENVMAT01 :
3662 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3663 break;
3664 case D3DTSS_BUMPENVMAT10 :
3665 case D3DTSS_BUMPENVMAT11 :
3666 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3667 break;
3669 case D3DTSS_TEXTURETRANSFORMFLAGS :
3670 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3671 break;
3673 case D3DTSS_BUMPENVLSCALE :
3674 case D3DTSS_BUMPENVLOFFSET :
3675 case D3DTSS_RESULTARG :
3676 default:
3677 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3678 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3681 LEAVE_GL();
3683 return D3D_OK;
3685 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3686 ICOM_THIS(IDirect3DDevice8Impl,iface);
3687 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3688 return D3D_OK;
3690 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3691 ICOM_THIS(IDirect3DDevice8Impl,iface);
3692 FIXME("(%p) : stub\n", This);
3693 return D3D_OK;
3695 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3696 ICOM_THIS(IDirect3DDevice8Impl,iface);
3697 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3698 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3699 if (PaletteNumber >= MAX_PALETTES) {
3700 return D3DERR_INVALIDCALL;
3702 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3703 return D3D_OK;
3705 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3706 ICOM_THIS(IDirect3DDevice8Impl,iface);
3707 if (PaletteNumber >= MAX_PALETTES) {
3708 return D3DERR_INVALIDCALL;
3710 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3711 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3712 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3713 return D3D_OK;
3715 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3716 ICOM_THIS(IDirect3DDevice8Impl,iface);
3717 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3718 if (PaletteNumber >= MAX_PALETTES) {
3719 return D3DERR_INVALIDCALL;
3721 This->currentPalette = PaletteNumber;
3723 #if defined(GL_EXT_paletted_texture)
3724 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3726 ENTER_GL();
3728 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3729 GL_RGBA, /* internal format */
3730 256, /* table size */
3731 GL_RGBA, /* table format */
3732 GL_UNSIGNED_BYTE, /* table type */
3733 This->palettes[PaletteNumber]);
3734 checkGLcall("glColorTableEXT");
3736 LEAVE_GL();
3738 } else {
3739 /* Delayed palette handling ... waiting for software emulation into preload code */
3741 #endif
3742 return D3D_OK;
3744 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3745 ICOM_THIS(IDirect3DDevice8Impl,iface);
3746 *PaletteNumber = This->currentPalette;
3747 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3748 return D3D_OK;
3750 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3752 ICOM_THIS(IDirect3DDevice8Impl,iface);
3753 This->StateBlock->streamIsUP = FALSE;
3755 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3756 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3758 return D3D_OK;
3760 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3761 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3762 UINT idxStride = 2;
3763 IDirect3DIndexBuffer8 *pIB;
3764 D3DINDEXBUFFER_DESC IdxBufDsc;
3766 ICOM_THIS(IDirect3DDevice8Impl,iface);
3767 pIB = This->StateBlock->pIndexData;
3768 This->StateBlock->streamIsUP = FALSE;
3770 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3771 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3772 minIndex, NumVertices, startIndex, primCount);
3774 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3775 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3776 idxStride = 2;
3777 } else {
3778 idxStride = 4;
3781 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3782 minIndex);
3784 return D3D_OK;
3786 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3787 ICOM_THIS(IDirect3DDevice8Impl,iface);
3789 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3790 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3792 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3794 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3795 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3796 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3797 This->StateBlock->streamIsUP = TRUE;
3798 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3799 This->StateBlock->stream_stride[0] = 0;
3800 This->StateBlock->stream_source[0] = NULL;
3802 /*stream zero settings set to null at end */
3803 return D3D_OK;
3805 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3806 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3807 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3808 UINT VertexStreamZeroStride) {
3809 int idxStride;
3810 ICOM_THIS(IDirect3DDevice8Impl,iface);
3811 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),
3812 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3814 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3815 if (IndexDataFormat == D3DFMT_INDEX16) {
3816 idxStride = 2;
3817 } else {
3818 idxStride = 4;
3821 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3822 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3823 This->StateBlock->streamIsUP = TRUE;
3824 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3825 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3827 /*stream zero settings set to null at end */
3828 This->StateBlock->stream_source[0] = NULL;
3829 This->StateBlock->stream_stride[0] = 0;
3830 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3832 return D3D_OK;
3834 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3835 ICOM_THIS(IDirect3DDevice8Impl,iface);
3836 FIXME("(%p) : stub\n", This); return D3D_OK;
3838 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3839 ICOM_THIS(IDirect3DDevice8Impl,iface);
3840 IDirect3DVertexShaderImpl* object;
3841 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3842 HRESULT res;
3843 UINT i;
3845 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3846 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3847 return D3DERR_INVALIDCALL;
3849 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3850 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3851 return D3DERR_OUTOFVIDEOMEMORY;
3854 /** Create the Vertex Shader */
3855 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3856 /** TODO: check FAILED(res) */
3858 /** Create and Bind the Vertex Shader Declaration */
3859 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3860 /** TODO: check FAILED(res) */
3862 VertexShaders[i] = object;
3863 VertexShaderDeclarations[i] = attached_decl;
3864 *pHandle = VS_HIGHESTFIXEDFXF + i;
3865 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3867 return D3D_OK;
3869 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3870 ICOM_THIS(IDirect3DDevice8Impl,iface);
3872 This->UpdateStateBlock->VertexShader = Handle;
3873 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3874 This->UpdateStateBlock->Set.vertexShader = TRUE;
3876 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3877 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3878 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3879 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3880 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3881 } else { /* use a fvf, so desactivate the vshader decl */
3882 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3883 This->UpdateStateBlock->vertexShaderDecl = NULL;
3884 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3885 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3887 /* Handle recording of state blocks */
3888 if (This->isRecordingState) {
3889 TRACE("Recording... not performing anything\n");
3890 return D3D_OK;
3893 * TODO: merge HAL shaders context switching from prototype
3895 return D3D_OK;
3897 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3898 ICOM_THIS(IDirect3DDevice8Impl,iface);
3899 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3900 *pHandle = This->StateBlock->VertexShader;
3901 return D3D_OK;
3904 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3905 ICOM_THIS(IDirect3DDevice8Impl,iface);
3906 IDirect3DVertexShaderImpl* object;
3907 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3909 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3910 return D3DERR_INVALIDCALL;
3914 * Delete Vertex Shader
3916 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3917 if (NULL == object) {
3918 return D3DERR_INVALIDCALL;
3920 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3921 /* TODO: check validity of object */
3922 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3923 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3924 HeapFree(GetProcessHeap(), 0, (void *)object);
3925 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3928 * Delete Vertex Shader Declaration
3930 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3931 if (NULL == attached_decl) {
3932 return D3DERR_INVALIDCALL;
3934 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3935 /* TODO: check validity of object */
3936 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3937 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3938 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3940 return D3D_OK;
3943 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3944 ICOM_THIS(IDirect3DDevice8Impl,iface);
3946 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3947 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3948 return D3DERR_INVALIDCALL;
3950 if (NULL == pConstantData) {
3951 return D3DERR_INVALIDCALL;
3953 if (ConstantCount > 1) {
3954 FLOAT* f = (FLOAT*)pConstantData;
3955 UINT i;
3956 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3957 for (i = 0; i < ConstantCount; ++i) {
3958 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3959 f += 4;
3961 } else {
3962 FLOAT* f = (FLOAT*) pConstantData;
3963 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3965 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3966 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3967 return D3D_OK;
3969 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3970 ICOM_THIS(IDirect3DDevice8Impl,iface);
3972 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3973 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3974 return D3DERR_INVALIDCALL;
3976 if (NULL == pConstantData) {
3977 return D3DERR_INVALIDCALL;
3979 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3980 return D3D_OK;
3982 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3983 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3984 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3986 attached_decl = VERTEX_SHADER_DECL(Handle);
3987 if (NULL == attached_decl) {
3988 return D3DERR_INVALIDCALL;
3990 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3992 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3993 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3994 IDirect3DVertexShaderImpl* object;
3996 object = VERTEX_SHADER(Handle);
3997 if (NULL == object) {
3998 return D3DERR_INVALIDCALL;
4000 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4003 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4004 ICOM_THIS(IDirect3DDevice8Impl,iface);
4005 IDirect3DIndexBuffer8 *oldIdxs;
4007 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4008 oldIdxs = This->StateBlock->pIndexData;
4010 This->UpdateStateBlock->Changed.Indices = TRUE;
4011 This->UpdateStateBlock->Set.Indices = TRUE;
4012 This->UpdateStateBlock->pIndexData = pIndexData;
4013 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4015 /* Handle recording of state blocks */
4016 if (This->isRecordingState) {
4017 TRACE("Recording... not performing anything\n");
4018 return D3D_OK;
4021 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4022 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4023 return D3D_OK;
4025 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4026 ICOM_THIS(IDirect3DDevice8Impl,iface);
4027 FIXME("(%p) : stub\n", This);
4029 *ppIndexData = This->StateBlock->pIndexData;
4030 /* up ref count on ppindexdata */
4031 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4032 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4034 return D3D_OK;
4036 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4037 ICOM_THIS(IDirect3DDevice8Impl,iface);
4038 IDirect3DPixelShaderImpl* object;
4039 HRESULT res;
4040 UINT i;
4042 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4043 if (NULL == pFunction || NULL == pHandle) {
4044 return D3DERR_INVALIDCALL;
4046 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4047 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4048 return D3DERR_OUTOFVIDEOMEMORY;
4051 /** Create the Pixel Shader */
4052 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4053 if (SUCCEEDED(res)) {
4054 PixelShaders[i] = object;
4055 *pHandle = VS_HIGHESTFIXEDFXF + i;
4056 return D3D_OK;
4058 *pHandle = 0xFFFFFFFF;
4059 return res;
4061 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4062 ICOM_THIS(IDirect3DDevice8Impl,iface);
4064 This->UpdateStateBlock->PixelShader = Handle;
4065 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4066 This->UpdateStateBlock->Set.pixelShader = TRUE;
4068 /* Handle recording of state blocks */
4069 if (This->isRecordingState) {
4070 TRACE_(d3d_shader)("Recording... not performing anything\n");
4071 return D3D_OK;
4074 /* FIXME: Quieten when not being used */
4075 if (Handle != 0) {
4076 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4077 } else {
4078 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4081 return D3D_OK;
4083 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4084 ICOM_THIS(IDirect3DDevice8Impl,iface);
4085 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4086 *pHandle = This->StateBlock->PixelShader;
4087 return D3D_OK;
4090 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4091 ICOM_THIS(IDirect3DDevice8Impl,iface);
4092 IDirect3DPixelShaderImpl* object;
4094 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4095 return D3DERR_INVALIDCALL;
4097 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4098 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4099 /* TODO: check validity of object before free */
4100 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4101 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4102 HeapFree(GetProcessHeap(), 0, (void *)object);
4103 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4105 return D3D_OK;
4108 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4109 ICOM_THIS(IDirect3DDevice8Impl,iface);
4111 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4112 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4113 return D3DERR_INVALIDCALL;
4115 if (NULL == pConstantData) {
4116 return D3DERR_INVALIDCALL;
4118 if (ConstantCount > 1) {
4119 FLOAT* f = (FLOAT*)pConstantData;
4120 UINT i;
4121 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4122 for (i = 0; i < ConstantCount; ++i) {
4123 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4124 f += 4;
4126 } else {
4127 FLOAT* f = (FLOAT*) pConstantData;
4128 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4130 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4131 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4132 return D3D_OK;
4134 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4135 ICOM_THIS(IDirect3DDevice8Impl,iface);
4137 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4138 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4139 return D3DERR_INVALIDCALL;
4141 if (NULL == pConstantData) {
4142 return D3DERR_INVALIDCALL;
4144 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4145 return D3D_OK;
4147 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4148 IDirect3DPixelShaderImpl* object;
4150 object = PIXEL_SHADER(Handle);
4151 if (NULL == object) {
4152 return D3DERR_INVALIDCALL;
4154 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4156 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4157 ICOM_THIS(IDirect3DDevice8Impl,iface);
4158 FIXME("(%p) : stub\n", This); return D3D_OK;
4160 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4161 ICOM_THIS(IDirect3DDevice8Impl,iface);
4162 FIXME("(%p) : stub\n", This); return D3D_OK;
4164 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4165 ICOM_THIS(IDirect3DDevice8Impl,iface);
4166 FIXME("(%p) : stub\n", This); return D3D_OK;
4169 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4170 IDirect3DVertexBuffer8 *oldSrc;
4171 ICOM_THIS(IDirect3DDevice8Impl,iface);
4173 oldSrc = This->StateBlock->stream_source[StreamNumber];
4174 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4176 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4177 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4178 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4179 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4181 /* Handle recording of state blocks */
4182 if (This->isRecordingState) {
4183 TRACE("Recording... not performing anything\n");
4184 return D3D_OK;
4187 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4188 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4189 return D3D_OK;
4191 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4192 ICOM_THIS(IDirect3DDevice8Impl,iface);
4193 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4194 *pStream = This->StateBlock->stream_source[StreamNumber];
4195 *pStride = This->StateBlock->stream_stride[StreamNumber];
4196 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4197 return D3D_OK;
4201 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4203 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4204 IDirect3DDevice8Impl_QueryInterface,
4205 IDirect3DDevice8Impl_AddRef,
4206 IDirect3DDevice8Impl_Release,
4207 IDirect3DDevice8Impl_TestCooperativeLevel,
4208 IDirect3DDevice8Impl_GetAvailableTextureMem,
4209 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4210 IDirect3DDevice8Impl_GetDirect3D,
4211 IDirect3DDevice8Impl_GetDeviceCaps,
4212 IDirect3DDevice8Impl_GetDisplayMode,
4213 IDirect3DDevice8Impl_GetCreationParameters,
4214 IDirect3DDevice8Impl_SetCursorProperties,
4215 IDirect3DDevice8Impl_SetCursorPosition,
4216 IDirect3DDevice8Impl_ShowCursor,
4217 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4218 IDirect3DDevice8Impl_Reset,
4219 IDirect3DDevice8Impl_Present,
4220 IDirect3DDevice8Impl_GetBackBuffer,
4221 IDirect3DDevice8Impl_GetRasterStatus,
4222 IDirect3DDevice8Impl_SetGammaRamp,
4223 IDirect3DDevice8Impl_GetGammaRamp,
4224 IDirect3DDevice8Impl_CreateTexture,
4225 IDirect3DDevice8Impl_CreateVolumeTexture,
4226 IDirect3DDevice8Impl_CreateCubeTexture,
4227 IDirect3DDevice8Impl_CreateVertexBuffer,
4228 IDirect3DDevice8Impl_CreateIndexBuffer,
4229 IDirect3DDevice8Impl_CreateRenderTarget,
4230 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4231 IDirect3DDevice8Impl_CreateImageSurface,
4232 IDirect3DDevice8Impl_CopyRects,
4233 IDirect3DDevice8Impl_UpdateTexture,
4234 IDirect3DDevice8Impl_GetFrontBuffer,
4235 IDirect3DDevice8Impl_SetRenderTarget,
4236 IDirect3DDevice8Impl_GetRenderTarget,
4237 IDirect3DDevice8Impl_GetDepthStencilSurface,
4238 IDirect3DDevice8Impl_BeginScene,
4239 IDirect3DDevice8Impl_EndScene,
4240 IDirect3DDevice8Impl_Clear,
4241 IDirect3DDevice8Impl_SetTransform,
4242 IDirect3DDevice8Impl_GetTransform,
4243 IDirect3DDevice8Impl_MultiplyTransform,
4244 IDirect3DDevice8Impl_SetViewport,
4245 IDirect3DDevice8Impl_GetViewport,
4246 IDirect3DDevice8Impl_SetMaterial,
4247 IDirect3DDevice8Impl_GetMaterial,
4248 IDirect3DDevice8Impl_SetLight,
4249 IDirect3DDevice8Impl_GetLight,
4250 IDirect3DDevice8Impl_LightEnable,
4251 IDirect3DDevice8Impl_GetLightEnable,
4252 IDirect3DDevice8Impl_SetClipPlane,
4253 IDirect3DDevice8Impl_GetClipPlane,
4254 IDirect3DDevice8Impl_SetRenderState,
4255 IDirect3DDevice8Impl_GetRenderState,
4256 IDirect3DDevice8Impl_BeginStateBlock,
4257 IDirect3DDevice8Impl_EndStateBlock,
4258 IDirect3DDevice8Impl_ApplyStateBlock,
4259 IDirect3DDevice8Impl_CaptureStateBlock,
4260 IDirect3DDevice8Impl_DeleteStateBlock,
4261 IDirect3DDevice8Impl_CreateStateBlock,
4262 IDirect3DDevice8Impl_SetClipStatus,
4263 IDirect3DDevice8Impl_GetClipStatus,
4264 IDirect3DDevice8Impl_GetTexture,
4265 IDirect3DDevice8Impl_SetTexture,
4266 IDirect3DDevice8Impl_GetTextureStageState,
4267 IDirect3DDevice8Impl_SetTextureStageState,
4268 IDirect3DDevice8Impl_ValidateDevice,
4269 IDirect3DDevice8Impl_GetInfo,
4270 IDirect3DDevice8Impl_SetPaletteEntries,
4271 IDirect3DDevice8Impl_GetPaletteEntries,
4272 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4273 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4274 IDirect3DDevice8Impl_DrawPrimitive,
4275 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4276 IDirect3DDevice8Impl_DrawPrimitiveUP,
4277 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4278 IDirect3DDevice8Impl_ProcessVertices,
4279 IDirect3DDevice8Impl_CreateVertexShader,
4280 IDirect3DDevice8Impl_SetVertexShader,
4281 IDirect3DDevice8Impl_GetVertexShader,
4282 IDirect3DDevice8Impl_DeleteVertexShader,
4283 IDirect3DDevice8Impl_SetVertexShaderConstant,
4284 IDirect3DDevice8Impl_GetVertexShaderConstant,
4285 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4286 IDirect3DDevice8Impl_GetVertexShaderFunction,
4287 IDirect3DDevice8Impl_SetStreamSource,
4288 IDirect3DDevice8Impl_GetStreamSource,
4289 IDirect3DDevice8Impl_SetIndices,
4290 IDirect3DDevice8Impl_GetIndices,
4291 IDirect3DDevice8Impl_CreatePixelShader,
4292 IDirect3DDevice8Impl_SetPixelShader,
4293 IDirect3DDevice8Impl_GetPixelShader,
4294 IDirect3DDevice8Impl_DeletePixelShader,
4295 IDirect3DDevice8Impl_SetPixelShaderConstant,
4296 IDirect3DDevice8Impl_GetPixelShaderConstant,
4297 IDirect3DDevice8Impl_GetPixelShaderFunction,
4298 IDirect3DDevice8Impl_DrawRectPatch,
4299 IDirect3DDevice8Impl_DrawTriPatch,
4300 IDirect3DDevice8Impl_DeletePatch
4303 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4305 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4306 ICOM_THIS(IDirect3DDevice8Impl,iface);
4308 ENTER_GL();
4310 #if 0
4311 if (This->glCtx != This->render_ctx) {
4312 glXDestroyContext(This->display, This->render_ctx);
4313 This->render_ctx = This->glCtx;
4315 #endif
4316 if (This->win != This->drawable) {
4317 glXDestroyPbuffer(This->display, This->drawable);
4318 This->drawable = This->win;
4321 LEAVE_GL();
4323 #endif
4324 return D3D_OK;
4327 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4328 IDirect3DSurface8* RenderSurface,
4329 IDirect3DSurface8* StencilSurface) {
4331 HRESULT ret = D3DERR_INVALIDCALL;
4333 * Currently only active for GLX >= 1.3
4334 * for others versions we'll have to use GLXPixmaps
4336 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4337 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4338 * so only check OpenGL version
4340 #if defined(GL_VERSION_1_3)
4341 GLXFBConfig* cfgs = NULL;
4342 int nCfgs = 0;
4343 int attribs[256];
4344 int nAttribs = 0;
4345 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4346 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4347 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4348 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4349 IDirect3DSurface8Impl* tmp;
4351 ICOM_THIS(IDirect3DDevice8Impl,iface);
4353 #define PUSH1(att) attribs[nAttribs++] = (att);
4354 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4356 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4357 PUSH2(GLX_X_RENDERABLE, TRUE);
4358 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4360 switch (BackBufferFormat) {
4361 /* color buffer */
4362 case D3DFMT_P8:
4363 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4364 PUSH2(GLX_BUFFER_SIZE, 8);
4365 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4366 break;
4368 case D3DFMT_R3G3B2:
4369 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4370 PUSH2(GLX_RED_SIZE, 3);
4371 PUSH2(GLX_GREEN_SIZE, 3);
4372 PUSH2(GLX_BLUE_SIZE, 2);
4373 break;
4375 case D3DFMT_A1R5G5B5:
4376 PUSH2(GLX_ALPHA_SIZE, 1);
4377 case D3DFMT_X1R5G5B5:
4378 PUSH2(GLX_RED_SIZE, 5);
4379 PUSH2(GLX_GREEN_SIZE, 5);
4380 PUSH2(GLX_BLUE_SIZE, 5);
4381 break;
4383 case D3DFMT_R5G6B5:
4384 PUSH2(GLX_RED_SIZE, 5);
4385 PUSH2(GLX_GREEN_SIZE, 6);
4386 PUSH2(GLX_BLUE_SIZE, 5);
4387 break;
4389 case D3DFMT_A4R4G4B4:
4390 PUSH2(GLX_ALPHA_SIZE, 4);
4391 case D3DFMT_X4R4G4B4:
4392 PUSH2(GLX_RED_SIZE, 4);
4393 PUSH2(GLX_GREEN_SIZE, 4);
4394 PUSH2(GLX_BLUE_SIZE, 4);
4395 break;
4397 case D3DFMT_A8R8G8B8:
4398 PUSH2(GLX_ALPHA_SIZE, 8);
4399 case D3DFMT_R8G8B8:
4400 case D3DFMT_X8R8G8B8:
4401 PUSH2(GLX_RED_SIZE, 8);
4402 PUSH2(GLX_GREEN_SIZE, 8);
4403 PUSH2(GLX_BLUE_SIZE, 8);
4404 break;
4406 default:
4407 break;
4410 switch (StencilBufferFormat) {
4411 case D3DFMT_D16_LOCKABLE:
4412 case D3DFMT_D16:
4413 PUSH2(GLX_DEPTH_SIZE, 16);
4414 break;
4416 case D3DFMT_D15S1:
4417 PUSH2(GLX_DEPTH_SIZE, 15);
4418 break;
4420 case D3DFMT_D24X8:
4421 PUSH2(GLX_DEPTH_SIZE, 24);
4422 break;
4424 case D3DFMT_D24X4S4:
4425 PUSH2(GLX_DEPTH_SIZE, 24);
4426 PUSH2(GLX_STENCIL_SIZE, 4);
4427 break;
4429 case D3DFMT_D24S8:
4430 PUSH2(GLX_DEPTH_SIZE, 24);
4431 PUSH2(GLX_STENCIL_SIZE, 8);
4432 break;
4434 case D3DFMT_D32:
4435 PUSH2(GLX_DEPTH_SIZE, 32);
4436 break;
4438 default:
4439 break;
4442 PUSH1(None);
4444 ENTER_GL();
4446 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4447 if (NULL != cfgs) {
4448 #ifdef EXTRA_TRACES
4449 int i;
4450 for (i = 0; i < nCfgs; ++i) {
4451 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4453 #endif
4455 if (NULL != This->renderTarget) {
4456 GLenum prev_read;
4457 glFlush();
4458 vcheckGLcall("glFlush");
4460 #ifdef EXTRA_TRACES
4461 /** very very usefull debug code */
4462 glXSwapBuffers(This->display, This->drawable);
4463 printf("Hit Enter to get next frame ...\n");
4464 getchar();
4465 #endif
4467 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4468 vcheckGLcall("glIntegerv");
4469 glReadBuffer(GL_BACK);
4470 vcheckGLcall("glReadBuffer");
4472 long j;
4473 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4475 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4476 pitch = pitch / 2;
4478 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4479 glReadPixels(0,
4480 This->renderTarget->myDesc.Height - j - 1,
4481 This->renderTarget->myDesc.Width,
4483 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4484 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4485 This->renderTarget->allocatedMemory + j * pitch);
4486 vcheckGLcall("glReadPixels");
4489 glReadBuffer(prev_read);
4490 vcheckGLcall("glReadBuffer");
4493 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4494 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4495 nAttribs = 0;
4496 PUSH2(GLX_PBUFFER_WIDTH, Width);
4497 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4498 PUSH1(None);
4499 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4501 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4502 if (NULL == This->render_ctx) {
4503 ERR("cannot create glxContext\n");
4506 glFlush();
4507 glXSwapBuffers(This->display, This->drawable);
4508 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4509 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4511 checkGLcall("glXMakeContextCurrent");
4514 tmp = This->renderTarget;
4515 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4516 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4517 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4519 tmp = This->stencilBufferTarget;
4520 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4521 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4522 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4524 ret = D3D_OK;
4526 } else {
4527 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4530 #undef PUSH1
4531 #undef PUSH2
4533 LEAVE_GL();
4535 #endif
4537 return ret;