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