Implemented DllCanUnloadNow.
[wine/multimedia.git] / dlls / d3d8 / device.c
blob5b487d344f6843b8c23c664ece9d7af5ec67fe65
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 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 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
301 return ++(This->ref);
304 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
305 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
306 ULONG ref = --This->ref;
307 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
308 if (ref == 0) {
309 IDirect3DDevice8Impl_CleanRender(iface);
310 IDirect3D8_Release((LPDIRECT3D8) This->direct3d8);
311 IWineD3DDevice_Release(This->WineD3DDevice);
312 HeapFree(GetProcessHeap(), 0, This);
314 return ref;
317 /* IDirect3DDevice Interface follow: */
318 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
319 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
320 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
321 return D3D_OK;
324 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
325 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
326 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
328 * pretend we have 32MB of any type of memory queried.
330 return (1024*1024*32);
333 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
334 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
335 FIXME("(%p) : stub\n", This);
336 return D3D_OK;
338 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
339 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
340 TRACE("(%p) : returning %p\n", This, This->direct3d8);
342 /* Inc ref count */
343 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
345 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
346 return D3D_OK;
348 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
349 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
350 FIXME("(%p) : stub, calling idirect3d for now\n", This);
351 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
352 return D3D_OK;
354 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
356 HDC hdc;
357 int bpp = 0;
359 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
360 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
361 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
362 pMode->RefreshRate = 85; /*FIXME: How to identify? */
364 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
365 bpp = GetDeviceCaps(hdc, BITSPIXEL);
366 DeleteDC(hdc);
368 switch (bpp) {
369 case 8: pMode->Format = D3DFMT_R8G8B8; break;
370 case 16: pMode->Format = D3DFMT_R5G6B5; break;
371 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
372 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
373 default:
374 FIXME("Unrecognized display mode format\n");
375 pMode->Format = D3DFMT_UNKNOWN;
378 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
379 pMode->Format, debug_d3dformat(pMode->Format));
380 return D3D_OK;
382 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
383 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
384 TRACE("(%p) copying to %p\n", This, pParameters);
385 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
386 return D3D_OK;
388 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
389 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
390 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
391 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
393 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
394 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
395 return D3DERR_INVALIDCALL;
397 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
398 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
399 return D3DERR_INVALIDCALL;
402 This->xHotSpot = XHotSpot;
403 This->yHotSpot = YHotSpot;
404 return D3D_OK;
406 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
407 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
408 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
409 This->xScreenSpace = XScreenSpace;
410 This->yScreenSpace = YScreenSpace;
411 return;
413 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
414 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
415 TRACE("(%p) : visible(%d)\n", This, bShow);
416 This->bCursorVisible = bShow;
417 return D3D_OK;
419 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
420 IDirect3DSwapChain8Impl* object;
421 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
422 FIXME("(%p) : stub\n", This);
424 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
425 if (NULL == object) {
426 return D3DERR_OUTOFVIDEOMEMORY;
428 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
429 object->ref = 1;
431 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
432 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
433 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
435 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
436 (pPresentationParameters->BackBufferHeight == 0))) {
437 RECT Rect;
439 GetClientRect(This->win_handle, &Rect);
441 if (pPresentationParameters->BackBufferWidth == 0) {
442 pPresentationParameters->BackBufferWidth = Rect.right;
443 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
445 if (pPresentationParameters->BackBufferHeight == 0) {
446 pPresentationParameters->BackBufferHeight = Rect.bottom;
447 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
451 /* Save the presentation parms now filled in correctly */
452 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
454 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
455 pPresentationParameters->BackBufferWidth,
456 pPresentationParameters->BackBufferHeight,
457 pPresentationParameters->BackBufferFormat,
458 pPresentationParameters->MultiSampleType,
459 TRUE,
460 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
462 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
463 pPresentationParameters->BackBufferWidth,
464 pPresentationParameters->BackBufferHeight,
465 pPresentationParameters->BackBufferFormat,
466 pPresentationParameters->MultiSampleType,
467 TRUE,
468 (LPDIRECT3DSURFACE8*) &object->backBuffer);
470 if (pPresentationParameters->EnableAutoDepthStencil) {
471 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
472 pPresentationParameters->BackBufferWidth,
473 pPresentationParameters->BackBufferHeight,
474 pPresentationParameters->AutoDepthStencilFormat,
475 D3DMULTISAMPLE_NONE,
476 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
477 } else {
478 object->depthStencilBuffer = NULL;
481 *pSwapChain = (IDirect3DSwapChain8*) object;
482 return D3D_OK;
484 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
485 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
486 FIXME("(%p) : stub\n", This);
487 return D3D_OK;
489 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
490 CONST RECT* pSourceRect, CONST RECT* pDestRect,
491 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
492 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
493 TRACE("(%p) : complete stub!\n", This);
495 ENTER_GL();
497 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
500 glXSwapBuffers(This->display, This->drawable);
501 /* Don't call checkGLcall, as glGetError is not applicable here */
502 TRACE("glXSwapBuffers called, Starting new frame\n");
504 /* FPS support */
505 if (TRACE_ON(d3d_fps))
507 static long prev_time, frames;
509 DWORD time = GetTickCount();
510 frames++;
511 /* every 1.5 seconds */
512 if (time - prev_time > 1500) {
513 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
514 prev_time = time;
515 frames = 0;
519 #if defined(FRAME_DEBUGGING)
521 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
522 if (!isOn) {
523 isOn = TRUE;
524 FIXME("Enabling D3D Trace\n");
525 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
526 #if defined(SHOW_FRAME_MAKEUP)
527 FIXME("Singe Frame snapshots Starting\n");
528 isDumpingFrames = TRUE;
529 glClear(GL_COLOR_BUFFER_BIT);
530 #endif
532 #if defined(SINGLE_FRAME_DEBUGGING)
533 } else {
534 #if defined(SHOW_FRAME_MAKEUP)
535 FIXME("Singe Frame snapshots Finishing\n");
536 isDumpingFrames = FALSE;
537 #endif
538 FIXME("Singe Frame trace complete\n");
539 DeleteFileA("C:\\D3DTRACE");
540 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
541 #endif
543 } else {
544 if (isOn) {
545 isOn = FALSE;
546 #if defined(SHOW_FRAME_MAKEUP)
547 FIXME("Singe Frame snapshots Finishing\n");
548 isDumpingFrames = FALSE;
549 #endif
550 FIXME("Disabling D3D Trace\n");
551 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
555 #endif
557 LEAVE_GL();
558 /* Although this is not strictly required, a simple demo showed this does occur
559 on (at least non-debug) d3d */
560 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
561 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
564 return D3D_OK;
566 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
567 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
568 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
569 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
571 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
572 FIXME("Only one backBuffer currently supported\n");
573 return D3DERR_INVALIDCALL;
576 /* Note inc ref on returned surface */
577 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
579 return D3D_OK;
581 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
582 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
583 FIXME("(%p) : stub\n", This);
584 return D3D_OK;
586 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
587 HDC hDC;
588 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
590 FIXME("(%p) : pRamp@%p\n", This, pRamp);
591 hDC = GetDC(This->win_handle);
592 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
593 ReleaseDC(This->win_handle, hDC);
594 return;
596 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
597 HDC hDC;
598 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
600 FIXME("(%p) : pRamp@%p\n", This, pRamp);
601 hDC = GetDC(This->win_handle);
602 GetDeviceGammaRamp(hDC, pRamp);
603 ReleaseDC(This->win_handle, hDC);
604 return;
606 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
607 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
608 IDirect3DTexture8Impl *object;
609 unsigned int i;
610 UINT tmpW;
611 UINT tmpH;
613 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
615 /* Allocate the storage for the device */
616 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);
617 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
618 object->lpVtbl = &Direct3DTexture8_Vtbl;
619 object->Device = This;
620 object->ResourceType = D3DRTYPE_TEXTURE;
621 object->ref = 1;
622 object->width = Width;
623 object->height = Height;
624 object->levels = Levels;
625 object->usage = Usage;
626 object->format = Format;
628 /* Calculate levels for mip mapping */
629 if (Levels == 0) {
630 object->levels++;
631 tmpW = Width;
632 tmpH = Height;
633 while (tmpW > 1 && tmpH > 1) {
634 tmpW = max(1, tmpW / 2);
635 tmpH = max(1, tmpH / 2);
636 object->levels++;
638 TRACE("Calculated levels = %d\n", object->levels);
641 /* Generate all the surfaces */
642 tmpW = Width;
643 tmpH = Height;
644 for (i = 0; i < object->levels; i++)
646 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
647 object->surfaces[i]->Container = (IUnknown*) object;
648 object->surfaces[i]->myDesc.Usage = Usage;
649 object->surfaces[i]->myDesc.Pool = Pool;
650 /**
651 * As written in msdn in IDirect3DTexture8::LockRect
652 * Textures created in D3DPOOL_DEFAULT are not lockable.
654 if (D3DPOOL_DEFAULT == Pool) {
655 object->surfaces[i]->lockable = FALSE;
658 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
659 tmpW = max(1, tmpW / 2);
660 tmpH = max(1, tmpH / 2);
663 *ppTexture = (LPDIRECT3DTEXTURE8) object;
664 TRACE("(%p) : Created texture %p\n", This, object);
665 return D3D_OK;
667 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
668 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
669 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
671 IDirect3DVolumeTexture8Impl *object;
672 unsigned int i;
673 UINT tmpW;
674 UINT tmpH;
675 UINT tmpD;
677 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
679 /* Allocate the storage for it */
680 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));
681 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
682 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
683 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
684 object->Device = This;
685 object->ref = 1;
687 object->width = Width;
688 object->height = Height;
689 object->depth = Depth;
690 object->levels = Levels;
691 object->usage = Usage;
692 object->format = Format;
694 /* Calculate levels for mip mapping */
695 if (Levels == 0) {
696 object->levels++;
697 tmpW = Width;
698 tmpH = Height;
699 tmpD = Depth;
700 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
701 tmpW = max(1, tmpW / 2);
702 tmpH = max(1, tmpH / 2);
703 tmpD = max(1, tmpD / 2);
704 object->levels++;
706 TRACE("Calculated levels = %d\n", object->levels);
709 /* Generate all the surfaces */
710 tmpW = Width;
711 tmpH = Height;
712 tmpD = Depth;
714 for (i = 0; i < object->levels; i++)
716 IDirect3DVolume8Impl* volume;
718 /* Create the volume - No entry point for this seperately?? */
719 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
720 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
722 volume->lpVtbl = &Direct3DVolume8_Vtbl;
723 volume->Device = This;
724 volume->ResourceType = D3DRTYPE_VOLUME;
725 volume->Container = (IUnknown*) object;
726 volume->ref = 1;
728 volume->myDesc.Width = Width;
729 volume->myDesc.Height = Height;
730 volume->myDesc.Depth = Depth;
731 volume->myDesc.Format = Format;
732 volume->myDesc.Type = D3DRTYPE_VOLUME;
733 volume->myDesc.Pool = Pool;
734 volume->myDesc.Usage = Usage;
735 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
736 /* Note: Volume textures cannot be dxtn, hence no need to check here */
737 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
738 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
740 volume->lockable = TRUE;
741 volume->locked = FALSE;
742 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
743 volume->Dirty = FALSE;
744 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
746 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
747 This, Width, Height, Depth, Format, debug_d3dformat(Format),
748 volume, volume->allocatedMemory, volume->myDesc.Size);
750 tmpW = max(1, tmpW / 2);
751 tmpH = max(1, tmpH / 2);
752 tmpD = max(1, tmpD / 2);
755 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
756 TRACE("(%p) : Created volume texture %p\n", This, object);
757 return D3D_OK;
759 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
760 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
762 IDirect3DCubeTexture8Impl *object;
763 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
764 unsigned int i,j;
765 UINT tmpW;
767 /* Allocate the storage for it */
768 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));
769 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
770 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
771 object->ref = 1;
772 object->Device = This;
773 object->ResourceType = D3DRTYPE_CUBETEXTURE;
775 object->edgeLength = EdgeLength;
776 object->levels = Levels;
777 object->usage = Usage;
778 object->format = Format;
780 /* Calculate levels for mip mapping */
781 if (Levels == 0) {
782 object->levels++;
783 tmpW = EdgeLength;
784 while (tmpW > 1) {
785 tmpW = max(1, tmpW / 2);
786 object->levels++;
788 TRACE("Calculated levels = %d\n", object->levels);
791 /* Generate all the surfaces */
792 tmpW = EdgeLength;
793 for (i = 0; i < object->levels; i++) {
794 /* Create the 6 faces */
795 for (j = 0; j < 6; j++) {
796 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
797 object->surfaces[j][i]->Container = (IUnknown*) object;
798 object->surfaces[j][i]->myDesc.Usage = Usage;
799 object->surfaces[j][i]->myDesc.Pool = Pool;
800 /**
801 * As written in msdn in IDirect3DCubeTexture8::LockRect
802 * Textures created in D3DPOOL_DEFAULT are not lockable.
804 if (D3DPOOL_DEFAULT == Pool) {
805 object->surfaces[j][i]->lockable = FALSE;
808 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
810 tmpW = max(1, tmpW / 2);
813 TRACE("(%p) : Iface@%p\n", This, object);
814 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
815 return D3D_OK;
817 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
818 IDirect3DVertexBuffer8Impl *object;
820 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
822 /* Allocate the storage for the device */
823 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
824 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
825 object->Device = This;
826 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
827 object->ref = 1;
828 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
829 object->currentDesc.Usage = Usage;
830 object->currentDesc.Pool = Pool;
831 object->currentDesc.FVF = FVF;
832 object->currentDesc.Size = Size;
834 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
836 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
838 return D3D_OK;
840 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
841 IDirect3DIndexBuffer8Impl *object;
843 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
844 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
846 /* Allocate the storage for the device */
847 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
848 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
849 object->Device = This;
850 object->ref = 1;
851 object->ResourceType = D3DRTYPE_INDEXBUFFER;
853 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
854 object->currentDesc.Usage = Usage;
855 object->currentDesc.Pool = Pool;
856 object->currentDesc.Format = Format;
857 object->currentDesc.Size = Length;
859 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
861 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
863 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
865 return D3D_OK;
867 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
868 IDirect3DSurface8Impl *object;
869 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
871 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
872 if (NULL == object) {
873 *ppSurface = NULL;
874 return D3DERR_OUTOFVIDEOMEMORY;
876 *ppSurface = (LPDIRECT3DSURFACE8) object;
877 object->lpVtbl = &Direct3DSurface8_Vtbl;
878 object->Device = This;
879 object->ResourceType = D3DRTYPE_SURFACE;
880 object->Container = (IUnknown*) This;
882 object->ref = 1;
883 object->myDesc.Width = Width;
884 object->myDesc.Height = Height;
885 object->myDesc.Format = Format;
886 object->myDesc.Type = D3DRTYPE_SURFACE;
887 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
888 object->myDesc.Pool = D3DPOOL_DEFAULT;
889 object->myDesc.MultiSampleType = MultiSample;
890 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
891 if (Format == D3DFMT_DXT1) {
892 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
893 } else {
894 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
896 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
897 object->lockable = Lockable;
898 object->locked = FALSE;
899 memset(&object->lockedRect, 0, sizeof(RECT));
900 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
902 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);
903 return D3D_OK;
905 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
906 IDirect3DSurface8Impl *object;
908 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
910 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
911 if (NULL == object) {
912 *ppSurface = NULL;
913 return D3DERR_OUTOFVIDEOMEMORY;
915 *ppSurface = (LPDIRECT3DSURFACE8) object;
916 object->lpVtbl = &Direct3DSurface8_Vtbl;
917 object->Device = This;
918 object->ResourceType = D3DRTYPE_SURFACE;
919 object->Container = (IUnknown*) This;
921 object->ref = 1;
922 object->myDesc.Width = Width;
923 object->myDesc.Height = Height;
924 object->myDesc.Format = Format;
925 object->myDesc.Type = D3DRTYPE_SURFACE;
926 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
927 object->myDesc.Pool = D3DPOOL_DEFAULT;
928 object->myDesc.MultiSampleType = MultiSample;
929 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
930 if (Format == D3DFMT_DXT1) {
931 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
932 } else {
933 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
935 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
936 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
937 object->locked = FALSE;
938 memset(&object->lockedRect, 0, sizeof(RECT));
939 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
941 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);
942 return D3D_OK;
944 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
945 IDirect3DSurface8Impl *object;
947 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
949 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
950 *ppSurface = (LPDIRECT3DSURFACE8) object;
951 object->lpVtbl = &Direct3DSurface8_Vtbl;
952 object->Device = This;
953 object->ResourceType = D3DRTYPE_SURFACE;
954 object->Container = (IUnknown*) This;
956 object->ref = 1;
957 object->myDesc.Width = Width;
958 object->myDesc.Height = Height;
959 object->myDesc.Format = Format;
960 object->myDesc.Type = D3DRTYPE_SURFACE;
961 object->myDesc.Usage = 0;
962 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
963 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
964 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
965 it is based around 4x4 pixel blocks it requires padding, so allocate enough
966 space! */
967 if (Format == D3DFMT_DXT1) {
968 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
969 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
970 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
971 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
972 } else {
973 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
975 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
976 object->lockable = TRUE;
977 object->locked = FALSE;
978 memset(&object->lockedRect, 0, sizeof(RECT));
979 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
981 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);
982 return D3D_OK;
984 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
985 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
986 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
988 HRESULT rc = D3D_OK;
989 IDirect3DBaseTexture8* texture = NULL;
992 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
993 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
995 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
996 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
997 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
999 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1000 a sample and doesn't seem to break anything as far as I can tell */
1001 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1002 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1003 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1004 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1005 rc = D3DERR_INVALIDCALL;
1007 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1008 TRACE("Converting dest to same format as source, since dest was unknown\n");
1009 dst->myDesc.Format = src->myDesc.Format;
1011 /* Convert container as well */
1012 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1013 if (SUCCEEDED(rc) && NULL != texture) {
1014 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1015 /** Releasing texture after GetContainer */
1016 IDirect3DBaseTexture8_Release(texture);
1017 texture = NULL;
1021 /* Quick if complete copy ... */
1022 if (SUCCEEDED(rc)) {
1023 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1025 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1027 D3DLOCKED_RECT lrSrc;
1028 D3DLOCKED_RECT lrDst;
1029 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1030 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1031 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1033 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1035 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1036 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1037 TRACE("Unlocked src and dst\n");
1039 } else {
1041 FIXME("Wanted to copy all surfaces but size not compatible\n");
1042 rc = D3DERR_INVALIDCALL;
1046 } else {
1048 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1050 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1051 unsigned int i;
1053 /* Copy rect by rect */
1054 for (i = 0; i < cRects; i++) {
1055 CONST RECT* r = &pSourceRectsArray[i];
1056 CONST POINT* p = &pDestPointsArray[i];
1057 int copyperline;
1058 int j;
1059 D3DLOCKED_RECT lrSrc;
1060 D3DLOCKED_RECT lrDst;
1061 RECT dest_rect;
1063 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1064 if (src->myDesc.Format == D3DFMT_DXT1) {
1065 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1066 } else {
1067 copyperline = ((r->right - r->left) * bytesPerPixel);
1069 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1070 dest_rect.left = p->x;
1071 dest_rect.top = p->y;
1072 dest_rect.right = p->x + (r->right - r->left);
1073 dest_rect.bottom= p->y + (r->bottom - r->top);
1074 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1075 TRACE("Locked src and dst\n");
1077 /* Find where to start */
1078 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1079 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1081 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1082 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1083 TRACE("Unlocked src and dst\n");
1085 } else {
1086 FIXME("Wanted to copy partial surfaces not implemented\n");
1087 rc = D3DERR_INVALIDCALL;
1092 return rc;
1094 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1095 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1096 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1097 D3DRESOURCETYPE srcType;
1098 D3DRESOURCETYPE dstType;
1100 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1101 TRACE("(%p) : first try\n", This);
1103 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1104 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1106 if (srcType != dstType) {
1107 return D3DERR_INVALIDCALL;
1109 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1110 return D3DERR_INVALIDCALL;
1112 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1113 return D3DERR_INVALIDCALL;
1115 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1116 /** Only copy Dirty textures */
1117 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1118 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1119 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1120 UINT i, j;
1122 for (i = skipLevels; i < srcLevelCnt; ++i) {
1123 HRESULT hr;
1125 switch (srcType) {
1126 case D3DRTYPE_TEXTURE:
1128 IDirect3DSurface8* srcSur = NULL;
1129 IDirect3DSurface8* dstSur = NULL;
1130 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1131 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1133 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1134 about dst with less levels than the source?) */
1135 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1137 IDirect3DSurface8Impl_Release(srcSur);
1138 IDirect3DSurface8Impl_Release(dstSur);
1140 break;
1141 case D3DRTYPE_VOLUMETEXTURE:
1143 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1145 break;
1146 case D3DRTYPE_CUBETEXTURE:
1148 IDirect3DSurface8* srcSur = NULL;
1149 IDirect3DSurface8* dstSur = NULL;
1150 for (j = 0; j < 5; ++j) {
1151 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1152 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1153 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1154 IDirect3DSurface8Impl_Release(srcSur);
1155 IDirect3DSurface8Impl_Release(dstSur);
1158 break;
1159 default:
1160 break;
1163 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1166 return D3D_OK;
1168 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1169 HRESULT hr;
1170 D3DLOCKED_RECT lockedRect;
1171 RECT wantedRect;
1172 GLint prev_store;
1173 GLenum prev_read;
1175 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1177 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1179 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1180 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1181 return D3DERR_INVALIDCALL;
1184 wantedRect.left = 0;
1185 wantedRect.top = 0;
1186 wantedRect.right = This->PresentParms.BackBufferWidth;
1187 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1189 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1190 if (FAILED(hr)) {
1191 ERR("(%p) : cannot lock surface\n", This);
1192 return D3DERR_INVALIDCALL;
1195 ENTER_GL();
1197 glFlush();
1198 vcheckGLcall("glFlush");
1199 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1200 vcheckGLcall("glIntegerv");
1201 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1202 vcheckGLcall("glIntegerv");
1204 glReadBuffer(GL_FRONT);
1205 vcheckGLcall("glReadBuffer");
1206 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1207 vcheckGLcall("glPixelStorei");
1208 /* stupid copy */
1210 unsigned long j;
1211 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1212 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1213 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1214 vcheckGLcall("glReadPixels");
1217 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1218 vcheckGLcall("glPixelStorei");
1219 glReadBuffer(prev_read);
1220 vcheckGLcall("glReadBuffer");
1222 LEAVE_GL();
1224 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1225 return hr;
1227 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1228 HRESULT hr = D3D_OK;
1229 D3DVIEWPORT8 viewport;
1231 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1233 /* If pRenderTarget == NULL, it seems to default to back buffer */
1234 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1236 /* For ease of code later on, handle a null depth as leave alone
1237 - Have not tested real d3d for this case but doing this avoids
1238 numerous null pointer checks */
1239 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1241 /* If we are trying to set what we already have, don't bother */
1242 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1243 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1244 } else {
1245 /* Otherwise, set the render target up */
1246 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1247 IDirect3DDevice8Impl_CleanRender(iface);
1248 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1251 if (SUCCEEDED(hr)) {
1252 /* Finally, reset the viewport as the MSDN states. */
1253 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1254 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1255 viewport.X = 0;
1256 viewport.Y = 0;
1257 viewport.MaxZ = 1.0f;
1258 viewport.MinZ = 0.0f;
1259 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1262 return hr;
1265 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1266 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1268 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1270 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1271 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1273 return D3D_OK;
1276 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1277 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1279 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1281 /* Note inc ref on returned surface */
1282 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1283 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1285 return D3D_OK;
1288 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1289 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1290 return IWineD3DDevice_BeginScene(This->WineD3DDevice);
1293 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1294 IDirect3DBaseTexture8* cont = NULL;
1295 HRESULT hr;
1296 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1297 TRACE("(%p)\n", This);
1299 ENTER_GL();
1301 glFlush();
1302 checkGLcall("glFlush");
1304 #if 0 /* Useful for debugging sometimes! */
1305 printf("Hit Enter ...\n");
1306 getchar();
1307 #endif
1309 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1310 #if 0
1311 GLenum prev_read;
1312 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1313 vcheckGLcall("glIntegerv");
1314 glReadBuffer(GL_FRONT);
1315 vcheckGLcall("glReadBuffer");
1317 long j;
1318 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1320 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1321 pitch = pitch / 2;
1323 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1324 glReadPixels(0,
1325 This->renderTarget->myDesc.Height - j - 1,
1326 This->renderTarget->myDesc.Width,
1328 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1329 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1330 This->renderTarget->allocatedMemory + j * pitch);
1331 vcheckGLcall("glReadPixels");
1334 glReadBuffer(prev_read);
1335 vcheckGLcall("glReadBuffer");
1336 #endif
1338 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1339 if (SUCCEEDED(hr) && NULL != cont) {
1340 /** always dirtify for now. we must find a better way to see that surface have been modified */
1341 This->renderTarget->inPBuffer = TRUE;
1342 This->renderTarget->inTexture = FALSE;
1343 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1344 IDirect3DBaseTexture8_PreLoad(cont);
1345 This->renderTarget->inPBuffer = FALSE;
1346 IDirect3DBaseTexture8Impl_Release(cont);
1347 cont = NULL;
1351 LEAVE_GL();
1352 return D3D_OK;
1354 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1355 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1357 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1358 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1359 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1360 GLbitfield glMask = 0;
1361 GLboolean old_ztest;
1362 GLfloat old_z_clear_value;
1363 GLint old_stencil_clear_value;
1364 GLfloat old_color_clear_value[4];
1365 unsigned int i;
1366 CONST D3DRECT* curRect;
1368 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1369 Count, pRects, Flags, Z, Stencil);
1371 ENTER_GL();
1372 glEnable(GL_SCISSOR_TEST);
1373 checkGLcall("glEnable GL_SCISSOR_TEST");
1374 if (Count > 0 && pRects) {
1375 curRect = pRects;
1376 } else {
1377 curRect = NULL;
1380 /* Only set the values up once, as they are not changing */
1381 if (Flags & D3DCLEAR_STENCIL) {
1382 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1383 glClearStencil(Stencil);
1384 checkGLcall("glClearStencil");
1385 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1386 glStencilMask(0xFFFFFFFF);
1389 if (Flags & D3DCLEAR_ZBUFFER) {
1390 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1391 glDepthMask(GL_TRUE);
1392 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1393 glClearDepth(Z);
1394 checkGLcall("glClearDepth");
1395 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1398 if (Flags & D3DCLEAR_TARGET) {
1399 TRACE("Clearing screen with glClear to color %lx\n", Color);
1400 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1401 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1402 ((Color >> 8) & 0xFF) / 255.0f,
1403 ((Color >> 0) & 0xFF) / 255.0f,
1404 ((Color >> 24) & 0xFF) / 255.0f);
1405 checkGLcall("glClearColor");
1407 /* Clear ALL colors! */
1408 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1409 glMask = glMask | GL_COLOR_BUFFER_BIT;
1412 /* Now process each rect in turn */
1413 for (i = 0; i < Count || i == 0; i++) {
1415 if (curRect) {
1416 /* Note gl uses lower left, width/height */
1417 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1418 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1419 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1420 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1421 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1422 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1423 checkGLcall("glScissor");
1424 } else {
1425 glScissor(This->StateBlock->viewport.X,
1426 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1427 This->StateBlock->viewport.Width,
1428 This->StateBlock->viewport.Height);
1429 checkGLcall("glScissor");
1432 /* Clear the selected rectangle (or full screen) */
1433 glClear(glMask);
1434 checkGLcall("glClear");
1436 /* Step to the next rectangle */
1437 if (curRect) curRect = curRect + sizeof(D3DRECT);
1440 /* Restore the old values (why..?) */
1441 if (Flags & D3DCLEAR_STENCIL) {
1442 glClearStencil(old_stencil_clear_value);
1443 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1445 if (Flags & D3DCLEAR_ZBUFFER) {
1446 glDepthMask(old_ztest);
1447 glClearDepth(old_z_clear_value);
1449 if (Flags & D3DCLEAR_TARGET) {
1450 glClearColor(old_color_clear_value[0],
1451 old_color_clear_value[1],
1452 old_color_clear_value[2],
1453 old_color_clear_value[3]);
1454 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1455 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1456 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1457 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1460 glDisable(GL_SCISSOR_TEST);
1461 checkGLcall("glDisable");
1462 LEAVE_GL();
1464 return D3D_OK;
1466 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1467 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1468 unsigned int k;
1470 /* Most of this routine, comments included copied from ddraw tree initially: */
1471 TRACE("(%p) : State=%d\n", This, d3dts);
1473 /* Handle recording of state blocks */
1474 if (This->isRecordingState) {
1475 TRACE("Recording... not performing anything\n");
1476 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1477 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1478 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1479 return D3D_OK;
1483 * if the new matrix is the same as the current one,
1484 * we cut off any further processing. this seems to be a reasonable
1485 * optimization because as was noticed, some apps (warcraft3 for example)
1486 * tend towards setting the same matrix repeatedly for some dumb reason.
1488 * From here on we assume that the new matrix is different, wherever it matters
1489 * but note
1491 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1492 TRACE("The app is setting the same matrix over again\n");
1493 return D3D_OK;
1494 } else {
1495 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1499 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1500 where ViewMat = Camera space, WorldMat = world space.
1502 In OpenGL, camera and world space is combined into GL_MODELVIEW
1503 matrix. The Projection matrix stay projection matrix.
1506 /* Capture the times we can just ignore the change */
1507 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1508 This->modelview_valid = FALSE;
1509 return D3D_OK;
1511 } else if (d3dts == D3DTS_PROJECTION) {
1512 This->proj_valid = FALSE;
1513 return D3D_OK;
1515 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1516 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1517 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1518 return D3D_OK;
1521 /* Chances are we really are going to have to change a matrix */
1522 ENTER_GL();
1524 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1525 if (d3dts < GL_LIMITS(textures)) {
1526 int tex = d3dts - D3DTS_TEXTURE0;
1527 #if defined(GL_VERSION_1_3)
1528 glActiveTexture(GL_TEXTURE0 + tex);
1529 checkGLcall("glActiveTexture");
1530 #else
1531 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1532 checkGLcall("glActiveTextureARB");
1533 #endif
1534 set_texture_matrix((const float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1537 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1539 PLIGHTINFOEL *lightChain = NULL;
1540 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1541 This->modelview_valid = FALSE;
1542 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1543 glMatrixMode(GL_MODELVIEW);
1544 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1545 glPushMatrix();
1546 glLoadMatrixf((const float *)lpmatrix);
1547 checkGLcall("glLoadMatrixf(...)");
1549 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1550 * NOTE: We have to reset the positions even if the light/plane is not currently
1551 * enabled, since the call to enable it will not reset the position.
1552 * NOTE2: Apparently texture transforms do NOT need reapplying
1555 /* Reset lights */
1556 lightChain = This->StateBlock->lights;
1557 while (lightChain && lightChain->glIndex != -1) {
1558 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1559 checkGLcall("glLightfv posn");
1560 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1561 checkGLcall("glLightfv dirn");
1562 lightChain = lightChain->next;
1564 /* Reset Clipping Planes if clipping is enabled */
1565 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1566 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1567 checkGLcall("glClipPlane");
1569 glPopMatrix();
1571 } else { /* What was requested!?? */
1572 WARN("invalid matrix specified: %i\n", d3dts);
1576 /* Release lock, all done */
1577 LEAVE_GL();
1578 return D3D_OK;
1581 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1582 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1583 TRACE("(%p) : for State %d\n", This, State);
1584 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1585 return D3D_OK;
1588 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1589 D3DMATRIX *mat = NULL;
1590 D3DMATRIX temp;
1592 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1593 but works regardless of recording being on.
1594 If this is found to be wrong, change to StateBlock. */
1595 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1596 TRACE("(%p) : For state %u\n", This, State);
1598 if (State < HIGHEST_TRANSFORMSTATE)
1600 mat = &This->UpdateStateBlock->transforms[State];
1601 } else {
1602 FIXME("Unhandled transform state!!\n");
1605 /* Copied from ddraw code: */
1606 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);
1607 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);
1608 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);
1609 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);
1611 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);
1612 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);
1613 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);
1614 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);
1616 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);
1617 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);
1618 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);
1619 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);
1621 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);
1622 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);
1623 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);
1624 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);
1626 /* Apply change via set transform - will reapply to eg. lights this way */
1627 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1628 return D3D_OK;
1630 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1631 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1633 TRACE("(%p)\n", This);
1634 This->UpdateStateBlock->Changed.viewport = TRUE;
1635 This->UpdateStateBlock->Set.viewport = TRUE;
1636 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1638 /* Handle recording of state blocks */
1639 if (This->isRecordingState) {
1640 TRACE("Recording... not performing anything\n");
1641 return D3D_OK;
1644 ENTER_GL();
1646 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1647 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1649 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1650 checkGLcall("glDepthRange");
1651 /* Note: GL requires lower left, DirectX supplies upper left */
1652 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1653 pViewport->Width, pViewport->Height);
1654 checkGLcall("glViewport");
1656 LEAVE_GL();
1658 return D3D_OK;
1661 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1662 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1663 TRACE("(%p)\n", This);
1664 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1665 return D3D_OK;
1668 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1669 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1671 This->UpdateStateBlock->Changed.material = TRUE;
1672 This->UpdateStateBlock->Set.material = TRUE;
1673 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1675 /* Handle recording of state blocks */
1676 if (This->isRecordingState) {
1677 TRACE("Recording... not performing anything\n");
1678 return D3D_OK;
1681 ENTER_GL();
1682 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1683 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1684 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1685 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1686 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1688 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1689 checkGLcall("glMaterialfv");
1690 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1691 checkGLcall("glMaterialfv");
1693 /* Only change material color if specular is enabled, otherwise it is set to black */
1694 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1695 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1696 checkGLcall("glMaterialfv");
1697 } else {
1698 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1699 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1700 checkGLcall("glMaterialfv");
1702 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1703 checkGLcall("glMaterialfv");
1704 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1705 checkGLcall("glMaterialf");
1707 LEAVE_GL();
1708 return D3D_OK;
1710 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1711 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1712 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1713 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1714 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1715 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1716 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1717 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1718 return D3D_OK;
1721 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1722 you can reference any indexes you want as long as that number max are enabled are any
1723 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1724 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1725 but when recording, just build a chain pretty much of commands to be replayed. */
1727 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1728 float rho;
1729 PLIGHTINFOEL *object, *temp;
1731 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1732 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1734 /* If recording state block, just add to end of lights chain */
1735 if (This->isRecordingState) {
1736 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1737 if (NULL == object) {
1738 return D3DERR_OUTOFVIDEOMEMORY;
1740 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1741 object->OriginalIndex = Index;
1742 object->glIndex = -1;
1743 object->changed = TRUE;
1745 /* Add to the END of the chain of lights changes to be replayed */
1746 if (This->UpdateStateBlock->lights == NULL) {
1747 This->UpdateStateBlock->lights = object;
1748 } else {
1749 temp = This->UpdateStateBlock->lights;
1750 while (temp->next != NULL) temp=temp->next;
1751 temp->next = object;
1753 TRACE("Recording... not performing anything more\n");
1754 return D3D_OK;
1757 /* Ok, not recording any longer so do real work */
1758 object = This->StateBlock->lights;
1759 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1761 /* If we didn't find it in the list of lights, time to add it */
1762 if (object == NULL) {
1763 PLIGHTINFOEL *insertAt,*prevPos;
1765 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1766 if (NULL == object) {
1767 return D3DERR_OUTOFVIDEOMEMORY;
1769 object->OriginalIndex = Index;
1770 object->glIndex = -1;
1772 /* Add it to the front of list with the idea that lights will be changed as needed
1773 BUT after any lights currently assigned GL indexes */
1774 insertAt = This->StateBlock->lights;
1775 prevPos = NULL;
1776 while (insertAt != NULL && insertAt->glIndex != -1) {
1777 prevPos = insertAt;
1778 insertAt = insertAt->next;
1781 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1782 This->StateBlock->lights = object;
1783 } else if (insertAt == NULL) { /* End of list */
1784 prevPos->next = object;
1785 object->prev = prevPos;
1786 } else { /* Middle of chain */
1787 if (prevPos == NULL) {
1788 This->StateBlock->lights = object;
1789 } else {
1790 prevPos->next = object;
1792 object->prev = prevPos;
1793 object->next = insertAt;
1794 insertAt->prev = object;
1798 /* Initialze the object */
1799 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,
1800 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1801 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1802 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1803 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1804 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1805 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1807 /* Save away the information */
1808 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1810 switch (pLight->Type) {
1811 case D3DLIGHT_POINT:
1812 /* Position */
1813 object->lightPosn[0] = pLight->Position.x;
1814 object->lightPosn[1] = pLight->Position.y;
1815 object->lightPosn[2] = pLight->Position.z;
1816 object->lightPosn[3] = 1.0f;
1817 object->cutoff = 180.0f;
1818 /* FIXME: Range */
1819 break;
1821 case D3DLIGHT_DIRECTIONAL:
1822 /* Direction */
1823 object->lightPosn[0] = -pLight->Direction.x;
1824 object->lightPosn[1] = -pLight->Direction.y;
1825 object->lightPosn[2] = -pLight->Direction.z;
1826 object->lightPosn[3] = 0.0;
1827 object->exponent = 0.0f;
1828 object->cutoff = 180.0f;
1829 break;
1831 case D3DLIGHT_SPOT:
1832 /* Position */
1833 object->lightPosn[0] = pLight->Position.x;
1834 object->lightPosn[1] = pLight->Position.y;
1835 object->lightPosn[2] = pLight->Position.z;
1836 object->lightPosn[3] = 1.0;
1838 /* Direction */
1839 object->lightDirn[0] = pLight->Direction.x;
1840 object->lightDirn[1] = pLight->Direction.y;
1841 object->lightDirn[2] = pLight->Direction.z;
1842 object->lightDirn[3] = 1.0;
1845 * opengl-ish and d3d-ish spot lights use too different models for the
1846 * light "intensity" as a function of the angle towards the main light direction,
1847 * so we only can approximate very roughly.
1848 * however spot lights are rather rarely used in games (if ever used at all).
1849 * furthermore if still used, probably nobody pays attention to such details.
1851 if (pLight->Falloff == 0) {
1852 rho = 6.28f;
1853 } else {
1854 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1856 if (rho < 0.0001) rho = 0.0001f;
1857 object->exponent = -0.3/log(cos(rho/2));
1858 object->cutoff = pLight->Phi*90/M_PI;
1860 /* FIXME: Range */
1861 break;
1863 default:
1864 FIXME("Unrecognized light type %d\n", pLight->Type);
1867 /* Update the live definitions if the light is currently assigned a glIndex */
1868 if (object->glIndex != -1) {
1869 setup_light(iface, object->glIndex, object);
1871 return D3D_OK;
1873 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1874 PLIGHTINFOEL *lightInfo = NULL;
1875 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1876 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1878 /* Locate the light in the live lights */
1879 lightInfo = This->StateBlock->lights;
1880 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1882 if (lightInfo == NULL) {
1883 TRACE("Light information requested but light not defined\n");
1884 return D3DERR_INVALIDCALL;
1887 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1888 return D3D_OK;
1890 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1891 PLIGHTINFOEL *lightInfo = NULL;
1892 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1893 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1895 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1896 if (This->isRecordingState) {
1897 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1898 if (NULL == lightInfo) {
1899 return D3DERR_OUTOFVIDEOMEMORY;
1901 lightInfo->OriginalIndex = Index;
1902 lightInfo->glIndex = -1;
1903 lightInfo->enabledChanged = TRUE;
1905 /* Add to the END of the chain of lights changes to be replayed */
1906 if (This->UpdateStateBlock->lights == NULL) {
1907 This->UpdateStateBlock->lights = lightInfo;
1908 } else {
1909 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1910 while (temp->next != NULL) temp=temp->next;
1911 temp->next = lightInfo;
1913 TRACE("Recording... not performing anything more\n");
1914 return D3D_OK;
1917 /* Not recording... So, locate the light in the live lights */
1918 lightInfo = This->StateBlock->lights;
1919 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1921 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1922 if (lightInfo == NULL) {
1923 D3DLIGHT8 lightParms;
1924 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1925 wait until someone confirms it seems to work! */
1926 TRACE("Light enabled requested but light not defined, so defining one!\n");
1927 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1928 lightParms.Diffuse.r = 1.0;
1929 lightParms.Diffuse.g = 1.0;
1930 lightParms.Diffuse.b = 1.0;
1931 lightParms.Diffuse.a = 0.0;
1932 lightParms.Specular.r = 0.0;
1933 lightParms.Specular.g = 0.0;
1934 lightParms.Specular.b = 0.0;
1935 lightParms.Specular.a = 0.0;
1936 lightParms.Ambient.r = 0.0;
1937 lightParms.Ambient.g = 0.0;
1938 lightParms.Ambient.b = 0.0;
1939 lightParms.Ambient.a = 0.0;
1940 lightParms.Position.x = 0.0;
1941 lightParms.Position.y = 0.0;
1942 lightParms.Position.z = 0.0;
1943 lightParms.Direction.x = 0.0;
1944 lightParms.Direction.y = 0.0;
1945 lightParms.Direction.z = 1.0;
1946 lightParms.Range = 0.0;
1947 lightParms.Falloff = 0.0;
1948 lightParms.Attenuation0 = 0.0;
1949 lightParms.Attenuation1 = 0.0;
1950 lightParms.Attenuation2 = 0.0;
1951 lightParms.Theta = 0.0;
1952 lightParms.Phi = 0.0;
1953 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1955 /* Search for it again! Should be fairly quick as near head of list */
1956 lightInfo = This->StateBlock->lights;
1957 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1958 if (lightInfo == NULL) {
1959 FIXME("Adding default lights has failed dismally\n");
1960 return D3DERR_INVALIDCALL;
1964 /* OK, we now have a light... */
1965 if (Enable == FALSE) {
1967 /* If we are disabling it, check it was enabled, and
1968 still only do something if it has assigned a glIndex (which it should have!) */
1969 if (lightInfo->lightEnabled && (lightInfo->glIndex != -1)) {
1970 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1971 ENTER_GL();
1972 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1973 checkGLcall("glDisable GL_LIGHT0+Index");
1974 LEAVE_GL();
1975 } else {
1976 TRACE("Nothing to do as light was not enabled\n");
1978 lightInfo->lightEnabled = FALSE;
1979 } else {
1981 /* We are enabling it. If it is enabled, its really simple */
1982 if (lightInfo->lightEnabled) {
1983 /* nop */
1984 TRACE("Nothing to do as light was enabled\n");
1986 /* If it already has a glIndex, its still simple */
1987 } else if (lightInfo->glIndex != -1) {
1988 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1989 lightInfo->lightEnabled = TRUE;
1990 ENTER_GL();
1991 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1992 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1993 LEAVE_GL();
1995 /* Otherwise got to find space - lights are ordered gl indexes first */
1996 } else {
1997 PLIGHTINFOEL *bsf = NULL;
1998 PLIGHTINFOEL *pos = This->StateBlock->lights;
1999 PLIGHTINFOEL *prev = NULL;
2000 int Index= 0;
2001 int glIndex = -1;
2003 /* Try to minimize changes as much as possible */
2004 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2006 /* Try to remember which index can be replaced if necessary */
2007 if (bsf==NULL && pos->lightEnabled == FALSE) {
2008 /* Found a light we can replace, save as best replacement */
2009 bsf = pos;
2012 /* Step to next space */
2013 prev = pos;
2014 pos = pos->next;
2015 Index ++;
2018 /* If we have too many active lights, fail the call */
2019 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2020 FIXME("Program requests too many concurrent lights\n");
2021 return D3DERR_INVALIDCALL;
2023 /* If we have allocated all lights, but not all are enabled,
2024 reuse one which is not enabled */
2025 } else if (Index == This->maxConcurrentLights) {
2026 /* use bsf - Simply swap the new light and the BSF one */
2027 PLIGHTINFOEL *bsfNext = bsf->next;
2028 PLIGHTINFOEL *bsfPrev = bsf->prev;
2030 /* Sort out ends */
2031 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2032 if (bsf->prev != NULL) {
2033 bsf->prev->next = lightInfo;
2034 } else {
2035 This->StateBlock->lights = lightInfo;
2038 /* If not side by side, lots of chains to update */
2039 if (bsf->next != lightInfo) {
2040 lightInfo->prev->next = bsf;
2041 bsf->next->prev = lightInfo;
2042 bsf->next = lightInfo->next;
2043 bsf->prev = lightInfo->prev;
2044 lightInfo->next = bsfNext;
2045 lightInfo->prev = bsfPrev;
2047 } else {
2048 /* Simple swaps */
2049 bsf->prev = lightInfo;
2050 bsf->next = lightInfo->next;
2051 lightInfo->next = bsf;
2052 lightInfo->prev = bsfPrev;
2056 /* Update states */
2057 glIndex = bsf->glIndex;
2058 bsf->glIndex = -1;
2059 lightInfo->glIndex = glIndex;
2060 lightInfo->lightEnabled = TRUE;
2062 /* Finally set up the light in gl itself */
2063 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2064 ENTER_GL();
2065 setup_light(iface, glIndex, lightInfo);
2066 glEnable(GL_LIGHT0 + glIndex);
2067 checkGLcall("glEnable GL_LIGHT0 new setup");
2068 LEAVE_GL();
2070 /* If we reached the end of the allocated lights, with space in the
2071 gl lights, setup a new light */
2072 } else if (pos->glIndex == -1) {
2074 /* We reached the end of the allocated gl lights, so already
2075 know the index of the next one! */
2076 glIndex = Index;
2077 lightInfo->glIndex = glIndex;
2078 lightInfo->lightEnabled = TRUE;
2080 /* In an ideal world, its already in the right place */
2081 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2082 /* No need to move it */
2083 } else {
2084 /* Remove this light from the list */
2085 lightInfo->prev->next = lightInfo->next;
2086 if (lightInfo->next != NULL) {
2087 lightInfo->next->prev = lightInfo->prev;
2090 /* Add in at appropriate place (inbetween prev and pos) */
2091 lightInfo->prev = prev;
2092 lightInfo->next = pos;
2093 if (prev == NULL) {
2094 This->StateBlock->lights = lightInfo;
2095 } else {
2096 prev->next = lightInfo;
2098 if (pos != NULL) {
2099 pos->prev = lightInfo;
2103 /* Finally set up the light in gl itself */
2104 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2105 ENTER_GL();
2106 setup_light(iface, glIndex, lightInfo);
2107 glEnable(GL_LIGHT0 + glIndex);
2108 checkGLcall("glEnable GL_LIGHT0 new setup");
2109 LEAVE_GL();
2114 return D3D_OK;
2116 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2118 PLIGHTINFOEL *lightInfo = NULL;
2119 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2120 TRACE("(%p) : for idx(%ld)\n", This, Index);
2122 /* Locate the light in the live lights */
2123 lightInfo = This->StateBlock->lights;
2124 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2126 if (lightInfo == NULL) {
2127 TRACE("Light enabled state requested but light not defined\n");
2128 return D3DERR_INVALIDCALL;
2130 *pEnable = lightInfo->lightEnabled;
2131 return D3D_OK;
2133 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2134 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2135 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2137 /* Validate Index */
2138 if (Index >= GL_LIMITS(clipplanes)) {
2139 TRACE("Application has requested clipplane this device doesn't support\n");
2140 return D3DERR_INVALIDCALL;
2143 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2144 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2145 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2146 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2147 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2148 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2150 /* Handle recording of state blocks */
2151 if (This->isRecordingState) {
2152 TRACE("Recording... not performing anything\n");
2153 return D3D_OK;
2156 /* Apply it */
2158 ENTER_GL();
2160 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2161 glMatrixMode(GL_MODELVIEW);
2162 glPushMatrix();
2163 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2165 TRACE("Clipplane [%f,%f,%f,%f]\n",
2166 This->UpdateStateBlock->clipplane[Index][0],
2167 This->UpdateStateBlock->clipplane[Index][1],
2168 This->UpdateStateBlock->clipplane[Index][2],
2169 This->UpdateStateBlock->clipplane[Index][3]);
2170 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2171 checkGLcall("glClipPlane");
2173 glPopMatrix();
2175 LEAVE_GL();
2177 return D3D_OK;
2179 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2180 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2181 TRACE("(%p) : for idx %ld\n", This, Index);
2183 /* Validate Index */
2184 if (Index >= GL_LIMITS(clipplanes)) {
2185 TRACE("Application has requested clipplane this device doesn't support\n");
2186 return D3DERR_INVALIDCALL;
2189 pPlane[0] = This->StateBlock->clipplane[Index][0];
2190 pPlane[1] = This->StateBlock->clipplane[Index][1];
2191 pPlane[2] = This->StateBlock->clipplane[Index][2];
2192 pPlane[3] = This->StateBlock->clipplane[Index][3];
2193 return D3D_OK;
2195 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2196 union {
2197 DWORD d;
2198 float f;
2199 } tmpvalue;
2200 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2201 DWORD OldValue = This->StateBlock->renderstate[State];
2203 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2204 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2205 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2206 This->UpdateStateBlock->renderstate[State] = Value;
2208 /* Handle recording of state blocks */
2209 if (This->isRecordingState) {
2210 TRACE("Recording... not performing anything\n");
2211 return D3D_OK;
2214 ENTER_GL();
2216 switch (State) {
2217 case D3DRS_FILLMODE :
2218 switch ((D3DFILLMODE) Value) {
2219 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2220 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2221 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2222 default:
2223 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2225 checkGLcall("glPolygonMode (fillmode)");
2226 break;
2228 case D3DRS_LIGHTING :
2229 if (Value) {
2230 glEnable(GL_LIGHTING);
2231 checkGLcall("glEnable GL_LIGHTING");
2232 } else {
2233 glDisable(GL_LIGHTING);
2234 checkGLcall("glDisable GL_LIGHTING");
2236 break;
2238 case D3DRS_ZENABLE :
2239 switch ((D3DZBUFFERTYPE) Value) {
2240 case D3DZB_FALSE:
2241 glDisable(GL_DEPTH_TEST);
2242 checkGLcall("glDisable GL_DEPTH_TEST");
2243 break;
2244 case D3DZB_TRUE:
2245 glEnable(GL_DEPTH_TEST);
2246 checkGLcall("glEnable GL_DEPTH_TEST");
2247 break;
2248 case D3DZB_USEW:
2249 glEnable(GL_DEPTH_TEST);
2250 checkGLcall("glEnable GL_DEPTH_TEST");
2251 FIXME("W buffer is not well handled\n");
2252 break;
2253 default:
2254 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2256 break;
2258 case D3DRS_CULLMODE :
2260 /* If we are culling "back faces with clockwise vertices" then
2261 set front faces to be counter clockwise and enable culling
2262 of back faces */
2263 switch ((D3DCULL) Value) {
2264 case D3DCULL_NONE:
2265 glDisable(GL_CULL_FACE);
2266 checkGLcall("glDisable GL_CULL_FACE");
2267 break;
2268 case D3DCULL_CW:
2269 glEnable(GL_CULL_FACE);
2270 checkGLcall("glEnable GL_CULL_FACE");
2271 if (This->renderUpsideDown) {
2272 glFrontFace(GL_CW);
2273 checkGLcall("glFrontFace GL_CW");
2274 } else {
2275 glFrontFace(GL_CCW);
2276 checkGLcall("glFrontFace GL_CCW");
2278 glCullFace(GL_BACK);
2279 break;
2280 case D3DCULL_CCW:
2281 glEnable(GL_CULL_FACE);
2282 checkGLcall("glEnable GL_CULL_FACE");
2283 if (This->renderUpsideDown) {
2284 glFrontFace(GL_CCW);
2285 checkGLcall("glFrontFace GL_CCW");
2286 } else {
2287 glFrontFace(GL_CW);
2288 checkGLcall("glFrontFace GL_CW");
2290 glCullFace(GL_BACK);
2291 break;
2292 default:
2293 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2295 break;
2297 case D3DRS_SHADEMODE :
2298 switch ((D3DSHADEMODE) Value) {
2299 case D3DSHADE_FLAT:
2300 glShadeModel(GL_FLAT);
2301 checkGLcall("glShadeModel");
2302 break;
2303 case D3DSHADE_GOURAUD:
2304 glShadeModel(GL_SMOOTH);
2305 checkGLcall("glShadeModel");
2306 break;
2307 case D3DSHADE_PHONG:
2308 FIXME("D3DSHADE_PHONG isn't supported?\n");
2310 LEAVE_GL();
2311 return D3DERR_INVALIDCALL;
2312 default:
2313 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2315 break;
2317 case D3DRS_DITHERENABLE :
2318 if (Value) {
2319 glEnable(GL_DITHER);
2320 checkGLcall("glEnable GL_DITHER");
2321 } else {
2322 glDisable(GL_DITHER);
2323 checkGLcall("glDisable GL_DITHER");
2325 break;
2327 case D3DRS_ZWRITEENABLE :
2328 if (Value) {
2329 glDepthMask(1);
2330 checkGLcall("glDepthMask");
2331 } else {
2332 glDepthMask(0);
2333 checkGLcall("glDepthMask");
2335 break;
2337 case D3DRS_ZFUNC :
2339 int glParm = GL_LESS;
2341 switch ((D3DCMPFUNC) Value) {
2342 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2343 case D3DCMP_LESS: glParm=GL_LESS; break;
2344 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2345 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2346 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2347 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2348 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2349 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2350 default:
2351 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2353 glDepthFunc(glParm);
2354 checkGLcall("glDepthFunc");
2356 break;
2358 case D3DRS_AMBIENT :
2360 float col[4];
2361 D3DCOLORTOGLFLOAT4(Value, col);
2362 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2363 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2364 checkGLcall("glLightModel for MODEL_AMBIENT");
2367 break;
2369 case D3DRS_ALPHABLENDENABLE :
2370 if (Value) {
2371 glEnable(GL_BLEND);
2372 checkGLcall("glEnable GL_BLEND");
2373 } else {
2374 glDisable(GL_BLEND);
2375 checkGLcall("glDisable GL_BLEND");
2377 break;
2379 case D3DRS_SRCBLEND :
2380 case D3DRS_DESTBLEND :
2382 int newVal = GL_ZERO;
2383 switch (Value) {
2384 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2385 case D3DBLEND_ONE : newVal = GL_ONE; break;
2386 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2387 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2388 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2389 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2390 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2391 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2392 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2393 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2394 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2396 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2397 This->srcBlend = newVal;
2398 This->dstBlend = newVal;
2399 break;
2401 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2402 This->srcBlend = newVal;
2403 This->dstBlend = newVal;
2404 break;
2405 default:
2406 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2409 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2410 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2411 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2412 glBlendFunc(This->srcBlend, This->dstBlend);
2414 checkGLcall("glBlendFunc");
2416 break;
2418 case D3DRS_ALPHATESTENABLE :
2419 if (Value) {
2420 glEnable(GL_ALPHA_TEST);
2421 checkGLcall("glEnable GL_ALPHA_TEST");
2422 } else {
2423 glDisable(GL_ALPHA_TEST);
2424 checkGLcall("glDisable GL_ALPHA_TEST");
2426 break;
2428 case D3DRS_ALPHAFUNC :
2430 int glParm = GL_LESS;
2431 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2433 switch ((D3DCMPFUNC) Value) {
2434 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2435 case D3DCMP_LESS: glParm = GL_LESS; break;
2436 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2437 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2438 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2439 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2440 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2441 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2442 default:
2443 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2445 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2446 glAlphaFunc(glParm, ref);
2447 This->alphafunc = glParm;
2448 checkGLcall("glAlphaFunc");
2450 break;
2452 case D3DRS_ALPHAREF :
2454 int glParm = This->alphafunc;
2455 float ref = 1.0f;
2457 ref = ((float) Value) / 255.0f;
2458 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2459 glAlphaFunc(glParm, ref);
2460 checkGLcall("glAlphaFunc");
2462 break;
2464 case D3DRS_CLIPPLANEENABLE :
2465 case D3DRS_CLIPPING :
2467 /* Ensure we only do the changed clip planes */
2468 DWORD enable = 0xFFFFFFFF;
2469 DWORD disable = 0x00000000;
2471 /* If enabling / disabling all */
2472 if (State == D3DRS_CLIPPING) {
2473 if (Value) {
2474 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2475 disable = 0x00;
2476 } else {
2477 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2478 enable = 0x00;
2480 } else {
2481 enable = Value & ~OldValue;
2482 disable = ~Value & OldValue;
2485 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2486 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2487 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2488 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2489 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2490 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2492 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2493 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2494 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2495 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2496 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2497 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2499 /** update clipping status */
2500 if (enable) {
2501 This->StateBlock->clip_status.ClipUnion = 0;
2502 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2503 } else {
2504 This->StateBlock->clip_status.ClipUnion = 0;
2505 This->StateBlock->clip_status.ClipIntersection = 0;
2508 break;
2510 case D3DRS_BLENDOP :
2512 int glParm = GL_FUNC_ADD;
2514 switch ((D3DBLENDOP) Value) {
2515 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2516 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2517 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2518 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2519 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2520 default:
2521 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2523 TRACE("glBlendEquation(%x)\n", glParm);
2524 glBlendEquation(glParm);
2525 checkGLcall("glBlendEquation");
2527 break;
2529 case D3DRS_TEXTUREFACTOR :
2531 unsigned int i;
2533 /* Note the texture color applies to all textures whereas
2534 GL_TEXTURE_ENV_COLOR applies to active only */
2535 float col[4];
2536 D3DCOLORTOGLFLOAT4(Value, col);
2537 /* Set the default alpha blend color */
2538 glBlendColor(col[0], col[1], col[2], col[3]);
2539 checkGLcall("glBlendColor");
2541 /* And now the default texture color as well */
2542 for (i = 0; i < GL_LIMITS(textures); i++) {
2544 /* Note the D3DRS value applies to all textures, but GL has one
2545 per texture, so apply it now ready to be used! */
2546 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2547 #if defined(GL_VERSION_1_3)
2548 glActiveTexture(GL_TEXTURE0 + i);
2549 #else
2550 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2551 #endif
2552 checkGLcall("Activate texture.. to update const color");
2553 } else if (i>0) {
2554 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2557 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2558 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2561 break;
2563 case D3DRS_SPECULARENABLE :
2565 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2566 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2567 specular color. This is wrong:
2568 Separate specular color means the specular colour is maintained separately, whereas
2569 single color means it is merged in. However in both cases they are being used to
2570 some extent.
2571 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2572 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2573 running 1.4 yet!
2575 if (Value) {
2576 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2577 checkGLcall("glMaterialfv");
2578 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2579 glEnable(GL_COLOR_SUM_EXT);
2580 } else {
2581 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2583 checkGLcall("glEnable(GL_COLOR_SUM)");
2584 } else {
2585 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2587 /* for the case of enabled lighting: */
2588 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2589 checkGLcall("glMaterialfv");
2591 /* for the case of disabled lighting: */
2592 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2593 glDisable(GL_COLOR_SUM_EXT);
2594 } else {
2595 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2597 checkGLcall("glDisable(GL_COLOR_SUM)");
2600 break;
2602 case D3DRS_STENCILENABLE :
2603 if (Value) {
2604 glEnable(GL_STENCIL_TEST);
2605 checkGLcall("glEnable GL_STENCIL_TEST");
2606 } else {
2607 glDisable(GL_STENCIL_TEST);
2608 checkGLcall("glDisable GL_STENCIL_TEST");
2610 break;
2612 case D3DRS_STENCILFUNC :
2614 int glParm = GL_ALWAYS;
2615 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2616 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2618 switch ((D3DCMPFUNC) Value) {
2619 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2620 case D3DCMP_LESS: glParm=GL_LESS; break;
2621 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2622 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2623 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2624 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2625 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2626 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2627 default:
2628 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2630 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2631 This->stencilfunc = glParm;
2632 glStencilFunc(glParm, ref, mask);
2633 checkGLcall("glStencilFunc");
2635 break;
2637 case D3DRS_STENCILREF :
2639 int glParm = This->stencilfunc;
2640 int ref = 0;
2641 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2643 ref = Value;
2644 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2645 glStencilFunc(glParm, ref, mask);
2646 checkGLcall("glStencilFunc");
2648 break;
2650 case D3DRS_STENCILMASK :
2652 int glParm = This->stencilfunc;
2653 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2654 GLuint mask = Value;
2656 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2657 glStencilFunc(glParm, ref, mask);
2658 checkGLcall("glStencilFunc");
2660 break;
2662 case D3DRS_STENCILFAIL :
2664 GLenum fail ;
2665 GLenum zpass ;
2666 GLenum zfail ;
2668 fail = StencilOp(Value);
2669 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2670 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2671 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2672 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2674 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2675 glStencilOp(fail, zfail, zpass);
2676 checkGLcall("glStencilOp(fail, zfail, zpass);");
2678 break;
2679 case D3DRS_STENCILZFAIL :
2681 GLenum fail ;
2682 GLenum zpass ;
2683 GLenum zfail ;
2685 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2686 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2687 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2688 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2689 zfail = StencilOp(Value);
2691 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2692 glStencilOp(fail, zfail, zpass);
2693 checkGLcall("glStencilOp(fail, zfail, zpass);");
2695 break;
2696 case D3DRS_STENCILPASS :
2698 GLenum fail ;
2699 GLenum zpass ;
2700 GLenum zfail ;
2702 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2703 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2704 zpass = StencilOp(Value);
2705 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2706 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2708 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2709 glStencilOp(fail, zfail, zpass);
2710 checkGLcall("glStencilOp(fail, zfail, zpass);");
2712 break;
2714 case D3DRS_STENCILWRITEMASK :
2716 glStencilMask(Value);
2717 TRACE("glStencilMask(%lu)\n", Value);
2718 checkGLcall("glStencilMask");
2720 break;
2722 case D3DRS_FOGENABLE :
2724 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2725 glEnable(GL_FOG);
2726 checkGLcall("glEnable GL_FOG");
2727 } else {
2728 glDisable(GL_FOG);
2729 checkGLcall("glDisable GL_FOG");
2732 break;
2734 case D3DRS_RANGEFOGENABLE :
2736 if (Value) {
2737 TRACE("Enabled RANGEFOG");
2738 } else {
2739 TRACE("Disabled RANGEFOG");
2742 break;
2744 case D3DRS_FOGCOLOR :
2746 float col[4];
2747 D3DCOLORTOGLFLOAT4(Value, col);
2748 /* Set the default alpha blend color */
2749 glFogfv(GL_FOG_COLOR, &col[0]);
2750 checkGLcall("glFog GL_FOG_COLOR");
2752 break;
2754 case D3DRS_FOGTABLEMODE :
2756 glHint(GL_FOG_HINT, GL_NICEST);
2757 switch (Value) {
2758 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2759 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2760 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2761 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2762 default:
2763 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2765 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2766 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2769 break;
2771 case D3DRS_FOGVERTEXMODE :
2773 glHint(GL_FOG_HINT, GL_FASTEST);
2774 switch (Value) {
2775 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2776 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2777 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2778 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2779 default:
2780 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2782 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2783 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2786 break;
2788 case D3DRS_FOGSTART :
2790 tmpvalue.d = Value;
2791 glFogfv(GL_FOG_START, &tmpvalue.f);
2792 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2793 TRACE("Fog Start == %f\n", tmpvalue.f);
2795 break;
2797 case D3DRS_FOGEND :
2799 tmpvalue.d = Value;
2800 glFogfv(GL_FOG_END, &tmpvalue.f);
2801 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2802 TRACE("Fog End == %f\n", tmpvalue.f);
2804 break;
2806 case D3DRS_FOGDENSITY :
2808 tmpvalue.d = Value;
2809 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2810 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2812 break;
2814 case D3DRS_VERTEXBLEND :
2816 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2817 TRACE("Vertex Blending state to %ld\n", Value);
2819 break;
2821 case D3DRS_TWEENFACTOR :
2823 tmpvalue.d = Value;
2824 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2825 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2827 break;
2829 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2831 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2833 break;
2835 case D3DRS_COLORVERTEX :
2836 case D3DRS_DIFFUSEMATERIALSOURCE :
2837 case D3DRS_SPECULARMATERIALSOURCE :
2838 case D3DRS_AMBIENTMATERIALSOURCE :
2839 case D3DRS_EMISSIVEMATERIALSOURCE :
2841 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2843 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2844 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2845 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2846 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2847 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2848 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2850 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2851 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2852 Parm = GL_AMBIENT_AND_DIFFUSE;
2853 } else {
2854 Parm = GL_DIFFUSE;
2856 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2857 Parm = GL_AMBIENT;
2858 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2859 Parm = GL_EMISSION;
2860 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2861 Parm = GL_SPECULAR;
2862 } else {
2863 Parm = -1;
2866 if (Parm == -1) {
2867 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2868 } else {
2869 This->tracking_color = NEEDS_TRACKING;
2870 This->tracking_parm = Parm;
2873 } else {
2874 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2877 break;
2879 case D3DRS_LINEPATTERN :
2881 union {
2882 DWORD d;
2883 D3DLINEPATTERN lp;
2884 } tmppattern;
2885 tmppattern.d = Value;
2887 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2889 if (tmppattern.lp.wRepeatFactor) {
2890 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2891 checkGLcall("glLineStipple(repeat, linepattern)");
2892 glEnable(GL_LINE_STIPPLE);
2893 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2894 } else {
2895 glDisable(GL_LINE_STIPPLE);
2896 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2899 break;
2901 case D3DRS_ZBIAS :
2903 if (Value) {
2904 tmpvalue.d = Value;
2905 TRACE("ZBias value %f\n", tmpvalue.f);
2906 glPolygonOffset(0, -tmpvalue.f);
2907 checkGLcall("glPolygonOffset(0, -Value)");
2908 glEnable(GL_POLYGON_OFFSET_FILL);
2909 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2910 glEnable(GL_POLYGON_OFFSET_LINE);
2911 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2912 glEnable(GL_POLYGON_OFFSET_POINT);
2913 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2914 } else {
2915 glDisable(GL_POLYGON_OFFSET_FILL);
2916 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2917 glDisable(GL_POLYGON_OFFSET_LINE);
2918 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2919 glDisable(GL_POLYGON_OFFSET_POINT);
2920 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2923 break;
2925 case D3DRS_NORMALIZENORMALS :
2926 if (Value) {
2927 glEnable(GL_NORMALIZE);
2928 checkGLcall("glEnable(GL_NORMALIZE);");
2929 } else {
2930 glDisable(GL_NORMALIZE);
2931 checkGLcall("glDisable(GL_NORMALIZE);");
2933 break;
2935 case D3DRS_POINTSIZE :
2936 tmpvalue.d = Value;
2937 TRACE("Set point size to %f\n", tmpvalue.f);
2938 glPointSize(tmpvalue.f);
2939 checkGLcall("glPointSize(...);");
2940 break;
2942 case D3DRS_POINTSIZE_MIN :
2943 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2944 tmpvalue.d = Value;
2945 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2946 checkGLcall("glPointParameterfEXT(...);");
2947 } else {
2948 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2950 break;
2952 case D3DRS_POINTSIZE_MAX :
2953 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2954 tmpvalue.d = Value;
2955 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2956 checkGLcall("glPointParameterfEXT(...);");
2957 } else {
2958 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2960 break;
2962 case D3DRS_POINTSCALE_A :
2963 case D3DRS_POINTSCALE_B :
2964 case D3DRS_POINTSCALE_C :
2965 case D3DRS_POINTSCALEENABLE :
2967 /* If enabled, supply the parameters, otherwise fall back to defaults */
2968 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2969 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2970 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2971 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2972 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2974 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2975 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2976 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2977 } else {
2978 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2980 } else {
2981 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2982 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2983 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2984 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2985 } else {
2986 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2989 break;
2992 case D3DRS_COLORWRITEENABLE :
2994 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2995 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2996 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2997 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2998 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2999 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3000 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3001 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3002 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3003 checkGLcall("glColorMask(...)");
3005 break;
3007 case D3DRS_LOCALVIEWER :
3009 GLint state = (Value) ? 1 : 0;
3010 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3011 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3013 break;
3015 case D3DRS_LASTPIXEL :
3017 if (Value) {
3018 TRACE("Last Pixel Drawing Enabled\n");
3019 } else {
3020 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3023 break;
3025 case D3DRS_SOFTWAREVERTEXPROCESSING :
3027 if (Value) {
3028 TRACE("Software Processing Enabled\n");
3029 } else {
3030 TRACE("Software Processing Disabled\n");
3033 break;
3035 /** not supported */
3036 case D3DRS_ZVISIBLE :
3038 LEAVE_GL();
3039 return D3DERR_INVALIDCALL;
3042 /* Unhandled yet...! */
3043 case D3DRS_EDGEANTIALIAS :
3044 case D3DRS_WRAP0 :
3045 case D3DRS_WRAP1 :
3046 case D3DRS_WRAP2 :
3047 case D3DRS_WRAP3 :
3048 case D3DRS_WRAP4 :
3049 case D3DRS_WRAP5 :
3050 case D3DRS_WRAP6 :
3051 case D3DRS_WRAP7 :
3052 case D3DRS_POINTSPRITEENABLE :
3053 case D3DRS_MULTISAMPLEANTIALIAS :
3054 case D3DRS_MULTISAMPLEMASK :
3055 case D3DRS_PATCHEDGESTYLE :
3056 case D3DRS_PATCHSEGMENTS :
3057 case D3DRS_DEBUGMONITORTOKEN :
3058 case D3DRS_POSITIONORDER :
3059 case D3DRS_NORMALORDER :
3060 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3061 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3062 break;
3063 default:
3064 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3067 LEAVE_GL();
3069 return D3D_OK;
3071 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3072 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3073 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3074 *pValue = This->StateBlock->renderstate[State];
3075 return D3D_OK;
3077 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3078 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3080 TRACE("(%p)\n", This);
3082 return IDirect3DDeviceImpl_BeginStateBlock(This);
3084 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3085 IDirect3DStateBlockImpl* pSB;
3086 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3087 HRESULT res;
3089 TRACE("(%p)\n", This);
3091 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3092 *pToken = (DWORD) pSB;
3093 return res;
3096 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3097 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3098 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3100 TRACE("(%p)\n", This);
3102 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3105 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3106 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3107 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3109 TRACE("(%p)\n", This);
3111 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3113 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3114 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3115 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3117 TRACE("(%p)\n", This);
3119 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3122 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3123 IDirect3DStateBlockImpl* pSB;
3124 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3125 HRESULT res;
3127 TRACE("(%p) : for type %d\n", This, Type);
3129 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3130 *pToken = (DWORD) pSB;
3131 return res;
3134 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3135 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3136 FIXME("(%p) : stub\n", This);
3137 if (NULL == pClipStatus) {
3138 return D3DERR_INVALIDCALL;
3140 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3141 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3142 return D3D_OK;
3144 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3145 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3146 FIXME("(%p) : stub\n", This);
3147 if (NULL == pClipStatus) {
3148 return D3DERR_INVALIDCALL;
3150 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3151 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3152 return D3D_OK;
3154 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3155 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3156 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3157 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3158 if (*ppTexture)
3159 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3160 return D3D_OK;
3162 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3164 IDirect3DBaseTexture8 *oldTxt;
3165 BOOL reapplyStates = TRUE;
3166 INT oldTextureDimensions = -1;
3167 DWORD reapplyFlags = 0;
3169 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3170 D3DRESOURCETYPE textureType;
3172 oldTxt = This->UpdateStateBlock->textures[Stage];
3173 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3175 /* Reject invalid texture units */
3176 if (Stage >= GL_LIMITS(textures)) {
3177 TRACE("Attempt to access invalid texture rejected\n");
3178 return D3DERR_INVALIDCALL;
3181 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3182 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3183 This->UpdateStateBlock->textures[Stage] = pTexture;
3185 /* Handle recording of state blocks */
3186 if (This->isRecordingState) {
3187 TRACE("Recording... not performing anything\n");
3188 return D3D_OK;
3191 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3192 ENTER_GL();
3194 /* Make appropriate texture active */
3195 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3196 #if defined(GL_VERSION_1_3)
3197 glActiveTexture(GL_TEXTURE0 + Stage);
3198 checkGLcall("glActiveTexture");
3199 #else
3200 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3201 checkGLcall("glActiveTextureARB");
3202 #endif
3203 } else if (Stage>0) {
3204 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3207 /* Decrement the count of the previous texture */
3208 if (NULL != oldTxt) {
3209 IDirect3DBaseTexture8Impl_Release(oldTxt);
3212 if (NULL != pTexture) {
3213 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3215 /* Now setup the texture appropraitly */
3216 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3218 if (textureType == D3DRTYPE_TEXTURE) {
3219 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3220 TRACE("Skipping setting texture as old == new\n");
3221 reapplyStates = FALSE;
3222 } else {
3223 /* Standard 2D texture */
3224 TRACE("Standard 2d texture\n");
3225 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3227 /* Load up the texture now */
3228 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3230 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3231 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3232 TRACE("Skipping setting texture as old == new\n");
3233 reapplyStates = FALSE;
3234 } else {
3235 /* Standard 3D (volume) texture */
3236 TRACE("Standard 3d texture\n");
3237 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3239 /* Load up the texture now */
3240 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3242 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3243 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3244 TRACE("Skipping setting texture as old == new\n");
3245 reapplyStates = FALSE;
3246 } else {
3247 /* Standard Cube texture */
3248 TRACE("Standard Cube texture\n");
3249 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3251 /* Load up the texture now */
3252 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3254 } else {
3255 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3257 } else {
3258 TRACE("Setting to no texture (ie default texture)\n");
3259 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3260 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3261 checkGLcall("glBindTexture");
3262 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3265 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3266 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3267 glDisable(oldTextureDimensions);
3268 checkGLcall("Disable oldTextureDimensions");
3269 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3270 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3271 checkGLcall("glEnable new texture dimensions");
3274 /* If Alpha arg1 is texture then handle the special case when there changes between a
3275 texture and no texture - See comments in set_tex_op */
3276 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3277 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3279 reapplyFlags |= REAPPLY_ALPHAOP;
3284 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3285 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3286 if (reapplyStates) {
3287 setupTextureStates(iface, Stage, reapplyFlags);
3290 LEAVE_GL();
3292 return D3D_OK;
3295 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3296 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3297 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3298 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3299 return D3D_OK;
3302 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3303 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3304 union {
3305 float f;
3306 DWORD d;
3307 } tmpvalue;
3309 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3311 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3313 /* Reject invalid texture units */
3314 if (Stage >= GL_LIMITS(textures)) {
3315 TRACE("Attempt to access invalid texture rejected\n");
3316 return D3DERR_INVALIDCALL;
3319 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3320 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3321 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3323 /* Handle recording of state blocks */
3324 if (This->isRecordingState) {
3325 TRACE("Recording... not performing anything\n");
3326 return D3D_OK;
3329 ENTER_GL();
3331 /* Make appropriate texture active */
3332 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3333 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3334 #if defined(GL_VERSION_1_3)
3335 glActiveTexture(GL_TEXTURE0 + Stage);
3336 vcheckGLcall("glActiveTexture");
3337 #else
3338 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3339 vcheckGLcall("glActiveTextureARB");
3340 #endif
3341 } else if (Stage > 0) {
3342 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3345 switch (Type) {
3347 case D3DTSS_MINFILTER :
3348 case D3DTSS_MIPFILTER :
3350 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3351 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3352 GLint realVal = GL_LINEAR;
3354 if (ValueMIN == D3DTEXF_NONE) {
3355 /* Doesn't really make sense - Windows just seems to disable
3356 mipmapping when this occurs */
3357 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3358 realVal = GL_LINEAR;
3359 } else if (ValueMIN == D3DTEXF_POINT) {
3360 /* GL_NEAREST_* */
3361 if (ValueMIP == D3DTEXF_NONE) {
3362 realVal = GL_NEAREST;
3363 } else if (ValueMIP == D3DTEXF_POINT) {
3364 realVal = GL_NEAREST_MIPMAP_NEAREST;
3365 } else if (ValueMIP == D3DTEXF_LINEAR) {
3366 realVal = GL_NEAREST_MIPMAP_LINEAR;
3367 } else {
3368 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3369 realVal = GL_NEAREST;
3371 } else if (ValueMIN == D3DTEXF_LINEAR) {
3372 /* GL_LINEAR_* */
3373 if (ValueMIP == D3DTEXF_NONE) {
3374 realVal = GL_LINEAR;
3375 } else if (ValueMIP == D3DTEXF_POINT) {
3376 realVal = GL_LINEAR_MIPMAP_NEAREST;
3377 } else if (ValueMIP == D3DTEXF_LINEAR) {
3378 realVal = GL_LINEAR_MIPMAP_LINEAR;
3379 } else {
3380 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3381 realVal = GL_LINEAR;
3383 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3384 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3385 if (ValueMIP == D3DTEXF_NONE) {
3386 realVal = GL_LINEAR_MIPMAP_LINEAR;
3387 } else if (ValueMIP == D3DTEXF_POINT) {
3388 realVal = GL_LINEAR_MIPMAP_NEAREST;
3389 } else if (ValueMIP == D3DTEXF_LINEAR) {
3390 realVal = GL_LINEAR_MIPMAP_LINEAR;
3391 } else {
3392 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3393 realVal = GL_LINEAR;
3395 } else {
3396 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3397 realVal = GL_LINEAR;
3399 } else {
3400 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3401 realVal = GL_LINEAR_MIPMAP_LINEAR;
3404 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3405 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3406 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3408 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3410 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3411 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3412 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3413 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3414 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3417 break;
3419 case D3DTSS_MAGFILTER :
3421 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3422 GLint realVal = GL_NEAREST;
3424 if (ValueMAG == D3DTEXF_POINT) {
3425 realVal = GL_NEAREST;
3426 } else if (ValueMAG == D3DTEXF_LINEAR) {
3427 realVal = GL_LINEAR;
3428 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3429 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3430 realVal = GL_LINEAR;
3431 } else {
3432 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3433 realVal = GL_NEAREST;
3435 } else {
3436 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3437 realVal = GL_NEAREST;
3439 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3440 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3441 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3443 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3445 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3446 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3447 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3448 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3449 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3452 break;
3454 case D3DTSS_MAXMIPLEVEL :
3457 * Not really the same, but the more apprioprate than nothing
3459 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3460 GL_TEXTURE_BASE_LEVEL,
3461 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3462 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3464 break;
3466 case D3DTSS_MAXANISOTROPY :
3468 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3469 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3470 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3471 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3472 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3475 break;
3477 case D3DTSS_MIPMAPLODBIAS :
3479 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3480 tmpvalue.d = Value;
3481 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3482 GL_TEXTURE_LOD_BIAS_EXT,
3483 tmpvalue.f);
3484 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3487 break;
3489 case D3DTSS_ALPHAOP :
3490 case D3DTSS_COLOROP :
3493 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3494 /* TODO: Disable by making this and all later levels disabled */
3495 glDisable(GL_TEXTURE_1D);
3496 checkGLcall("Disable GL_TEXTURE_1D");
3497 glDisable(GL_TEXTURE_2D);
3498 checkGLcall("Disable GL_TEXTURE_2D");
3499 glDisable(GL_TEXTURE_3D);
3500 checkGLcall("Disable GL_TEXTURE_3D");
3501 break; /* Don't bother setting the texture operations */
3502 } else {
3503 /* Enable only the appropriate texture dimension */
3504 if (Type == D3DTSS_COLOROP) {
3505 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3506 glEnable(GL_TEXTURE_1D);
3507 checkGLcall("Enable GL_TEXTURE_1D");
3508 } else {
3509 glDisable(GL_TEXTURE_1D);
3510 checkGLcall("Disable GL_TEXTURE_1D");
3512 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3513 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3514 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3515 checkGLcall("Enable GL_TEXTURE_2D");
3516 } else {
3517 glEnable(GL_TEXTURE_2D);
3518 checkGLcall("Enable GL_TEXTURE_2D");
3520 } else {
3521 glDisable(GL_TEXTURE_2D);
3522 checkGLcall("Disable GL_TEXTURE_2D");
3524 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3525 glEnable(GL_TEXTURE_3D);
3526 checkGLcall("Enable GL_TEXTURE_3D");
3527 } else {
3528 glDisable(GL_TEXTURE_3D);
3529 checkGLcall("Disable GL_TEXTURE_3D");
3531 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3532 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3533 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3534 } else {
3535 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3536 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3540 /* Drop through... (Except disable case) */
3541 case D3DTSS_COLORARG0 :
3542 case D3DTSS_COLORARG1 :
3543 case D3DTSS_COLORARG2 :
3544 case D3DTSS_ALPHAARG0 :
3545 case D3DTSS_ALPHAARG1 :
3546 case D3DTSS_ALPHAARG2 :
3548 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3549 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3550 if (isAlphaArg) {
3551 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3552 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3553 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3554 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3555 } else {
3556 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3557 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3558 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3559 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3562 break;
3565 case D3DTSS_ADDRESSU :
3566 case D3DTSS_ADDRESSV :
3567 case D3DTSS_ADDRESSW :
3569 GLint wrapParm = GL_REPEAT;
3571 switch (Value) {
3572 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3573 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3574 case D3DTADDRESS_BORDER:
3576 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3577 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3578 } else {
3579 /* FIXME: Not right, but better */
3580 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3581 wrapParm = GL_REPEAT;
3584 break;
3585 case D3DTADDRESS_MIRROR:
3587 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3588 wrapParm = GL_MIRRORED_REPEAT_ARB;
3589 } else {
3590 /* Unsupported in OpenGL pre-1.4 */
3591 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3592 wrapParm = GL_REPEAT;
3595 break;
3596 case D3DTADDRESS_MIRRORONCE:
3598 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3599 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3600 } else {
3601 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3602 wrapParm = GL_REPEAT;
3605 break;
3607 default:
3608 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3609 wrapParm = GL_REPEAT;
3612 switch (Type) {
3613 case D3DTSS_ADDRESSU:
3614 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3615 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3616 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3617 break;
3618 case D3DTSS_ADDRESSV:
3619 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3620 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3621 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3622 break;
3623 case D3DTSS_ADDRESSW:
3624 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3625 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3626 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3627 break;
3628 default: /* nop */
3629 break; /** stupic compilator */
3632 break;
3634 case D3DTSS_BORDERCOLOR :
3636 float col[4];
3637 D3DCOLORTOGLFLOAT4(Value, col);
3638 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3639 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3640 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3642 break;
3644 case D3DTSS_TEXCOORDINDEX :
3646 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3648 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3649 one flag, you can still specify an index value, which the system uses to
3650 determine the texture wrapping mode.
3651 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3652 means use the vertex position (camera-space) as the input texture coordinates
3653 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3654 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3655 to the TEXCOORDINDEX value */
3657 /**
3658 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3660 switch (Value & 0xFFFF0000) {
3661 case D3DTSS_TCI_PASSTHRU:
3662 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3663 glDisable(GL_TEXTURE_GEN_S);
3664 glDisable(GL_TEXTURE_GEN_T);
3665 glDisable(GL_TEXTURE_GEN_R);
3666 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3667 break;
3669 case D3DTSS_TCI_CAMERASPACEPOSITION:
3670 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3671 as the input texture coordinates for this stage's texture transformation. This
3672 equates roughly to EYE_LINEAR */
3674 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3675 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3676 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3677 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3678 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3680 glMatrixMode(GL_MODELVIEW);
3681 glPushMatrix();
3682 glLoadIdentity();
3683 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3684 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3685 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3686 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3687 glPopMatrix();
3689 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3690 glEnable(GL_TEXTURE_GEN_S);
3691 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3692 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3693 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3694 glEnable(GL_TEXTURE_GEN_T);
3695 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3696 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3697 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3698 glEnable(GL_TEXTURE_GEN_R);
3699 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3700 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3701 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3703 break;
3705 case D3DTSS_TCI_CAMERASPACENORMAL:
3707 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3708 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3709 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3710 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3711 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3712 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3714 glMatrixMode(GL_MODELVIEW);
3715 glPushMatrix();
3716 glLoadIdentity();
3717 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3718 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3719 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3720 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3721 glPopMatrix();
3723 glEnable(GL_TEXTURE_GEN_S);
3724 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3725 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3726 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3727 glEnable(GL_TEXTURE_GEN_T);
3728 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3729 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3730 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3731 glEnable(GL_TEXTURE_GEN_R);
3732 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3733 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3734 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3737 break;
3739 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3741 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
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 glEnable(GL_TEXTURE_GEN_S);
3758 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3759 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3760 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3761 glEnable(GL_TEXTURE_GEN_T);
3762 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3763 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3764 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3765 glEnable(GL_TEXTURE_GEN_R);
3766 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3767 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3768 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3771 break;
3773 /* Unhandled types: */
3774 default:
3775 /* Todo: */
3776 /* ? disable GL_TEXTURE_GEN_n ? */
3777 glDisable(GL_TEXTURE_GEN_S);
3778 glDisable(GL_TEXTURE_GEN_T);
3779 glDisable(GL_TEXTURE_GEN_R);
3780 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3781 break;
3784 break;
3786 /* Unhandled */
3787 case D3DTSS_TEXTURETRANSFORMFLAGS :
3788 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3789 break;
3791 case D3DTSS_BUMPENVMAT00 :
3792 case D3DTSS_BUMPENVMAT01 :
3793 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3794 break;
3795 case D3DTSS_BUMPENVMAT10 :
3796 case D3DTSS_BUMPENVMAT11 :
3797 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3798 break;
3800 case D3DTSS_BUMPENVLSCALE :
3801 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3802 break;
3804 case D3DTSS_BUMPENVLOFFSET :
3805 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3806 break;
3808 case D3DTSS_RESULTARG :
3809 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3810 break;
3812 default:
3813 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3814 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3817 LEAVE_GL();
3819 return D3D_OK;
3821 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3822 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3823 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3824 return D3D_OK;
3826 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3827 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3828 FIXME("(%p) : stub\n", This);
3829 return D3D_OK;
3831 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3832 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3833 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3834 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3835 if (PaletteNumber >= MAX_PALETTES) {
3836 return D3DERR_INVALIDCALL;
3838 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3839 return D3D_OK;
3841 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3842 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3843 if (PaletteNumber >= MAX_PALETTES) {
3844 return D3DERR_INVALIDCALL;
3846 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3847 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3848 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3849 return D3D_OK;
3851 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3852 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3853 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3854 if (PaletteNumber >= MAX_PALETTES) {
3855 return D3DERR_INVALIDCALL;
3857 This->currentPalette = PaletteNumber;
3859 #if defined(GL_EXT_paletted_texture)
3860 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3862 ENTER_GL();
3864 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3865 GL_RGBA, /* internal format */
3866 256, /* table size */
3867 GL_RGBA, /* table format */
3868 GL_UNSIGNED_BYTE, /* table type */
3869 This->palettes[PaletteNumber]);
3870 checkGLcall("glColorTableEXT");
3872 LEAVE_GL();
3874 } else {
3875 /* Delayed palette handling ... waiting for software emulation into preload code */
3877 #endif
3878 return D3D_OK;
3880 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3881 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3882 *PaletteNumber = This->currentPalette;
3883 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3884 return D3D_OK;
3886 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3888 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3889 This->StateBlock->streamIsUP = FALSE;
3891 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3892 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3894 return D3D_OK;
3896 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3897 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3898 UINT idxStride = 2;
3899 IDirect3DIndexBuffer8 *pIB;
3900 D3DINDEXBUFFER_DESC IdxBufDsc;
3902 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3903 pIB = This->StateBlock->pIndexData;
3904 This->StateBlock->streamIsUP = FALSE;
3906 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3907 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3908 minIndex, NumVertices, startIndex, primCount);
3910 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3911 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3912 idxStride = 2;
3913 } else {
3914 idxStride = 4;
3917 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3918 minIndex);
3920 return D3D_OK;
3922 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3923 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3925 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3926 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3928 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3930 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3931 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3932 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3933 This->StateBlock->streamIsUP = TRUE;
3934 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3935 This->StateBlock->stream_stride[0] = 0;
3936 This->StateBlock->stream_source[0] = NULL;
3938 /*stream zero settings set to null at end */
3939 return D3D_OK;
3941 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3942 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3943 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3944 UINT VertexStreamZeroStride) {
3945 int idxStride;
3946 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3947 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),
3948 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3950 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3951 if (IndexDataFormat == D3DFMT_INDEX16) {
3952 idxStride = 2;
3953 } else {
3954 idxStride = 4;
3957 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3958 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3959 This->StateBlock->streamIsUP = TRUE;
3960 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3961 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3963 /*stream zero settings set to null at end */
3964 This->StateBlock->stream_source[0] = NULL;
3965 This->StateBlock->stream_stride[0] = 0;
3966 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3968 return D3D_OK;
3970 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3971 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3972 FIXME("(%p) : stub\n", This); return D3D_OK;
3974 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3975 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3976 IDirect3DVertexShaderImpl* object;
3977 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3978 HRESULT res;
3979 UINT i;
3981 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3982 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3983 return D3DERR_INVALIDCALL;
3985 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3986 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3987 return D3DERR_OUTOFVIDEOMEMORY;
3990 /** Create the Vertex Shader */
3991 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3992 /** TODO: check FAILED(res) */
3994 /** Create and Bind the Vertex Shader Declaration */
3995 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3996 /** TODO: check FAILED(res) */
3998 VertexShaders[i] = object;
3999 VertexShaderDeclarations[i] = attached_decl;
4000 *pHandle = VS_HIGHESTFIXEDFXF + i;
4001 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4003 return D3D_OK;
4005 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4006 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4008 This->UpdateStateBlock->VertexShader = Handle;
4009 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4010 This->UpdateStateBlock->Set.vertexShader = TRUE;
4012 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4013 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4014 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4015 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4016 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4017 } else { /* use a fvf, so desactivate the vshader decl */
4018 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4019 This->UpdateStateBlock->vertexShaderDecl = NULL;
4020 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4021 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4023 /* Handle recording of state blocks */
4024 if (This->isRecordingState) {
4025 TRACE("Recording... not performing anything\n");
4026 return D3D_OK;
4029 * TODO: merge HAL shaders context switching from prototype
4031 return D3D_OK;
4033 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4034 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4035 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4036 *pHandle = This->StateBlock->VertexShader;
4037 return D3D_OK;
4040 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4041 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4042 IDirect3DVertexShaderImpl* object;
4043 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4045 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4046 return D3DERR_INVALIDCALL;
4050 * Delete Vertex Shader
4052 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4053 if (NULL == object) {
4054 return D3DERR_INVALIDCALL;
4056 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4057 /* TODO: check validity of object */
4058 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4059 if (object->prgId != 0) {
4060 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4062 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4063 HeapFree(GetProcessHeap(), 0, (void *)object);
4064 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4067 * Delete Vertex Shader Declaration
4069 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4070 if (NULL == attached_decl) {
4071 return D3DERR_INVALIDCALL;
4073 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4074 /* TODO: check validity of object */
4075 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4076 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4077 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4079 return D3D_OK;
4082 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4083 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4085 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4086 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4087 return D3DERR_INVALIDCALL;
4089 if (NULL == pConstantData) {
4090 return D3DERR_INVALIDCALL;
4092 if (ConstantCount > 1) {
4093 const FLOAT* f = (const FLOAT*)pConstantData;
4094 UINT i;
4095 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4096 for (i = 0; i < ConstantCount; ++i) {
4097 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4098 f += 4;
4100 } else {
4101 const FLOAT* f = (const FLOAT*) pConstantData;
4102 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4104 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4105 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4106 return D3D_OK;
4108 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4109 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4111 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4112 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4113 return D3DERR_INVALIDCALL;
4115 if (NULL == pConstantData) {
4116 return D3DERR_INVALIDCALL;
4118 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4119 return D3D_OK;
4121 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4122 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4123 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4125 attached_decl = VERTEX_SHADER_DECL(Handle);
4126 if (NULL == attached_decl) {
4127 return D3DERR_INVALIDCALL;
4129 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4131 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4132 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4133 IDirect3DVertexShaderImpl* object;
4135 object = VERTEX_SHADER(Handle);
4136 if (NULL == object) {
4137 return D3DERR_INVALIDCALL;
4139 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4142 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4143 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4144 IDirect3DIndexBuffer8 *oldIdxs;
4146 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4147 oldIdxs = This->StateBlock->pIndexData;
4149 This->UpdateStateBlock->Changed.Indices = TRUE;
4150 This->UpdateStateBlock->Set.Indices = TRUE;
4151 This->UpdateStateBlock->pIndexData = pIndexData;
4152 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4154 /* Handle recording of state blocks */
4155 if (This->isRecordingState) {
4156 TRACE("Recording... not performing anything\n");
4157 return D3D_OK;
4160 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4161 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4162 return D3D_OK;
4164 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4165 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4166 FIXME("(%p) : stub\n", This);
4168 *ppIndexData = This->StateBlock->pIndexData;
4169 /* up ref count on ppindexdata */
4170 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4171 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4173 return D3D_OK;
4175 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4176 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4177 IDirect3DPixelShaderImpl* object;
4178 HRESULT res;
4179 UINT i;
4181 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4182 if (NULL == pFunction || NULL == pHandle) {
4183 return D3DERR_INVALIDCALL;
4185 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4186 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4187 return D3DERR_OUTOFVIDEOMEMORY;
4190 /** Create the Pixel Shader */
4191 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4192 if (SUCCEEDED(res)) {
4193 PixelShaders[i] = object;
4194 *pHandle = VS_HIGHESTFIXEDFXF + i;
4195 return D3D_OK;
4197 *pHandle = 0xFFFFFFFF;
4198 return res;
4201 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4202 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4204 This->UpdateStateBlock->PixelShader = Handle;
4205 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4206 This->UpdateStateBlock->Set.pixelShader = TRUE;
4208 /* Handle recording of state blocks */
4209 if (This->isRecordingState) {
4210 TRACE_(d3d_shader)("Recording... not performing anything\n");
4211 return D3D_OK;
4214 if (Handle != 0) {
4215 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4216 } else {
4217 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4220 return D3D_OK;
4223 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4224 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4225 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4226 *pHandle = This->StateBlock->PixelShader;
4227 return D3D_OK;
4230 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4231 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4232 IDirect3DPixelShaderImpl* object;
4234 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4235 return D3DERR_INVALIDCALL;
4237 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4238 if (NULL == object) {
4239 return D3DERR_INVALIDCALL;
4241 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4242 /* TODO: check validity of object before free */
4243 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4244 if (object->prgId != 0) {
4245 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4247 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4248 HeapFree(GetProcessHeap(), 0, (void *)object);
4249 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4251 return D3D_OK;
4254 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4255 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4257 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4258 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4259 return D3DERR_INVALIDCALL;
4261 if (NULL == pConstantData) {
4262 return D3DERR_INVALIDCALL;
4264 if (ConstantCount > 1) {
4265 const FLOAT* f = (const FLOAT*)pConstantData;
4266 UINT i;
4267 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4268 for (i = 0; i < ConstantCount; ++i) {
4269 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4270 f += 4;
4272 } else {
4273 const FLOAT* f = (const FLOAT*) pConstantData;
4274 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4276 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4277 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4278 return D3D_OK;
4280 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4281 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4283 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4284 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4285 return D3DERR_INVALIDCALL;
4287 if (NULL == pConstantData) {
4288 return D3DERR_INVALIDCALL;
4290 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4291 return D3D_OK;
4293 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4294 IDirect3DPixelShaderImpl* object;
4296 object = PIXEL_SHADER(Handle);
4297 if (NULL == object) {
4298 return D3DERR_INVALIDCALL;
4300 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4302 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4303 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4304 FIXME("(%p) : stub\n", This); return D3D_OK;
4306 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4307 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4308 FIXME("(%p) : stub\n", This); return D3D_OK;
4310 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4311 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4312 FIXME("(%p) : stub\n", This); return D3D_OK;
4315 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4316 IDirect3DVertexBuffer8 *oldSrc;
4317 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4319 oldSrc = This->StateBlock->stream_source[StreamNumber];
4320 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4322 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4323 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4324 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4325 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4327 /* Handle recording of state blocks */
4328 if (This->isRecordingState) {
4329 TRACE("Recording... not performing anything\n");
4330 return D3D_OK;
4333 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4334 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4335 return D3D_OK;
4337 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4338 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4339 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4340 *pStream = This->StateBlock->stream_source[StreamNumber];
4341 *pStride = This->StateBlock->stream_stride[StreamNumber];
4342 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4343 return D3D_OK;
4347 IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4349 IDirect3DDevice8Impl_QueryInterface,
4350 IDirect3DDevice8Impl_AddRef,
4351 IDirect3DDevice8Impl_Release,
4352 IDirect3DDevice8Impl_TestCooperativeLevel,
4353 IDirect3DDevice8Impl_GetAvailableTextureMem,
4354 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4355 IDirect3DDevice8Impl_GetDirect3D,
4356 IDirect3DDevice8Impl_GetDeviceCaps,
4357 IDirect3DDevice8Impl_GetDisplayMode,
4358 IDirect3DDevice8Impl_GetCreationParameters,
4359 IDirect3DDevice8Impl_SetCursorProperties,
4360 IDirect3DDevice8Impl_SetCursorPosition,
4361 IDirect3DDevice8Impl_ShowCursor,
4362 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4363 IDirect3DDevice8Impl_Reset,
4364 IDirect3DDevice8Impl_Present,
4365 IDirect3DDevice8Impl_GetBackBuffer,
4366 IDirect3DDevice8Impl_GetRasterStatus,
4367 IDirect3DDevice8Impl_SetGammaRamp,
4368 IDirect3DDevice8Impl_GetGammaRamp,
4369 IDirect3DDevice8Impl_CreateTexture,
4370 IDirect3DDevice8Impl_CreateVolumeTexture,
4371 IDirect3DDevice8Impl_CreateCubeTexture,
4372 IDirect3DDevice8Impl_CreateVertexBuffer,
4373 IDirect3DDevice8Impl_CreateIndexBuffer,
4374 IDirect3DDevice8Impl_CreateRenderTarget,
4375 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4376 IDirect3DDevice8Impl_CreateImageSurface,
4377 IDirect3DDevice8Impl_CopyRects,
4378 IDirect3DDevice8Impl_UpdateTexture,
4379 IDirect3DDevice8Impl_GetFrontBuffer,
4380 IDirect3DDevice8Impl_SetRenderTarget,
4381 IDirect3DDevice8Impl_GetRenderTarget,
4382 IDirect3DDevice8Impl_GetDepthStencilSurface,
4383 IDirect3DDevice8Impl_BeginScene,
4384 IDirect3DDevice8Impl_EndScene,
4385 IDirect3DDevice8Impl_Clear,
4386 IDirect3DDevice8Impl_SetTransform,
4387 IDirect3DDevice8Impl_GetTransform,
4388 IDirect3DDevice8Impl_MultiplyTransform,
4389 IDirect3DDevice8Impl_SetViewport,
4390 IDirect3DDevice8Impl_GetViewport,
4391 IDirect3DDevice8Impl_SetMaterial,
4392 IDirect3DDevice8Impl_GetMaterial,
4393 IDirect3DDevice8Impl_SetLight,
4394 IDirect3DDevice8Impl_GetLight,
4395 IDirect3DDevice8Impl_LightEnable,
4396 IDirect3DDevice8Impl_GetLightEnable,
4397 IDirect3DDevice8Impl_SetClipPlane,
4398 IDirect3DDevice8Impl_GetClipPlane,
4399 IDirect3DDevice8Impl_SetRenderState,
4400 IDirect3DDevice8Impl_GetRenderState,
4401 IDirect3DDevice8Impl_BeginStateBlock,
4402 IDirect3DDevice8Impl_EndStateBlock,
4403 IDirect3DDevice8Impl_ApplyStateBlock,
4404 IDirect3DDevice8Impl_CaptureStateBlock,
4405 IDirect3DDevice8Impl_DeleteStateBlock,
4406 IDirect3DDevice8Impl_CreateStateBlock,
4407 IDirect3DDevice8Impl_SetClipStatus,
4408 IDirect3DDevice8Impl_GetClipStatus,
4409 IDirect3DDevice8Impl_GetTexture,
4410 IDirect3DDevice8Impl_SetTexture,
4411 IDirect3DDevice8Impl_GetTextureStageState,
4412 IDirect3DDevice8Impl_SetTextureStageState,
4413 IDirect3DDevice8Impl_ValidateDevice,
4414 IDirect3DDevice8Impl_GetInfo,
4415 IDirect3DDevice8Impl_SetPaletteEntries,
4416 IDirect3DDevice8Impl_GetPaletteEntries,
4417 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4418 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4419 IDirect3DDevice8Impl_DrawPrimitive,
4420 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4421 IDirect3DDevice8Impl_DrawPrimitiveUP,
4422 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4423 IDirect3DDevice8Impl_ProcessVertices,
4424 IDirect3DDevice8Impl_CreateVertexShader,
4425 IDirect3DDevice8Impl_SetVertexShader,
4426 IDirect3DDevice8Impl_GetVertexShader,
4427 IDirect3DDevice8Impl_DeleteVertexShader,
4428 IDirect3DDevice8Impl_SetVertexShaderConstant,
4429 IDirect3DDevice8Impl_GetVertexShaderConstant,
4430 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4431 IDirect3DDevice8Impl_GetVertexShaderFunction,
4432 IDirect3DDevice8Impl_SetStreamSource,
4433 IDirect3DDevice8Impl_GetStreamSource,
4434 IDirect3DDevice8Impl_SetIndices,
4435 IDirect3DDevice8Impl_GetIndices,
4436 IDirect3DDevice8Impl_CreatePixelShader,
4437 IDirect3DDevice8Impl_SetPixelShader,
4438 IDirect3DDevice8Impl_GetPixelShader,
4439 IDirect3DDevice8Impl_DeletePixelShader,
4440 IDirect3DDevice8Impl_SetPixelShaderConstant,
4441 IDirect3DDevice8Impl_GetPixelShaderConstant,
4442 IDirect3DDevice8Impl_GetPixelShaderFunction,
4443 IDirect3DDevice8Impl_DrawRectPatch,
4444 IDirect3DDevice8Impl_DrawTriPatch,
4445 IDirect3DDevice8Impl_DeletePatch
4448 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4450 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4451 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4453 ENTER_GL();
4455 #if 0
4456 if (This->glCtx != This->render_ctx) {
4457 glXDestroyContext(This->display, This->render_ctx);
4458 This->render_ctx = This->glCtx;
4460 #endif
4461 if (This->win != This->drawable) {
4462 glXDestroyPbuffer(This->display, This->drawable);
4463 This->drawable = This->win;
4466 LEAVE_GL();
4468 #endif
4469 return D3D_OK;
4472 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4473 IDirect3DSurface8* RenderSurface,
4474 IDirect3DSurface8* StencilSurface) {
4476 HRESULT ret = D3DERR_INVALIDCALL;
4478 * Currently only active for GLX >= 1.3
4479 * for others versions we'll have to use GLXPixmaps
4481 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4482 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4483 * so only check OpenGL version
4485 #if defined(GL_VERSION_1_3)
4486 GLXFBConfig* cfgs = NULL;
4487 int nCfgs = 0;
4488 int attribs[256];
4489 int nAttribs = 0;
4490 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4491 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4492 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4493 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4494 IDirect3DSurface8Impl* tmp;
4496 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4498 #define PUSH1(att) attribs[nAttribs++] = (att);
4499 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4501 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4502 PUSH2(GLX_X_RENDERABLE, TRUE);
4503 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4505 switch (BackBufferFormat) {
4506 /* color buffer */
4507 case D3DFMT_P8:
4508 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4509 PUSH2(GLX_BUFFER_SIZE, 8);
4510 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4511 break;
4513 case D3DFMT_R3G3B2:
4514 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4515 PUSH2(GLX_RED_SIZE, 3);
4516 PUSH2(GLX_GREEN_SIZE, 3);
4517 PUSH2(GLX_BLUE_SIZE, 2);
4518 break;
4520 case D3DFMT_A1R5G5B5:
4521 PUSH2(GLX_ALPHA_SIZE, 1);
4522 case D3DFMT_X1R5G5B5:
4523 PUSH2(GLX_RED_SIZE, 5);
4524 PUSH2(GLX_GREEN_SIZE, 5);
4525 PUSH2(GLX_BLUE_SIZE, 5);
4526 break;
4528 case D3DFMT_R5G6B5:
4529 PUSH2(GLX_RED_SIZE, 5);
4530 PUSH2(GLX_GREEN_SIZE, 6);
4531 PUSH2(GLX_BLUE_SIZE, 5);
4532 break;
4534 case D3DFMT_A4R4G4B4:
4535 PUSH2(GLX_ALPHA_SIZE, 4);
4536 case D3DFMT_X4R4G4B4:
4537 PUSH2(GLX_RED_SIZE, 4);
4538 PUSH2(GLX_GREEN_SIZE, 4);
4539 PUSH2(GLX_BLUE_SIZE, 4);
4540 break;
4542 case D3DFMT_A8R8G8B8:
4543 PUSH2(GLX_ALPHA_SIZE, 8);
4544 case D3DFMT_R8G8B8:
4545 case D3DFMT_X8R8G8B8:
4546 PUSH2(GLX_RED_SIZE, 8);
4547 PUSH2(GLX_GREEN_SIZE, 8);
4548 PUSH2(GLX_BLUE_SIZE, 8);
4549 break;
4551 default:
4552 break;
4555 switch (StencilBufferFormat) {
4556 case D3DFMT_D16_LOCKABLE:
4557 case D3DFMT_D16:
4558 PUSH2(GLX_DEPTH_SIZE, 16);
4559 break;
4561 case D3DFMT_D15S1:
4562 PUSH2(GLX_DEPTH_SIZE, 15);
4563 break;
4565 case D3DFMT_D24X8:
4566 PUSH2(GLX_DEPTH_SIZE, 24);
4567 break;
4569 case D3DFMT_D24X4S4:
4570 PUSH2(GLX_DEPTH_SIZE, 24);
4571 PUSH2(GLX_STENCIL_SIZE, 4);
4572 break;
4574 case D3DFMT_D24S8:
4575 PUSH2(GLX_DEPTH_SIZE, 24);
4576 PUSH2(GLX_STENCIL_SIZE, 8);
4577 break;
4579 case D3DFMT_D32:
4580 PUSH2(GLX_DEPTH_SIZE, 32);
4581 break;
4583 default:
4584 break;
4587 PUSH1(None);
4589 ENTER_GL();
4591 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4592 if (NULL != cfgs) {
4593 #ifdef EXTRA_TRACES
4594 int i;
4595 for (i = 0; i < nCfgs; ++i) {
4596 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4598 #endif
4600 if (NULL != This->renderTarget) {
4601 /*GLenum prev_read; */
4602 glFlush();
4603 vcheckGLcall("glFlush");
4605 #ifdef EXTRA_TRACES
4606 /** very very usefull debug code */
4607 glXSwapBuffers(This->display, This->drawable);
4608 printf("Hit Enter to get next frame ...\n");
4609 getchar();
4610 #endif
4612 #if 0
4613 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4614 vcheckGLcall("glIntegerv");
4615 glReadBuffer(GL_BACK);
4616 vcheckGLcall("glReadBuffer");
4618 long j;
4619 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4621 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4622 pitch = pitch / 2;
4624 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4625 glReadPixels(0,
4626 This->renderTarget->myDesc.Height - j - 1,
4627 This->renderTarget->myDesc.Width,
4629 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4630 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4631 This->renderTarget->allocatedMemory + j * pitch);
4632 vcheckGLcall("glReadPixels");
4635 glReadBuffer(prev_read);
4636 vcheckGLcall("glReadBuffer");
4637 #endif
4640 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4641 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4642 nAttribs = 0;
4643 PUSH2(GLX_PBUFFER_WIDTH, Width);
4644 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4645 PUSH1(None);
4646 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4648 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4649 if (NULL == This->render_ctx) {
4650 ERR("cannot create glxContext\n");
4653 glFlush();
4654 glXSwapBuffers(This->display, This->drawable);
4655 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4656 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4658 checkGLcall("glXMakeContextCurrent");
4661 tmp = This->renderTarget;
4662 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4663 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4664 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4666 tmp = This->stencilBufferTarget;
4667 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4668 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4669 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4672 DWORD value;
4673 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4674 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4675 /* Force updating the cull mode */
4676 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4677 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4678 /* Force updating projection matrix */
4679 This->last_was_rhw = FALSE;
4680 This->proj_valid = FALSE;
4683 ret = D3D_OK;
4685 } else {
4686 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4689 #undef PUSH1
4690 #undef PUSH2
4692 LEAVE_GL();
4694 #endif
4696 return ret;