d3d8: Render state additions.
[wine/multimedia.git] / dlls / d3d8 / device.c
blob363052d0ba23d4359392db7392ba119a85912c5e
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 :
3058 if(Value) {
3059 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3060 glEnable(GL_BLEND);
3061 checkGLcall("glEnable GL_BLEND");
3062 glEnable(GL_LINE_SMOOTH);
3063 checkGLcall("glEnable Gl_LINE_SMOOTH");
3064 } else {
3065 glDisable(GL_BLEND);
3066 checkGLcall("glDisable GL_BLEND");
3067 glDisable(GL_LINE_SMOOTH);
3068 checkGLcall("glDisable GL_LINE_SMOOTH");
3070 break;
3072 case D3DRS_WRAP0 :
3073 case D3DRS_WRAP1 :
3074 case D3DRS_WRAP2 :
3075 case D3DRS_WRAP3 :
3076 case D3DRS_WRAP4 :
3077 case D3DRS_WRAP5 :
3078 case D3DRS_WRAP6 :
3079 case D3DRS_WRAP7 :
3081 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3082 break;
3084 case D3DRS_POINTSPRITEENABLE :
3086 if(Value) {
3087 if(GL_SUPPORT(GL_ARB_point_sprite)) {
3088 glEnable(GL_POINT_SPRITE_ARB);
3089 checkGLcall("glEnable GL_POINT_SPRITE_ARB");
3090 } else {
3091 TRACE("Point sprites cannot be enabled in this version of opengl\n");
3093 } else {
3094 if(GL_SUPPORT(GL_ARB_point_sprite)) {
3095 glDisable(GL_POINT_SPRITE_ARB);
3096 checkGLcall("glDisable GL_POINT_SPRITE_ARB");
3097 } else {
3098 TRACE("Point sprites cannot be disabled in this version of opengl\n");
3101 break;
3103 case D3DRS_MULTISAMPLEANTIALIAS :
3105 if(Value) {
3106 if(GL_SUPPORT(GL_ARB_multisample)) {
3107 glEnable(GL_MULTISAMPLE_ARB);
3108 checkGLcall("glEnable GL_MULTISAMPLE_ARB");
3109 } else {
3110 TRACE("Multisample antialiasing cannot be enabled in this version of opengl\n");
3112 } else {
3113 if(GL_SUPPORT(GL_ARB_multisample)) {
3114 glDisable(GL_MULTISAMPLE_ARB);
3115 checkGLcall("glDisable GL_MULTISAMPLE_ARB");
3116 } else {
3117 TRACE("Multisample antialiasing cannot be disabled in this version of opengl\n");
3120 break;
3122 case D3DRS_MULTISAMPLEMASK :
3123 case D3DRS_PATCHEDGESTYLE :
3124 case D3DRS_PATCHSEGMENTS :
3125 case D3DRS_DEBUGMONITORTOKEN :
3126 case D3DRS_POSITIONORDER :
3127 case D3DRS_NORMALORDER :
3128 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3129 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3130 break;
3131 default:
3132 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3135 LEAVE_GL();
3137 return D3D_OK;
3139 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3140 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3141 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3142 *pValue = This->StateBlock->renderstate[State];
3143 return D3D_OK;
3145 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3146 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3148 TRACE("(%p)\n", This);
3150 return IDirect3DDeviceImpl_BeginStateBlock(This);
3152 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3153 IDirect3DStateBlockImpl* pSB;
3154 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3155 HRESULT res;
3157 TRACE("(%p)\n", This);
3159 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3160 *pToken = (DWORD) pSB;
3161 return res;
3164 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3165 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3166 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3168 TRACE("(%p)\n", This);
3170 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3173 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3174 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3175 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3177 TRACE("(%p)\n", This);
3179 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3181 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3182 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3183 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3185 TRACE("(%p)\n", This);
3187 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3190 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3191 IDirect3DStateBlockImpl* pSB;
3192 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3193 HRESULT res;
3195 TRACE("(%p) : for type %d\n", This, Type);
3197 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3198 *pToken = (DWORD) pSB;
3199 return res;
3202 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3203 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3204 FIXME("(%p) : stub\n", This);
3205 if (NULL == pClipStatus) {
3206 return D3DERR_INVALIDCALL;
3208 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3209 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3210 return D3D_OK;
3212 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3213 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3214 FIXME("(%p) : stub\n", This);
3215 if (NULL == pClipStatus) {
3216 return D3DERR_INVALIDCALL;
3218 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3219 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3220 return D3D_OK;
3222 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3223 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3224 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3225 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3226 if (*ppTexture)
3227 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3228 return D3D_OK;
3230 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3232 IDirect3DBaseTexture8 *oldTxt;
3233 BOOL reapplyStates = TRUE;
3234 INT oldTextureDimensions = -1;
3235 DWORD reapplyFlags = 0;
3237 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3238 D3DRESOURCETYPE textureType;
3240 oldTxt = This->UpdateStateBlock->textures[Stage];
3241 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3243 /* Reject invalid texture units */
3244 if (Stage >= GL_LIMITS(textures)) {
3245 TRACE("Attempt to access invalid texture rejected\n");
3246 return D3DERR_INVALIDCALL;
3249 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3250 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3251 This->UpdateStateBlock->textures[Stage] = pTexture;
3253 /* Handle recording of state blocks */
3254 if (This->isRecordingState) {
3255 TRACE("Recording... not performing anything\n");
3256 return D3D_OK;
3259 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3260 ENTER_GL();
3262 /* Make appropriate texture active */
3263 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3264 #if defined(GL_VERSION_1_3)
3265 glActiveTexture(GL_TEXTURE0 + Stage);
3266 checkGLcall("glActiveTexture");
3267 #else
3268 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3269 checkGLcall("glActiveTextureARB");
3270 #endif
3271 } else if (Stage>0) {
3272 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3275 /* Decrement the count of the previous texture */
3276 if (NULL != oldTxt) {
3277 IDirect3DBaseTexture8Impl_Release(oldTxt);
3280 if (NULL != pTexture) {
3281 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3283 /* Now setup the texture appropraitly */
3284 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3286 if (textureType == D3DRTYPE_TEXTURE) {
3287 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3288 TRACE("Skipping setting texture as old == new\n");
3289 reapplyStates = FALSE;
3290 } else {
3291 /* Standard 2D texture */
3292 TRACE("Standard 2d texture\n");
3293 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3295 /* Load up the texture now */
3296 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3298 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3299 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3300 TRACE("Skipping setting texture as old == new\n");
3301 reapplyStates = FALSE;
3302 } else {
3303 /* Standard 3D (volume) texture */
3304 TRACE("Standard 3d texture\n");
3305 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3307 /* Load up the texture now */
3308 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3310 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3311 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3312 TRACE("Skipping setting texture as old == new\n");
3313 reapplyStates = FALSE;
3314 } else {
3315 /* Standard Cube texture */
3316 TRACE("Standard Cube texture\n");
3317 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3319 /* Load up the texture now */
3320 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3322 } else {
3323 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3325 } else {
3326 TRACE("Setting to no texture (ie default texture)\n");
3327 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3328 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3329 checkGLcall("glBindTexture");
3330 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3333 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3334 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3335 glDisable(oldTextureDimensions);
3336 checkGLcall("Disable oldTextureDimensions");
3337 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3338 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3339 checkGLcall("glEnable new texture dimensions");
3342 /* If Alpha arg1 is texture then handle the special case when there changes between a
3343 texture and no texture - See comments in set_tex_op */
3344 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3345 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3347 reapplyFlags |= REAPPLY_ALPHAOP;
3352 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3353 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3354 if (reapplyStates) {
3355 setupTextureStates(iface, Stage, reapplyFlags);
3358 LEAVE_GL();
3360 return D3D_OK;
3363 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3364 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3365 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3366 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3367 return D3D_OK;
3370 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3371 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3372 union {
3373 float f;
3374 DWORD d;
3375 } tmpvalue;
3377 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3379 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3381 /* Reject invalid texture units */
3382 if (Stage >= GL_LIMITS(textures)) {
3383 TRACE("Attempt to access invalid texture rejected\n");
3384 return D3DERR_INVALIDCALL;
3387 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3388 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3389 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3391 /* Handle recording of state blocks */
3392 if (This->isRecordingState) {
3393 TRACE("Recording... not performing anything\n");
3394 return D3D_OK;
3397 ENTER_GL();
3399 /* Make appropriate texture active */
3400 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3401 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3402 #if defined(GL_VERSION_1_3)
3403 glActiveTexture(GL_TEXTURE0 + Stage);
3404 vcheckGLcall("glActiveTexture");
3405 #else
3406 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3407 vcheckGLcall("glActiveTextureARB");
3408 #endif
3409 } else if (Stage > 0) {
3410 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3413 switch (Type) {
3415 case D3DTSS_MINFILTER :
3416 case D3DTSS_MIPFILTER :
3418 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3419 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3420 GLint realVal = GL_LINEAR;
3422 if (ValueMIN == D3DTEXF_NONE) {
3423 /* Doesn't really make sense - Windows just seems to disable
3424 mipmapping when this occurs */
3425 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3426 realVal = GL_LINEAR;
3427 } else if (ValueMIN == D3DTEXF_POINT) {
3428 /* GL_NEAREST_* */
3429 if (ValueMIP == D3DTEXF_NONE) {
3430 realVal = GL_NEAREST;
3431 } else if (ValueMIP == D3DTEXF_POINT) {
3432 realVal = GL_NEAREST_MIPMAP_NEAREST;
3433 } else if (ValueMIP == D3DTEXF_LINEAR) {
3434 realVal = GL_NEAREST_MIPMAP_LINEAR;
3435 } else {
3436 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3437 realVal = GL_NEAREST;
3439 } else if (ValueMIN == D3DTEXF_LINEAR) {
3440 /* GL_LINEAR_* */
3441 if (ValueMIP == D3DTEXF_NONE) {
3442 realVal = GL_LINEAR;
3443 } else if (ValueMIP == D3DTEXF_POINT) {
3444 realVal = GL_LINEAR_MIPMAP_NEAREST;
3445 } else if (ValueMIP == D3DTEXF_LINEAR) {
3446 realVal = GL_LINEAR_MIPMAP_LINEAR;
3447 } else {
3448 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3449 realVal = GL_LINEAR;
3451 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3452 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3453 if (ValueMIP == D3DTEXF_NONE) {
3454 realVal = GL_LINEAR_MIPMAP_LINEAR;
3455 } else if (ValueMIP == D3DTEXF_POINT) {
3456 realVal = GL_LINEAR_MIPMAP_NEAREST;
3457 } else if (ValueMIP == D3DTEXF_LINEAR) {
3458 realVal = GL_LINEAR_MIPMAP_LINEAR;
3459 } else {
3460 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3461 realVal = GL_LINEAR;
3463 } else {
3464 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3465 realVal = GL_LINEAR;
3467 } else {
3468 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3469 realVal = GL_LINEAR_MIPMAP_LINEAR;
3472 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3473 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3474 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3476 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3478 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3479 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3480 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3481 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3482 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3485 break;
3487 case D3DTSS_MAGFILTER :
3489 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3490 GLint realVal = GL_NEAREST;
3492 if (ValueMAG == D3DTEXF_POINT) {
3493 realVal = GL_NEAREST;
3494 } else if (ValueMAG == D3DTEXF_LINEAR) {
3495 realVal = GL_LINEAR;
3496 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3497 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3498 realVal = GL_LINEAR;
3499 } else {
3500 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3501 realVal = GL_NEAREST;
3503 } else {
3504 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3505 realVal = GL_NEAREST;
3507 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3508 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3509 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3511 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3513 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3514 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3515 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3516 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3517 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3520 break;
3522 case D3DTSS_MAXMIPLEVEL :
3525 * Not really the same, but the more apprioprate than nothing
3527 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3528 GL_TEXTURE_BASE_LEVEL,
3529 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3530 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3532 break;
3534 case D3DTSS_MAXANISOTROPY :
3536 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3537 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3538 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3539 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3540 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3543 break;
3545 case D3DTSS_MIPMAPLODBIAS :
3547 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3548 tmpvalue.d = Value;
3549 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3550 GL_TEXTURE_LOD_BIAS_EXT,
3551 tmpvalue.f);
3552 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3555 break;
3557 case D3DTSS_ALPHAOP :
3558 case D3DTSS_COLOROP :
3561 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3562 /* TODO: Disable by making this and all later levels disabled */
3563 glDisable(GL_TEXTURE_1D);
3564 checkGLcall("Disable GL_TEXTURE_1D");
3565 glDisable(GL_TEXTURE_2D);
3566 checkGLcall("Disable GL_TEXTURE_2D");
3567 glDisable(GL_TEXTURE_3D);
3568 checkGLcall("Disable GL_TEXTURE_3D");
3569 break; /* Don't bother setting the texture operations */
3570 } else {
3571 /* Enable only the appropriate texture dimension */
3572 if (Type == D3DTSS_COLOROP) {
3573 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3574 glEnable(GL_TEXTURE_1D);
3575 checkGLcall("Enable GL_TEXTURE_1D");
3576 } else {
3577 glDisable(GL_TEXTURE_1D);
3578 checkGLcall("Disable GL_TEXTURE_1D");
3580 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3581 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3582 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3583 checkGLcall("Enable GL_TEXTURE_2D");
3584 } else {
3585 glEnable(GL_TEXTURE_2D);
3586 checkGLcall("Enable GL_TEXTURE_2D");
3588 } else {
3589 glDisable(GL_TEXTURE_2D);
3590 checkGLcall("Disable GL_TEXTURE_2D");
3592 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3593 glEnable(GL_TEXTURE_3D);
3594 checkGLcall("Enable GL_TEXTURE_3D");
3595 } else {
3596 glDisable(GL_TEXTURE_3D);
3597 checkGLcall("Disable GL_TEXTURE_3D");
3599 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3600 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3601 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3602 } else {
3603 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3604 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3608 /* Drop through... (Except disable case) */
3609 case D3DTSS_COLORARG0 :
3610 case D3DTSS_COLORARG1 :
3611 case D3DTSS_COLORARG2 :
3612 case D3DTSS_ALPHAARG0 :
3613 case D3DTSS_ALPHAARG1 :
3614 case D3DTSS_ALPHAARG2 :
3616 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3617 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3618 if (isAlphaArg) {
3619 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3620 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3621 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3622 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3623 } else {
3624 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3625 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3626 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3627 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3630 break;
3633 case D3DTSS_ADDRESSU :
3634 case D3DTSS_ADDRESSV :
3635 case D3DTSS_ADDRESSW :
3637 GLint wrapParm = GL_REPEAT;
3639 switch (Value) {
3640 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3641 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3642 case D3DTADDRESS_BORDER:
3644 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3645 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3646 } else {
3647 /* FIXME: Not right, but better */
3648 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3649 wrapParm = GL_REPEAT;
3652 break;
3653 case D3DTADDRESS_MIRROR:
3655 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3656 wrapParm = GL_MIRRORED_REPEAT_ARB;
3657 } else {
3658 /* Unsupported in OpenGL pre-1.4 */
3659 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3660 wrapParm = GL_REPEAT;
3663 break;
3664 case D3DTADDRESS_MIRRORONCE:
3666 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3667 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3668 } else {
3669 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3670 wrapParm = GL_REPEAT;
3673 break;
3675 default:
3676 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3677 wrapParm = GL_REPEAT;
3680 switch (Type) {
3681 case D3DTSS_ADDRESSU:
3682 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3683 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3684 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3685 break;
3686 case D3DTSS_ADDRESSV:
3687 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3688 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3689 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3690 break;
3691 case D3DTSS_ADDRESSW:
3692 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3693 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3694 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3695 break;
3696 default: /* nop */
3697 break; /** stupic compilator */
3700 break;
3702 case D3DTSS_BORDERCOLOR :
3704 float col[4];
3705 D3DCOLORTOGLFLOAT4(Value, col);
3706 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3707 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3708 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3710 break;
3712 case D3DTSS_TEXCOORDINDEX :
3714 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3716 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3717 one flag, you can still specify an index value, which the system uses to
3718 determine the texture wrapping mode.
3719 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3720 means use the vertex position (camera-space) as the input texture coordinates
3721 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3722 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3723 to the TEXCOORDINDEX value */
3725 /**
3726 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3728 switch (Value & 0xFFFF0000) {
3729 case D3DTSS_TCI_PASSTHRU:
3730 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3731 glDisable(GL_TEXTURE_GEN_S);
3732 glDisable(GL_TEXTURE_GEN_T);
3733 glDisable(GL_TEXTURE_GEN_R);
3734 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3735 break;
3737 case D3DTSS_TCI_CAMERASPACEPOSITION:
3738 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3739 as the input texture coordinates for this stage's texture transformation. This
3740 equates roughly to EYE_LINEAR */
3742 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3743 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3744 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3745 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3746 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3748 glMatrixMode(GL_MODELVIEW);
3749 glPushMatrix();
3750 glLoadIdentity();
3751 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3752 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3753 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3754 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3755 glPopMatrix();
3757 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3758 glEnable(GL_TEXTURE_GEN_S);
3759 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3760 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3761 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3762 glEnable(GL_TEXTURE_GEN_T);
3763 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3764 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3765 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3766 glEnable(GL_TEXTURE_GEN_R);
3767 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3768 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3769 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3771 break;
3773 case D3DTSS_TCI_CAMERASPACENORMAL:
3775 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3776 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3777 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3778 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3779 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3780 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3782 glMatrixMode(GL_MODELVIEW);
3783 glPushMatrix();
3784 glLoadIdentity();
3785 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3786 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3787 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3788 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3789 glPopMatrix();
3791 glEnable(GL_TEXTURE_GEN_S);
3792 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3793 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3794 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3795 glEnable(GL_TEXTURE_GEN_T);
3796 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3797 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3798 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3799 glEnable(GL_TEXTURE_GEN_R);
3800 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3801 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3802 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3805 break;
3807 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3809 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3810 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3811 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3812 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3813 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3814 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3816 glMatrixMode(GL_MODELVIEW);
3817 glPushMatrix();
3818 glLoadIdentity();
3819 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3820 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3821 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3822 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3823 glPopMatrix();
3825 glEnable(GL_TEXTURE_GEN_S);
3826 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3827 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3828 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3829 glEnable(GL_TEXTURE_GEN_T);
3830 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3831 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3832 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3833 glEnable(GL_TEXTURE_GEN_R);
3834 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3835 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3836 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3839 break;
3841 /* Unhandled types: */
3842 default:
3843 /* Todo: */
3844 /* ? disable GL_TEXTURE_GEN_n ? */
3845 glDisable(GL_TEXTURE_GEN_S);
3846 glDisable(GL_TEXTURE_GEN_T);
3847 glDisable(GL_TEXTURE_GEN_R);
3848 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3849 break;
3852 break;
3854 /* Unhandled */
3855 case D3DTSS_TEXTURETRANSFORMFLAGS :
3856 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3857 break;
3859 case D3DTSS_BUMPENVMAT00 :
3860 case D3DTSS_BUMPENVMAT01 :
3861 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3862 break;
3863 case D3DTSS_BUMPENVMAT10 :
3864 case D3DTSS_BUMPENVMAT11 :
3865 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3866 break;
3868 case D3DTSS_BUMPENVLSCALE :
3869 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3870 break;
3872 case D3DTSS_BUMPENVLOFFSET :
3873 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3874 break;
3876 case D3DTSS_RESULTARG :
3877 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3878 break;
3880 default:
3881 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3882 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3885 LEAVE_GL();
3887 return D3D_OK;
3889 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3890 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3891 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3892 return D3D_OK;
3894 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3895 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3896 FIXME("(%p) : stub\n", This);
3897 return D3D_OK;
3899 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3900 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3901 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3902 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3903 if (PaletteNumber >= MAX_PALETTES) {
3904 return D3DERR_INVALIDCALL;
3906 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3907 return D3D_OK;
3909 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3910 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3911 if (PaletteNumber >= MAX_PALETTES) {
3912 return D3DERR_INVALIDCALL;
3914 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3915 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3916 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3917 return D3D_OK;
3919 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3920 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3921 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3922 if (PaletteNumber >= MAX_PALETTES) {
3923 return D3DERR_INVALIDCALL;
3925 This->currentPalette = PaletteNumber;
3927 #if defined(GL_EXT_paletted_texture)
3928 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3930 ENTER_GL();
3932 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3933 GL_RGBA, /* internal format */
3934 256, /* table size */
3935 GL_RGBA, /* table format */
3936 GL_UNSIGNED_BYTE, /* table type */
3937 This->palettes[PaletteNumber]);
3938 checkGLcall("glColorTableEXT");
3940 LEAVE_GL();
3942 } else {
3943 /* Delayed palette handling ... waiting for software emulation into preload code */
3945 #endif
3946 return D3D_OK;
3948 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3949 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3950 *PaletteNumber = This->currentPalette;
3951 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3952 return D3D_OK;
3954 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3956 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3957 This->StateBlock->streamIsUP = FALSE;
3959 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3960 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3962 return D3D_OK;
3964 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3965 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3966 UINT idxStride = 2;
3967 IDirect3DIndexBuffer8 *pIB;
3968 D3DINDEXBUFFER_DESC IdxBufDsc;
3970 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3971 pIB = This->StateBlock->pIndexData;
3972 This->StateBlock->streamIsUP = FALSE;
3974 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
3975 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3976 minIndex, NumVertices, startIndex, primCount);
3978 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3979 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3980 idxStride = 2;
3981 } else {
3982 idxStride = 4;
3985 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3986 minIndex);
3988 return D3D_OK;
3990 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3991 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3993 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3994 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3996 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3998 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3999 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
4000 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4001 This->StateBlock->streamIsUP = TRUE;
4002 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4003 This->StateBlock->stream_stride[0] = 0;
4004 This->StateBlock->stream_source[0] = NULL;
4006 /*stream zero settings set to null at end */
4007 return D3D_OK;
4009 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4010 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4011 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4012 UINT VertexStreamZeroStride) {
4013 int idxStride;
4014 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4015 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),
4016 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4018 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4019 if (IndexDataFormat == D3DFMT_INDEX16) {
4020 idxStride = 2;
4021 } else {
4022 idxStride = 4;
4025 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
4026 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
4027 This->StateBlock->streamIsUP = TRUE;
4028 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4029 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4031 /*stream zero settings set to null at end */
4032 This->StateBlock->stream_source[0] = NULL;
4033 This->StateBlock->stream_stride[0] = 0;
4034 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4036 return D3D_OK;
4038 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4039 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4040 FIXME("(%p) : stub\n", This); return D3D_OK;
4042 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4043 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4044 IDirect3DVertexShaderImpl* object;
4045 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4046 HRESULT res;
4047 UINT i;
4049 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
4050 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4051 return D3DERR_INVALIDCALL;
4053 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4054 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4055 return D3DERR_OUTOFVIDEOMEMORY;
4058 /** Create the Vertex Shader */
4059 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4060 /** TODO: check FAILED(res) */
4062 /** Create and Bind the Vertex Shader Declaration */
4063 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4064 /** TODO: check FAILED(res) */
4066 VertexShaders[i] = object;
4067 VertexShaderDeclarations[i] = attached_decl;
4068 *pHandle = VS_HIGHESTFIXEDFXF + i;
4069 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4071 return D3D_OK;
4073 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4074 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4076 This->UpdateStateBlock->VertexShader = Handle;
4077 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4078 This->UpdateStateBlock->Set.vertexShader = TRUE;
4080 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4081 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4082 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4083 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4084 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4085 } else { /* use a fvf, so desactivate the vshader decl */
4086 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4087 This->UpdateStateBlock->vertexShaderDecl = NULL;
4088 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4089 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4091 /* Handle recording of state blocks */
4092 if (This->isRecordingState) {
4093 TRACE("Recording... not performing anything\n");
4094 return D3D_OK;
4097 * TODO: merge HAL shaders context switching from prototype
4099 return D3D_OK;
4101 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4102 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4103 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4104 *pHandle = This->StateBlock->VertexShader;
4105 return D3D_OK;
4108 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4109 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4110 IDirect3DVertexShaderImpl* object;
4111 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4113 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4114 return D3DERR_INVALIDCALL;
4118 * Delete Vertex Shader
4120 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4121 if (NULL == object) {
4122 return D3DERR_INVALIDCALL;
4124 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4125 /* TODO: check validity of object */
4126 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4127 if (object->prgId != 0) {
4128 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4130 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4131 HeapFree(GetProcessHeap(), 0, (void *)object);
4132 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4135 * Delete Vertex Shader Declaration
4137 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4138 if (NULL == attached_decl) {
4139 return D3DERR_INVALIDCALL;
4141 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4142 /* TODO: check validity of object */
4143 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4144 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4145 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4147 return D3D_OK;
4150 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4151 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4153 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4154 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4155 return D3DERR_INVALIDCALL;
4157 if (NULL == pConstantData) {
4158 return D3DERR_INVALIDCALL;
4160 if (ConstantCount > 1) {
4161 const FLOAT* f = (const FLOAT*)pConstantData;
4162 UINT i;
4163 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4164 for (i = 0; i < ConstantCount; ++i) {
4165 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4166 f += 4;
4168 } else {
4169 const FLOAT* f = (const FLOAT*) pConstantData;
4170 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4172 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4173 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4174 return D3D_OK;
4176 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4177 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4179 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4180 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4181 return D3DERR_INVALIDCALL;
4183 if (NULL == pConstantData) {
4184 return D3DERR_INVALIDCALL;
4186 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4187 return D3D_OK;
4189 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4190 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4191 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4193 attached_decl = VERTEX_SHADER_DECL(Handle);
4194 if (NULL == attached_decl) {
4195 return D3DERR_INVALIDCALL;
4197 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4199 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4200 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4201 IDirect3DVertexShaderImpl* object;
4203 object = VERTEX_SHADER(Handle);
4204 if (NULL == object) {
4205 return D3DERR_INVALIDCALL;
4207 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4210 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4211 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4212 IDirect3DIndexBuffer8 *oldIdxs;
4214 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4215 oldIdxs = This->StateBlock->pIndexData;
4217 This->UpdateStateBlock->Changed.Indices = TRUE;
4218 This->UpdateStateBlock->Set.Indices = TRUE;
4219 This->UpdateStateBlock->pIndexData = pIndexData;
4220 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4222 /* Handle recording of state blocks */
4223 if (This->isRecordingState) {
4224 TRACE("Recording... not performing anything\n");
4225 return D3D_OK;
4228 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRefInt(This->StateBlock->pIndexData);
4229 if (oldIdxs) IDirect3DIndexBuffer8Impl_ReleaseInt(oldIdxs);
4230 return D3D_OK;
4232 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4233 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4234 FIXME("(%p) : stub\n", This);
4236 *ppIndexData = This->StateBlock->pIndexData;
4237 /* up ref count on ppindexdata */
4238 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4239 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4241 return D3D_OK;
4243 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4244 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4245 IDirect3DPixelShaderImpl* object;
4246 HRESULT res;
4247 UINT i;
4249 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4250 if (NULL == pFunction || NULL == pHandle) {
4251 return D3DERR_INVALIDCALL;
4253 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4254 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4255 return D3DERR_OUTOFVIDEOMEMORY;
4258 /** Create the Pixel Shader */
4259 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4260 if (SUCCEEDED(res)) {
4261 PixelShaders[i] = object;
4262 *pHandle = VS_HIGHESTFIXEDFXF + i;
4263 return D3D_OK;
4265 *pHandle = 0xFFFFFFFF;
4266 return res;
4269 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4270 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4272 This->UpdateStateBlock->PixelShader = Handle;
4273 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4274 This->UpdateStateBlock->Set.pixelShader = TRUE;
4276 /* Handle recording of state blocks */
4277 if (This->isRecordingState) {
4278 TRACE_(d3d_shader)("Recording... not performing anything\n");
4279 return D3D_OK;
4282 if (Handle != 0) {
4283 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4284 } else {
4285 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4288 return D3D_OK;
4291 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4292 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4293 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4294 *pHandle = This->StateBlock->PixelShader;
4295 return D3D_OK;
4298 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4299 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4300 IDirect3DPixelShaderImpl* object;
4302 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4303 return D3DERR_INVALIDCALL;
4305 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4306 if (NULL == object) {
4307 return D3DERR_INVALIDCALL;
4309 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4310 /* TODO: check validity of object before free */
4311 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4312 if (object->prgId != 0) {
4313 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4315 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4316 HeapFree(GetProcessHeap(), 0, (void *)object);
4317 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4319 return D3D_OK;
4322 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4323 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4325 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4326 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4327 return D3DERR_INVALIDCALL;
4329 if (NULL == pConstantData) {
4330 return D3DERR_INVALIDCALL;
4332 if (ConstantCount > 1) {
4333 const FLOAT* f = (const FLOAT*)pConstantData;
4334 UINT i;
4335 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4336 for (i = 0; i < ConstantCount; ++i) {
4337 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4338 f += 4;
4340 } else {
4341 const FLOAT* f = (const FLOAT*) pConstantData;
4342 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4344 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4345 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4346 return D3D_OK;
4348 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4349 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4351 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4352 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4353 return D3DERR_INVALIDCALL;
4355 if (NULL == pConstantData) {
4356 return D3DERR_INVALIDCALL;
4358 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4359 return D3D_OK;
4361 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4362 IDirect3DPixelShaderImpl* object;
4364 object = PIXEL_SHADER(Handle);
4365 if (NULL == object) {
4366 return D3DERR_INVALIDCALL;
4368 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4370 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4371 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4372 FIXME("(%p) : stub\n", This); return D3D_OK;
4374 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4375 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4376 FIXME("(%p) : stub\n", This); return D3D_OK;
4378 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4379 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4380 FIXME("(%p) : stub\n", This); return D3D_OK;
4383 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4384 IDirect3DVertexBuffer8 *oldSrc;
4385 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4387 oldSrc = This->StateBlock->stream_source[StreamNumber];
4388 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4390 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4391 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4392 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4393 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4395 /* Handle recording of state blocks */
4396 if (This->isRecordingState) {
4397 TRACE("Recording... not performing anything\n");
4398 return D3D_OK;
4401 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRefInt(pStreamData);
4402 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_ReleaseInt(oldSrc);
4403 return D3D_OK;
4405 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4406 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4407 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4408 *pStream = This->StateBlock->stream_source[StreamNumber];
4409 *pStride = This->StateBlock->stream_stride[StreamNumber];
4410 if (*pStream != NULL) IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4411 return D3D_OK;
4415 const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4417 IDirect3DDevice8Impl_QueryInterface,
4418 IDirect3DDevice8Impl_AddRef,
4419 IDirect3DDevice8Impl_Release,
4420 IDirect3DDevice8Impl_TestCooperativeLevel,
4421 IDirect3DDevice8Impl_GetAvailableTextureMem,
4422 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4423 IDirect3DDevice8Impl_GetDirect3D,
4424 IDirect3DDevice8Impl_GetDeviceCaps,
4425 IDirect3DDevice8Impl_GetDisplayMode,
4426 IDirect3DDevice8Impl_GetCreationParameters,
4427 IDirect3DDevice8Impl_SetCursorProperties,
4428 IDirect3DDevice8Impl_SetCursorPosition,
4429 IDirect3DDevice8Impl_ShowCursor,
4430 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4431 IDirect3DDevice8Impl_Reset,
4432 IDirect3DDevice8Impl_Present,
4433 IDirect3DDevice8Impl_GetBackBuffer,
4434 IDirect3DDevice8Impl_GetRasterStatus,
4435 IDirect3DDevice8Impl_SetGammaRamp,
4436 IDirect3DDevice8Impl_GetGammaRamp,
4437 IDirect3DDevice8Impl_CreateTexture,
4438 IDirect3DDevice8Impl_CreateVolumeTexture,
4439 IDirect3DDevice8Impl_CreateCubeTexture,
4440 IDirect3DDevice8Impl_CreateVertexBuffer,
4441 IDirect3DDevice8Impl_CreateIndexBuffer,
4442 IDirect3DDevice8Impl_CreateRenderTarget,
4443 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4444 IDirect3DDevice8Impl_CreateImageSurface,
4445 IDirect3DDevice8Impl_CopyRects,
4446 IDirect3DDevice8Impl_UpdateTexture,
4447 IDirect3DDevice8Impl_GetFrontBuffer,
4448 IDirect3DDevice8Impl_SetRenderTarget,
4449 IDirect3DDevice8Impl_GetRenderTarget,
4450 IDirect3DDevice8Impl_GetDepthStencilSurface,
4451 IDirect3DDevice8Impl_BeginScene,
4452 IDirect3DDevice8Impl_EndScene,
4453 IDirect3DDevice8Impl_Clear,
4454 IDirect3DDevice8Impl_SetTransform,
4455 IDirect3DDevice8Impl_GetTransform,
4456 IDirect3DDevice8Impl_MultiplyTransform,
4457 IDirect3DDevice8Impl_SetViewport,
4458 IDirect3DDevice8Impl_GetViewport,
4459 IDirect3DDevice8Impl_SetMaterial,
4460 IDirect3DDevice8Impl_GetMaterial,
4461 IDirect3DDevice8Impl_SetLight,
4462 IDirect3DDevice8Impl_GetLight,
4463 IDirect3DDevice8Impl_LightEnable,
4464 IDirect3DDevice8Impl_GetLightEnable,
4465 IDirect3DDevice8Impl_SetClipPlane,
4466 IDirect3DDevice8Impl_GetClipPlane,
4467 IDirect3DDevice8Impl_SetRenderState,
4468 IDirect3DDevice8Impl_GetRenderState,
4469 IDirect3DDevice8Impl_BeginStateBlock,
4470 IDirect3DDevice8Impl_EndStateBlock,
4471 IDirect3DDevice8Impl_ApplyStateBlock,
4472 IDirect3DDevice8Impl_CaptureStateBlock,
4473 IDirect3DDevice8Impl_DeleteStateBlock,
4474 IDirect3DDevice8Impl_CreateStateBlock,
4475 IDirect3DDevice8Impl_SetClipStatus,
4476 IDirect3DDevice8Impl_GetClipStatus,
4477 IDirect3DDevice8Impl_GetTexture,
4478 IDirect3DDevice8Impl_SetTexture,
4479 IDirect3DDevice8Impl_GetTextureStageState,
4480 IDirect3DDevice8Impl_SetTextureStageState,
4481 IDirect3DDevice8Impl_ValidateDevice,
4482 IDirect3DDevice8Impl_GetInfo,
4483 IDirect3DDevice8Impl_SetPaletteEntries,
4484 IDirect3DDevice8Impl_GetPaletteEntries,
4485 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4486 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4487 IDirect3DDevice8Impl_DrawPrimitive,
4488 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4489 IDirect3DDevice8Impl_DrawPrimitiveUP,
4490 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4491 IDirect3DDevice8Impl_ProcessVertices,
4492 IDirect3DDevice8Impl_CreateVertexShader,
4493 IDirect3DDevice8Impl_SetVertexShader,
4494 IDirect3DDevice8Impl_GetVertexShader,
4495 IDirect3DDevice8Impl_DeleteVertexShader,
4496 IDirect3DDevice8Impl_SetVertexShaderConstant,
4497 IDirect3DDevice8Impl_GetVertexShaderConstant,
4498 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4499 IDirect3DDevice8Impl_GetVertexShaderFunction,
4500 IDirect3DDevice8Impl_SetStreamSource,
4501 IDirect3DDevice8Impl_GetStreamSource,
4502 IDirect3DDevice8Impl_SetIndices,
4503 IDirect3DDevice8Impl_GetIndices,
4504 IDirect3DDevice8Impl_CreatePixelShader,
4505 IDirect3DDevice8Impl_SetPixelShader,
4506 IDirect3DDevice8Impl_GetPixelShader,
4507 IDirect3DDevice8Impl_DeletePixelShader,
4508 IDirect3DDevice8Impl_SetPixelShaderConstant,
4509 IDirect3DDevice8Impl_GetPixelShaderConstant,
4510 IDirect3DDevice8Impl_GetPixelShaderFunction,
4511 IDirect3DDevice8Impl_DrawRectPatch,
4512 IDirect3DDevice8Impl_DrawTriPatch,
4513 IDirect3DDevice8Impl_DeletePatch
4516 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4518 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4519 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4521 ENTER_GL();
4523 #if 0
4524 if (This->glCtx != This->render_ctx) {
4525 glXDestroyContext(This->display, This->render_ctx);
4526 This->render_ctx = This->glCtx;
4528 #endif
4529 if (This->win != This->drawable) {
4530 glXDestroyPbuffer(This->display, This->drawable);
4531 This->drawable = This->win;
4534 LEAVE_GL();
4536 #endif
4537 return D3D_OK;
4540 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4541 IDirect3DSurface8* RenderSurface,
4542 IDirect3DSurface8* StencilSurface) {
4544 HRESULT ret = D3DERR_INVALIDCALL;
4546 * Currently only active for GLX >= 1.3
4547 * for others versions we'll have to use GLXPixmaps
4549 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4550 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4551 * so only check OpenGL version
4553 #if defined(GL_VERSION_1_3)
4554 GLXFBConfig* cfgs = NULL;
4555 int nCfgs = 0;
4556 int attribs[256];
4557 int nAttribs = 0;
4558 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4559 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4560 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4561 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4562 IDirect3DSurface8Impl* tmp;
4564 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4566 #define PUSH1(att) attribs[nAttribs++] = (att);
4567 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4569 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4570 PUSH2(GLX_X_RENDERABLE, TRUE);
4571 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4573 switch (BackBufferFormat) {
4574 /* color buffer */
4575 case D3DFMT_P8:
4576 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4577 PUSH2(GLX_BUFFER_SIZE, 8);
4578 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4579 break;
4581 case D3DFMT_R3G3B2:
4582 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4583 PUSH2(GLX_RED_SIZE, 3);
4584 PUSH2(GLX_GREEN_SIZE, 3);
4585 PUSH2(GLX_BLUE_SIZE, 2);
4586 break;
4588 case D3DFMT_A1R5G5B5:
4589 PUSH2(GLX_ALPHA_SIZE, 1);
4590 case D3DFMT_X1R5G5B5:
4591 PUSH2(GLX_RED_SIZE, 5);
4592 PUSH2(GLX_GREEN_SIZE, 5);
4593 PUSH2(GLX_BLUE_SIZE, 5);
4594 break;
4596 case D3DFMT_R5G6B5:
4597 PUSH2(GLX_RED_SIZE, 5);
4598 PUSH2(GLX_GREEN_SIZE, 6);
4599 PUSH2(GLX_BLUE_SIZE, 5);
4600 break;
4602 case D3DFMT_A4R4G4B4:
4603 PUSH2(GLX_ALPHA_SIZE, 4);
4604 case D3DFMT_X4R4G4B4:
4605 PUSH2(GLX_RED_SIZE, 4);
4606 PUSH2(GLX_GREEN_SIZE, 4);
4607 PUSH2(GLX_BLUE_SIZE, 4);
4608 break;
4610 case D3DFMT_A8R8G8B8:
4611 PUSH2(GLX_ALPHA_SIZE, 8);
4612 case D3DFMT_R8G8B8:
4613 case D3DFMT_X8R8G8B8:
4614 PUSH2(GLX_RED_SIZE, 8);
4615 PUSH2(GLX_GREEN_SIZE, 8);
4616 PUSH2(GLX_BLUE_SIZE, 8);
4617 break;
4619 default:
4620 break;
4623 switch (StencilBufferFormat) {
4624 case D3DFMT_D16_LOCKABLE:
4625 case D3DFMT_D16:
4626 PUSH2(GLX_DEPTH_SIZE, 16);
4627 break;
4629 case D3DFMT_D15S1:
4630 PUSH2(GLX_DEPTH_SIZE, 15);
4631 break;
4633 case D3DFMT_D24X8:
4634 PUSH2(GLX_DEPTH_SIZE, 24);
4635 break;
4637 case D3DFMT_D24X4S4:
4638 PUSH2(GLX_DEPTH_SIZE, 24);
4639 PUSH2(GLX_STENCIL_SIZE, 4);
4640 break;
4642 case D3DFMT_D24S8:
4643 PUSH2(GLX_DEPTH_SIZE, 24);
4644 PUSH2(GLX_STENCIL_SIZE, 8);
4645 break;
4647 case D3DFMT_D32:
4648 PUSH2(GLX_DEPTH_SIZE, 32);
4649 break;
4651 default:
4652 break;
4655 PUSH1(None);
4657 ENTER_GL();
4659 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4660 if (NULL != cfgs) {
4661 #ifdef EXTRA_TRACES
4662 int i;
4663 for (i = 0; i < nCfgs; ++i) {
4664 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4666 #endif
4668 if (NULL != This->renderTarget) {
4669 /*GLenum prev_read; */
4670 glFlush();
4671 vcheckGLcall("glFlush");
4673 #ifdef EXTRA_TRACES
4674 /** very very useful debug code */
4675 glXSwapBuffers(This->display, This->drawable);
4676 printf("Hit Enter to get next frame ...\n");
4677 getchar();
4678 #endif
4680 #if 0
4681 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4682 vcheckGLcall("glIntegerv");
4683 glReadBuffer(GL_BACK);
4684 vcheckGLcall("glReadBuffer");
4686 long j;
4687 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4689 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4690 pitch = pitch / 2;
4692 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4693 glReadPixels(0,
4694 This->renderTarget->myDesc.Height - j - 1,
4695 This->renderTarget->myDesc.Width,
4697 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4698 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4699 This->renderTarget->allocatedMemory + j * pitch);
4700 vcheckGLcall("glReadPixels");
4703 glReadBuffer(prev_read);
4704 vcheckGLcall("glReadBuffer");
4705 #endif
4708 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4709 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4710 nAttribs = 0;
4711 PUSH2(GLX_PBUFFER_WIDTH, Width);
4712 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4713 PUSH1(None);
4714 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4716 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4717 if (NULL == This->render_ctx) {
4718 ERR("cannot create glxContext\n");
4721 glFlush();
4722 glXSwapBuffers(This->display, This->drawable);
4723 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4724 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4726 checkGLcall("glXMakeContextCurrent");
4729 tmp = This->renderTarget;
4730 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4731 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4732 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4734 tmp = This->stencilBufferTarget;
4735 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4736 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4737 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4740 DWORD value;
4741 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4742 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4743 /* Force updating the cull mode */
4744 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4745 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4746 /* Force updating projection matrix */
4747 This->last_was_rhw = FALSE;
4748 This->proj_valid = FALSE;
4751 ret = D3D_OK;
4753 } else {
4754 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4757 #undef PUSH1
4758 #undef PUSH2
4760 LEAVE_GL();
4762 #endif
4764 return ret;