Removed some more uses of the non-standard ICOM_THIS macro.
[wine.git] / dlls / d3d8 / device.c
blobda8272616f7a71bd9c72eb96b2abc61b9a654543
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(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 HeapFree(GetProcessHeap(), 0, This);
312 return ref;
315 /* IDirect3DDevice Interface follow: */
316 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
317 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
318 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
319 return D3D_OK;
322 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
323 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
324 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
326 * pretend we have 32MB of any type of memory queried.
328 return (1024*1024*32);
331 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
332 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
333 FIXME("(%p) : stub\n", This);
334 return D3D_OK;
336 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
337 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
338 TRACE("(%p) : returning %p\n", This, This->direct3d8);
340 /* Inc ref count */
341 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
343 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
344 return D3D_OK;
346 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
347 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
348 FIXME("(%p) : stub, calling idirect3d for now\n", This);
349 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
350 return D3D_OK;
352 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
354 HDC hdc;
355 int bpp = 0;
357 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
358 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
359 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
360 pMode->RefreshRate = 85; /*FIXME: How to identify? */
362 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
363 bpp = GetDeviceCaps(hdc, BITSPIXEL);
364 DeleteDC(hdc);
366 switch (bpp) {
367 case 8: pMode->Format = D3DFMT_R8G8B8; break;
368 case 16: pMode->Format = D3DFMT_R5G6B5; break;
369 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
370 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
371 default:
372 FIXME("Unrecognized display mode format\n");
373 pMode->Format = D3DFMT_UNKNOWN;
376 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
377 pMode->Format, debug_d3dformat(pMode->Format));
378 return D3D_OK;
380 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
381 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
382 TRACE("(%p) copying to %p\n", This, pParameters);
383 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
384 return D3D_OK;
386 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
387 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
388 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
389 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
391 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
392 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
393 return D3DERR_INVALIDCALL;
395 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
396 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
397 return D3DERR_INVALIDCALL;
400 This->xHotSpot = XHotSpot;
401 This->yHotSpot = YHotSpot;
402 return D3D_OK;
404 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
405 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
406 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
407 This->xScreenSpace = XScreenSpace;
408 This->yScreenSpace = YScreenSpace;
409 return;
411 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
412 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
413 TRACE("(%p) : visible(%d)\n", This, bShow);
414 This->bCursorVisible = bShow;
415 return D3D_OK;
417 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
418 IDirect3DSwapChain8Impl* object;
419 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
420 FIXME("(%p) : stub\n", This);
422 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
423 if (NULL == object) {
424 return D3DERR_OUTOFVIDEOMEMORY;
426 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
427 object->ref = 1;
429 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
430 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
431 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
433 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
434 (pPresentationParameters->BackBufferHeight == 0))) {
435 RECT Rect;
437 GetClientRect(This->win_handle, &Rect);
439 if (pPresentationParameters->BackBufferWidth == 0) {
440 pPresentationParameters->BackBufferWidth = Rect.right;
441 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
443 if (pPresentationParameters->BackBufferHeight == 0) {
444 pPresentationParameters->BackBufferHeight = Rect.bottom;
445 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
449 /* Save the presentation parms now filled in correctly */
450 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
452 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
453 pPresentationParameters->BackBufferWidth,
454 pPresentationParameters->BackBufferHeight,
455 pPresentationParameters->BackBufferFormat,
456 pPresentationParameters->MultiSampleType,
457 TRUE,
458 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
460 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
461 pPresentationParameters->BackBufferWidth,
462 pPresentationParameters->BackBufferHeight,
463 pPresentationParameters->BackBufferFormat,
464 pPresentationParameters->MultiSampleType,
465 TRUE,
466 (LPDIRECT3DSURFACE8*) &object->backBuffer);
468 if (pPresentationParameters->EnableAutoDepthStencil) {
469 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
470 pPresentationParameters->BackBufferWidth,
471 pPresentationParameters->BackBufferHeight,
472 pPresentationParameters->AutoDepthStencilFormat,
473 D3DMULTISAMPLE_NONE,
474 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
475 } else {
476 object->depthStencilBuffer = NULL;
479 *pSwapChain = (IDirect3DSwapChain8*) object;
480 return D3D_OK;
482 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
483 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
484 FIXME("(%p) : stub\n", This);
485 return D3D_OK;
487 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
488 CONST RECT* pSourceRect, CONST RECT* pDestRect,
489 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
490 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
491 TRACE("(%p) : complete stub!\n", This);
493 ENTER_GL();
495 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
498 glXSwapBuffers(This->display, This->drawable);
499 /* Don't call checkGLcall, as glGetError is not applicable here */
500 TRACE("glXSwapBuffers called, Starting new frame\n");
502 /* FPS support */
503 if (TRACE_ON(d3d_fps))
505 static long prev_time, frames;
507 DWORD time = GetTickCount();
508 frames++;
509 /* every 1.5 seconds */
510 if (time - prev_time > 1500) {
511 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
512 prev_time = time;
513 frames = 0;
517 #if defined(FRAME_DEBUGGING)
519 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
520 if (!isOn) {
521 isOn = TRUE;
522 FIXME("Enabling D3D Trace\n");
523 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
524 #if defined(SHOW_FRAME_MAKEUP)
525 FIXME("Singe Frame snapshots Starting\n");
526 isDumpingFrames = TRUE;
527 glClear(GL_COLOR_BUFFER_BIT);
528 #endif
530 #if defined(SINGLE_FRAME_DEBUGGING)
531 } else {
532 #if defined(SHOW_FRAME_MAKEUP)
533 FIXME("Singe Frame snapshots Finishing\n");
534 isDumpingFrames = FALSE;
535 #endif
536 FIXME("Singe Frame trace complete\n");
537 DeleteFileA("C:\\D3DTRACE");
538 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
539 #endif
541 } else {
542 if (isOn) {
543 isOn = FALSE;
544 #if defined(SHOW_FRAME_MAKEUP)
545 FIXME("Singe Frame snapshots Finishing\n");
546 isDumpingFrames = FALSE;
547 #endif
548 FIXME("Disabling D3D Trace\n");
549 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
553 #endif
555 LEAVE_GL();
556 /* Although this is not strictly required, a simple demo showed this does occur
557 on (at least non-debug) d3d */
558 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
559 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
562 return D3D_OK;
564 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
565 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
566 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
567 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
569 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
570 FIXME("Only one backBuffer currently supported\n");
571 return D3DERR_INVALIDCALL;
574 /* Note inc ref on returned surface */
575 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
577 return D3D_OK;
579 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
580 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
581 FIXME("(%p) : stub\n", This);
582 return D3D_OK;
584 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
585 HDC hDC;
586 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
588 FIXME("(%p) : pRamp@%p\n", This, pRamp);
589 hDC = GetDC(This->win_handle);
590 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
591 ReleaseDC(This->win_handle, hDC);
592 return;
594 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
595 HDC hDC;
596 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
598 FIXME("(%p) : pRamp@%p\n", This, pRamp);
599 hDC = GetDC(This->win_handle);
600 GetDeviceGammaRamp(hDC, pRamp);
601 ReleaseDC(This->win_handle, hDC);
602 return;
604 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
605 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
606 IDirect3DTexture8Impl *object;
607 unsigned int i;
608 UINT tmpW;
609 UINT tmpH;
611 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
613 /* Allocate the storage for the device */
614 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);
615 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
616 object->lpVtbl = &Direct3DTexture8_Vtbl;
617 object->Device = This;
618 object->ResourceType = D3DRTYPE_TEXTURE;
619 object->ref = 1;
620 object->width = Width;
621 object->height = Height;
622 object->levels = Levels;
623 object->usage = Usage;
624 object->format = Format;
626 /* Calculate levels for mip mapping */
627 if (Levels == 0) {
628 object->levels++;
629 tmpW = Width;
630 tmpH = Height;
631 while (tmpW > 1 && tmpH > 1) {
632 tmpW = max(1, tmpW / 2);
633 tmpH = max(1, tmpH / 2);
634 object->levels++;
636 TRACE("Calculated levels = %d\n", object->levels);
639 /* Generate all the surfaces */
640 tmpW = Width;
641 tmpH = Height;
642 for (i = 0; i < object->levels; i++)
644 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
645 object->surfaces[i]->Container = (IUnknown*) object;
646 object->surfaces[i]->myDesc.Usage = Usage;
647 object->surfaces[i]->myDesc.Pool = Pool;
648 /**
649 * As written in msdn in IDirect3DTexture8::LockRect
650 * Textures created in D3DPOOL_DEFAULT are not lockable.
652 if (D3DPOOL_DEFAULT == Pool) {
653 object->surfaces[i]->lockable = FALSE;
656 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
657 tmpW = max(1, tmpW / 2);
658 tmpH = max(1, tmpH / 2);
661 *ppTexture = (LPDIRECT3DTEXTURE8) object;
662 TRACE("(%p) : Created texture %p\n", This, object);
663 return D3D_OK;
665 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
666 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
667 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
669 IDirect3DVolumeTexture8Impl *object;
670 unsigned int i;
671 UINT tmpW;
672 UINT tmpH;
673 UINT tmpD;
675 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
677 /* Allocate the storage for it */
678 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));
679 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
680 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
681 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
682 object->Device = This;
683 object->ref = 1;
685 object->width = Width;
686 object->height = Height;
687 object->depth = Depth;
688 object->levels = Levels;
689 object->usage = Usage;
690 object->format = Format;
692 /* Calculate levels for mip mapping */
693 if (Levels == 0) {
694 object->levels++;
695 tmpW = Width;
696 tmpH = Height;
697 tmpD = Depth;
698 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
699 tmpW = max(1, tmpW / 2);
700 tmpH = max(1, tmpH / 2);
701 tmpD = max(1, tmpD / 2);
702 object->levels++;
704 TRACE("Calculated levels = %d\n", object->levels);
707 /* Generate all the surfaces */
708 tmpW = Width;
709 tmpH = Height;
710 tmpD = Depth;
712 for (i = 0; i < object->levels; i++)
714 IDirect3DVolume8Impl* volume;
716 /* Create the volume - No entry point for this seperately?? */
717 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
718 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
720 volume->lpVtbl = &Direct3DVolume8_Vtbl;
721 volume->Device = This;
722 volume->ResourceType = D3DRTYPE_VOLUME;
723 volume->Container = (IUnknown*) object;
724 volume->ref = 1;
726 volume->myDesc.Width = Width;
727 volume->myDesc.Height = Height;
728 volume->myDesc.Depth = Depth;
729 volume->myDesc.Format = Format;
730 volume->myDesc.Type = D3DRTYPE_VOLUME;
731 volume->myDesc.Pool = Pool;
732 volume->myDesc.Usage = Usage;
733 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
734 /* Note: Volume textures cannot be dxtn, hence no need to check here */
735 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
736 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
738 volume->lockable = TRUE;
739 volume->locked = FALSE;
740 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
741 volume->Dirty = FALSE;
742 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
744 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
745 This, Width, Height, Depth, Format, debug_d3dformat(Format),
746 volume, volume->allocatedMemory, volume->myDesc.Size);
748 tmpW = max(1, tmpW / 2);
749 tmpH = max(1, tmpH / 2);
750 tmpD = max(1, tmpD / 2);
753 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
754 TRACE("(%p) : Created volume texture %p\n", This, object);
755 return D3D_OK;
757 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
758 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
760 IDirect3DCubeTexture8Impl *object;
761 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
762 unsigned int i,j;
763 UINT tmpW;
765 /* Allocate the storage for it */
766 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));
767 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
768 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
769 object->ref = 1;
770 object->Device = This;
771 object->ResourceType = D3DRTYPE_CUBETEXTURE;
773 object->edgeLength = EdgeLength;
774 object->levels = Levels;
775 object->usage = Usage;
776 object->format = Format;
778 /* Calculate levels for mip mapping */
779 if (Levels == 0) {
780 object->levels++;
781 tmpW = EdgeLength;
782 while (tmpW > 1) {
783 tmpW = max(1, tmpW / 2);
784 object->levels++;
786 TRACE("Calculated levels = %d\n", object->levels);
789 /* Generate all the surfaces */
790 tmpW = EdgeLength;
791 for (i = 0; i < object->levels; i++) {
792 /* Create the 6 faces */
793 for (j = 0; j < 6; j++) {
794 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
795 object->surfaces[j][i]->Container = (IUnknown*) object;
796 object->surfaces[j][i]->myDesc.Usage = Usage;
797 object->surfaces[j][i]->myDesc.Pool = Pool;
798 /**
799 * As written in msdn in IDirect3DCubeTexture8::LockRect
800 * Textures created in D3DPOOL_DEFAULT are not lockable.
802 if (D3DPOOL_DEFAULT == Pool) {
803 object->surfaces[j][i]->lockable = FALSE;
806 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
808 tmpW = max(1, tmpW / 2);
811 TRACE("(%p) : Iface@%p\n", This, object);
812 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
813 return D3D_OK;
815 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
816 IDirect3DVertexBuffer8Impl *object;
818 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
820 /* Allocate the storage for the device */
821 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
822 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
823 object->Device = This;
824 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
825 object->ref = 1;
826 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
827 object->currentDesc.Usage = Usage;
828 object->currentDesc.Pool = Pool;
829 object->currentDesc.FVF = FVF;
830 object->currentDesc.Size = Size;
832 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
834 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
836 return D3D_OK;
838 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
839 IDirect3DIndexBuffer8Impl *object;
841 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
842 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
844 /* Allocate the storage for the device */
845 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
846 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
847 object->Device = This;
848 object->ref = 1;
849 object->ResourceType = D3DRTYPE_INDEXBUFFER;
851 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
852 object->currentDesc.Usage = Usage;
853 object->currentDesc.Pool = Pool;
854 object->currentDesc.Format = Format;
855 object->currentDesc.Size = Length;
857 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
859 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
861 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
863 return D3D_OK;
865 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
866 IDirect3DSurface8Impl *object;
867 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
869 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
870 if (NULL == object) {
871 *ppSurface = NULL;
872 return D3DERR_OUTOFVIDEOMEMORY;
874 *ppSurface = (LPDIRECT3DSURFACE8) object;
875 object->lpVtbl = &Direct3DSurface8_Vtbl;
876 object->Device = This;
877 object->ResourceType = D3DRTYPE_SURFACE;
878 object->Container = (IUnknown*) This;
880 object->ref = 1;
881 object->myDesc.Width = Width;
882 object->myDesc.Height = Height;
883 object->myDesc.Format = Format;
884 object->myDesc.Type = D3DRTYPE_SURFACE;
885 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
886 object->myDesc.Pool = D3DPOOL_DEFAULT;
887 object->myDesc.MultiSampleType = MultiSample;
888 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
889 if (Format == D3DFMT_DXT1) {
890 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
891 } else {
892 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
894 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
895 object->lockable = Lockable;
896 object->locked = FALSE;
897 memset(&object->lockedRect, 0, sizeof(RECT));
898 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
900 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);
901 return D3D_OK;
903 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
904 IDirect3DSurface8Impl *object;
906 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
908 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
909 if (NULL == object) {
910 *ppSurface = NULL;
911 return D3DERR_OUTOFVIDEOMEMORY;
913 *ppSurface = (LPDIRECT3DSURFACE8) object;
914 object->lpVtbl = &Direct3DSurface8_Vtbl;
915 object->Device = This;
916 object->ResourceType = D3DRTYPE_SURFACE;
917 object->Container = (IUnknown*) This;
919 object->ref = 1;
920 object->myDesc.Width = Width;
921 object->myDesc.Height = Height;
922 object->myDesc.Format = Format;
923 object->myDesc.Type = D3DRTYPE_SURFACE;
924 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
925 object->myDesc.Pool = D3DPOOL_DEFAULT;
926 object->myDesc.MultiSampleType = MultiSample;
927 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
928 if (Format == D3DFMT_DXT1) {
929 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
930 } else {
931 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
933 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
934 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
935 object->locked = FALSE;
936 memset(&object->lockedRect, 0, sizeof(RECT));
937 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
939 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);
940 return D3D_OK;
942 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
943 IDirect3DSurface8Impl *object;
945 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
947 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
948 *ppSurface = (LPDIRECT3DSURFACE8) object;
949 object->lpVtbl = &Direct3DSurface8_Vtbl;
950 object->Device = This;
951 object->ResourceType = D3DRTYPE_SURFACE;
952 object->Container = (IUnknown*) This;
954 object->ref = 1;
955 object->myDesc.Width = Width;
956 object->myDesc.Height = Height;
957 object->myDesc.Format = Format;
958 object->myDesc.Type = D3DRTYPE_SURFACE;
959 object->myDesc.Usage = 0;
960 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
961 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
962 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
963 it is based around 4x4 pixel blocks it requires padding, so allocate enough
964 space! */
965 if (Format == D3DFMT_DXT1) {
966 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
967 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
968 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
969 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
970 } else {
971 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
973 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
974 object->lockable = TRUE;
975 object->locked = FALSE;
976 memset(&object->lockedRect, 0, sizeof(RECT));
977 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
979 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);
980 return D3D_OK;
982 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
983 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
984 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
986 HRESULT rc = D3D_OK;
987 IDirect3DBaseTexture8* texture = NULL;
990 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
991 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
993 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
994 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
995 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
997 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
998 a sample and doesn't seem to break anything as far as I can tell */
999 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1000 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1001 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1002 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1003 rc = D3DERR_INVALIDCALL;
1005 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1006 TRACE("Converting dest to same format as source, since dest was unknown\n");
1007 dst->myDesc.Format = src->myDesc.Format;
1009 /* Convert container as well */
1010 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1011 if (SUCCEEDED(rc) && NULL != texture) {
1012 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1013 /** Releasing texture after GetContainer */
1014 IDirect3DBaseTexture8_Release(texture);
1015 texture = NULL;
1019 /* Quick if complete copy ... */
1020 if (SUCCEEDED(rc)) {
1021 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1023 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1025 D3DLOCKED_RECT lrSrc;
1026 D3DLOCKED_RECT lrDst;
1027 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1028 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1029 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1031 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1033 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1034 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1035 TRACE("Unlocked src and dst\n");
1037 } else {
1039 FIXME("Wanted to copy all surfaces but size not compatible\n");
1040 rc = D3DERR_INVALIDCALL;
1044 } else {
1046 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1048 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1049 unsigned int i;
1051 /* Copy rect by rect */
1052 for (i = 0; i < cRects; i++) {
1053 CONST RECT* r = &pSourceRectsArray[i];
1054 CONST POINT* p = &pDestPointsArray[i];
1055 int copyperline;
1056 int j;
1057 D3DLOCKED_RECT lrSrc;
1058 D3DLOCKED_RECT lrDst;
1059 RECT dest_rect;
1061 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1062 if (src->myDesc.Format == D3DFMT_DXT1) {
1063 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1064 } else {
1065 copyperline = ((r->right - r->left) * bytesPerPixel);
1067 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1068 dest_rect.left = p->x;
1069 dest_rect.top = p->y;
1070 dest_rect.right = p->x + (r->right - r->left);
1071 dest_rect.bottom= p->y + (r->bottom - r->top);
1072 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1073 TRACE("Locked src and dst\n");
1075 /* Find where to start */
1076 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1077 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1079 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1080 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1081 TRACE("Unlocked src and dst\n");
1083 } else {
1084 FIXME("Wanted to copy partial surfaces not implemented\n");
1085 rc = D3DERR_INVALIDCALL;
1090 return rc;
1092 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1093 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1094 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1095 D3DRESOURCETYPE srcType;
1096 D3DRESOURCETYPE dstType;
1098 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1099 TRACE("(%p) : first try\n", This);
1101 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1102 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1104 if (srcType != dstType) {
1105 return D3DERR_INVALIDCALL;
1107 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1108 return D3DERR_INVALIDCALL;
1110 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1111 return D3DERR_INVALIDCALL;
1113 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1114 /** Only copy Dirty textures */
1115 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1116 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1117 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1118 UINT i, j;
1120 for (i = skipLevels; i < srcLevelCnt; ++i) {
1121 HRESULT hr;
1123 switch (srcType) {
1124 case D3DRTYPE_TEXTURE:
1126 IDirect3DSurface8* srcSur = NULL;
1127 IDirect3DSurface8* dstSur = NULL;
1128 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1129 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1131 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1132 about dst with less levels than the source?) */
1133 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1135 IDirect3DSurface8Impl_Release(srcSur);
1136 IDirect3DSurface8Impl_Release(dstSur);
1138 break;
1139 case D3DRTYPE_VOLUMETEXTURE:
1141 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1143 break;
1144 case D3DRTYPE_CUBETEXTURE:
1146 IDirect3DSurface8* srcSur = NULL;
1147 IDirect3DSurface8* dstSur = NULL;
1148 for (j = 0; j < 5; ++j) {
1149 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1150 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1151 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1152 IDirect3DSurface8Impl_Release(srcSur);
1153 IDirect3DSurface8Impl_Release(dstSur);
1156 break;
1157 default:
1158 break;
1161 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1164 return D3D_OK;
1166 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1167 HRESULT hr;
1168 D3DLOCKED_RECT lockedRect;
1169 RECT wantedRect;
1170 GLint prev_store;
1171 GLenum prev_read;
1173 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1175 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1177 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1178 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1179 return D3DERR_INVALIDCALL;
1182 wantedRect.left = 0;
1183 wantedRect.top = 0;
1184 wantedRect.right = This->PresentParms.BackBufferWidth;
1185 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1187 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1188 if (FAILED(hr)) {
1189 ERR("(%p) : cannot lock surface\n", This);
1190 return D3DERR_INVALIDCALL;
1193 ENTER_GL();
1195 glFlush();
1196 vcheckGLcall("glFlush");
1197 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1198 vcheckGLcall("glIntegerv");
1199 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1200 vcheckGLcall("glIntegerv");
1202 glReadBuffer(GL_FRONT);
1203 vcheckGLcall("glReadBuffer");
1204 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1205 vcheckGLcall("glPixelStorei");
1206 /* stupid copy */
1208 unsigned long j;
1209 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1210 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1211 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1212 vcheckGLcall("glReadPixels");
1215 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1216 vcheckGLcall("glPixelStorei");
1217 glReadBuffer(prev_read);
1218 vcheckGLcall("glReadBuffer");
1220 LEAVE_GL();
1222 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1223 return hr;
1225 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1226 HRESULT hr = D3D_OK;
1227 D3DVIEWPORT8 viewport;
1229 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1231 /* If pRenderTarget == NULL, it seems to default to back buffer */
1232 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1234 /* For ease of code later on, handle a null depth as leave alone
1235 - Have not tested real d3d for this case but doing this avoids
1236 numerous null pointer checks */
1237 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1239 /* If we are trying to set what we already have, don't bother */
1240 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1241 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1242 } else {
1243 /* Otherwise, set the render target up */
1244 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1245 IDirect3DDevice8Impl_CleanRender(iface);
1246 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1249 if (SUCCEEDED(hr)) {
1250 /* Finally, reset the viewport as the MSDN states. */
1251 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1252 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1253 viewport.X = 0;
1254 viewport.Y = 0;
1255 viewport.MaxZ = 1.0f;
1256 viewport.MinZ = 0.0f;
1257 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1260 return hr;
1263 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1264 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1266 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1268 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1269 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1271 return D3D_OK;
1274 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1275 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1277 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1279 /* Note inc ref on returned surface */
1280 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1281 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1283 return D3D_OK;
1286 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1287 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1288 TRACE("(%p) : stub\n", This);
1289 return D3D_OK;
1292 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1293 IDirect3DBaseTexture8* cont = NULL;
1294 HRESULT hr;
1295 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1296 TRACE("(%p)\n", This);
1298 ENTER_GL();
1300 glFlush();
1301 checkGLcall("glFlush");
1303 #if 0 /* Useful for debugging sometimes! */
1304 printf("Hit Enter ...\n");
1305 getchar();
1306 #endif
1308 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1309 #if 0
1310 GLenum prev_read;
1311 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1312 vcheckGLcall("glIntegerv");
1313 glReadBuffer(GL_FRONT);
1314 vcheckGLcall("glReadBuffer");
1316 long j;
1317 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1319 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1320 pitch = pitch / 2;
1322 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1323 glReadPixels(0,
1324 This->renderTarget->myDesc.Height - j - 1,
1325 This->renderTarget->myDesc.Width,
1327 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1328 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1329 This->renderTarget->allocatedMemory + j * pitch);
1330 vcheckGLcall("glReadPixels");
1333 glReadBuffer(prev_read);
1334 vcheckGLcall("glReadBuffer");
1335 #endif
1337 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1338 if (SUCCEEDED(hr) && NULL != cont) {
1339 /** always dirtify for now. we must find a better way to see that surface have been modified */
1340 This->renderTarget->inPBuffer = TRUE;
1341 This->renderTarget->inTexture = FALSE;
1342 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1343 IDirect3DBaseTexture8_PreLoad(cont);
1344 This->renderTarget->inPBuffer = FALSE;
1345 IDirect3DBaseTexture8Impl_Release(cont);
1346 cont = NULL;
1350 LEAVE_GL();
1351 return D3D_OK;
1353 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1354 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1356 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1357 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1358 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1359 GLbitfield glMask = 0;
1360 GLboolean old_ztest;
1361 GLfloat old_z_clear_value;
1362 GLint old_stencil_clear_value;
1363 GLfloat old_color_clear_value[4];
1364 unsigned int i;
1365 CONST D3DRECT* curRect;
1367 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1368 Count, pRects, Flags, Z, Stencil);
1370 ENTER_GL();
1371 glEnable(GL_SCISSOR_TEST);
1372 checkGLcall("glEnable GL_SCISSOR_TEST");
1373 if (Count > 0 && pRects) {
1374 curRect = pRects;
1375 } else {
1376 curRect = NULL;
1379 /* Only set the values up once, as they are not changing */
1380 if (Flags & D3DCLEAR_STENCIL) {
1381 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1382 glClearStencil(Stencil);
1383 checkGLcall("glClearStencil");
1384 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1385 glStencilMask(0xFFFFFFFF);
1388 if (Flags & D3DCLEAR_ZBUFFER) {
1389 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1390 glDepthMask(GL_TRUE);
1391 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1392 glClearDepth(Z);
1393 checkGLcall("glClearDepth");
1394 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1397 if (Flags & D3DCLEAR_TARGET) {
1398 TRACE("Clearing screen with glClear to color %lx\n", Color);
1399 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1400 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1401 ((Color >> 8) & 0xFF) / 255.0f,
1402 ((Color >> 0) & 0xFF) / 255.0f,
1403 ((Color >> 24) & 0xFF) / 255.0f);
1404 checkGLcall("glClearColor");
1406 /* Clear ALL colors! */
1407 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1408 glMask = glMask | GL_COLOR_BUFFER_BIT;
1411 /* Now process each rect in turn */
1412 for (i = 0; i < Count || i == 0; i++) {
1414 if (curRect) {
1415 /* Note gl uses lower left, width/height */
1416 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1417 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1418 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1419 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1420 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1421 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1422 checkGLcall("glScissor");
1423 } else {
1424 glScissor(This->StateBlock->viewport.X,
1425 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1426 This->StateBlock->viewport.Width,
1427 This->StateBlock->viewport.Height);
1428 checkGLcall("glScissor");
1431 /* Clear the selected rectangle (or full screen) */
1432 glClear(glMask);
1433 checkGLcall("glClear");
1435 /* Step to the next rectangle */
1436 if (curRect) curRect = curRect + sizeof(D3DRECT);
1439 /* Restore the old values (why..?) */
1440 if (Flags & D3DCLEAR_STENCIL) {
1441 glClearStencil(old_stencil_clear_value);
1442 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1444 if (Flags & D3DCLEAR_ZBUFFER) {
1445 glDepthMask(old_ztest);
1446 glClearDepth(old_z_clear_value);
1448 if (Flags & D3DCLEAR_TARGET) {
1449 glClearColor(old_color_clear_value[0],
1450 old_color_clear_value[1],
1451 old_color_clear_value[2],
1452 old_color_clear_value[3]);
1453 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1454 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1455 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1456 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1459 glDisable(GL_SCISSOR_TEST);
1460 checkGLcall("glDisable");
1461 LEAVE_GL();
1463 return D3D_OK;
1465 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1466 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1467 unsigned int k;
1469 /* Most of this routine, comments included copied from ddraw tree initially: */
1470 TRACE("(%p) : State=%d\n", This, d3dts);
1472 /* Handle recording of state blocks */
1473 if (This->isRecordingState) {
1474 TRACE("Recording... not performing anything\n");
1475 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1476 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1477 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1478 return D3D_OK;
1482 * if the new matrix is the same as the current one,
1483 * we cut off any further processing. this seems to be a reasonable
1484 * optimization because as was noticed, some apps (warcraft3 for example)
1485 * tend towards setting the same matrix repeatedly for some dumb reason.
1487 * From here on we assume that the new matrix is different, wherever it matters
1488 * but note
1490 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1491 TRACE("The app is setting the same matrix over again\n");
1492 return D3D_OK;
1493 } else {
1494 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1498 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1499 where ViewMat = Camera space, WorldMat = world space.
1501 In OpenGL, camera and world space is combined into GL_MODELVIEW
1502 matrix. The Projection matrix stay projection matrix.
1505 /* Capture the times we can just ignore the change */
1506 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1507 This->modelview_valid = FALSE;
1508 return D3D_OK;
1510 } else if (d3dts == D3DTS_PROJECTION) {
1511 This->proj_valid = FALSE;
1512 return D3D_OK;
1514 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1515 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1516 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1517 return D3D_OK;
1520 /* Chances are we really are going to have to change a matrix */
1521 ENTER_GL();
1523 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1524 if (d3dts < GL_LIMITS(textures)) {
1525 int tex = d3dts - D3DTS_TEXTURE0;
1526 #if defined(GL_VERSION_1_3)
1527 glActiveTexture(GL_TEXTURE0 + tex);
1528 checkGLcall("glActiveTexture");
1529 #else
1530 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1531 checkGLcall("glActiveTextureARB");
1532 #endif
1533 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1536 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1538 PLIGHTINFOEL *lightChain = NULL;
1539 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1540 This->modelview_valid = FALSE;
1541 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1542 glMatrixMode(GL_MODELVIEW);
1543 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1544 glPushMatrix();
1545 glLoadMatrixf((float *)lpmatrix);
1546 checkGLcall("glLoadMatrixf(...)");
1548 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1549 * NOTE: We have to reset the positions even if the light/plane is not currently
1550 * enabled, since the call to enable it will not reset the position.
1551 * NOTE2: Apparently texture transforms do NOT need reapplying
1554 /* Reset lights */
1555 lightChain = This->StateBlock->lights;
1556 while (lightChain && lightChain->glIndex != -1) {
1557 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1558 checkGLcall("glLightfv posn");
1559 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1560 checkGLcall("glLightfv dirn");
1561 lightChain = lightChain->next;
1563 /* Reset Clipping Planes if clipping is enabled */
1564 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1565 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1566 checkGLcall("glClipPlane");
1568 glPopMatrix();
1570 } else { /* What was requested!?? */
1571 WARN("invalid matrix specified: %i\n", d3dts);
1575 /* Release lock, all done */
1576 LEAVE_GL();
1577 return D3D_OK;
1580 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1581 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1582 TRACE("(%p) : for State %d\n", This, State);
1583 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1584 return D3D_OK;
1587 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1588 D3DMATRIX *mat = NULL;
1589 D3DMATRIX temp;
1591 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1592 but works regardless of recording being on.
1593 If this is found to be wrong, change to StateBlock. */
1594 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1595 TRACE("(%p) : For state %u\n", This, State);
1597 if (State < HIGHEST_TRANSFORMSTATE)
1599 mat = &This->UpdateStateBlock->transforms[State];
1600 } else {
1601 FIXME("Unhandled transform state!!\n");
1604 /* Copied from ddraw code: */
1605 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);
1606 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);
1607 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);
1608 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);
1610 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);
1611 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);
1612 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);
1613 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);
1615 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);
1616 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);
1617 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);
1618 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);
1620 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);
1621 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);
1622 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);
1623 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);
1625 /* Apply change via set transform - will reapply to eg. lights this way */
1626 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1627 return D3D_OK;
1629 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1630 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1632 TRACE("(%p)\n", This);
1633 This->UpdateStateBlock->Changed.viewport = TRUE;
1634 This->UpdateStateBlock->Set.viewport = TRUE;
1635 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1637 /* Handle recording of state blocks */
1638 if (This->isRecordingState) {
1639 TRACE("Recording... not performing anything\n");
1640 return D3D_OK;
1643 ENTER_GL();
1645 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1646 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1648 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1649 checkGLcall("glDepthRange");
1650 /* Note: GL requires lower left, DirectX supplies upper left */
1651 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1652 pViewport->Width, pViewport->Height);
1653 checkGLcall("glViewport");
1655 LEAVE_GL();
1657 return D3D_OK;
1660 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1661 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1662 TRACE("(%p)\n", This);
1663 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1664 return D3D_OK;
1667 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1668 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1670 This->UpdateStateBlock->Changed.material = TRUE;
1671 This->UpdateStateBlock->Set.material = TRUE;
1672 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1674 /* Handle recording of state blocks */
1675 if (This->isRecordingState) {
1676 TRACE("Recording... not performing anything\n");
1677 return D3D_OK;
1680 ENTER_GL();
1681 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1682 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1683 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1684 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1685 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1687 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1688 checkGLcall("glMaterialfv");
1689 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1690 checkGLcall("glMaterialfv");
1692 /* Only change material color if specular is enabled, otherwise it is set to black */
1693 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1694 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1695 checkGLcall("glMaterialfv");
1696 } else {
1697 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1698 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1699 checkGLcall("glMaterialfv");
1701 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1702 checkGLcall("glMaterialfv");
1703 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1704 checkGLcall("glMaterialf");
1706 LEAVE_GL();
1707 return D3D_OK;
1709 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1710 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1711 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1712 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1713 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1714 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1715 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1716 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1717 return D3D_OK;
1720 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1721 you can reference any indexes you want as long as that number max are enabled are any
1722 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1723 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1724 but when recording, just build a chain pretty much of commands to be replayed. */
1726 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1727 float rho;
1728 PLIGHTINFOEL *object, *temp;
1730 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1731 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1733 /* If recording state block, just add to end of lights chain */
1734 if (This->isRecordingState) {
1735 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1736 if (NULL == object) {
1737 return D3DERR_OUTOFVIDEOMEMORY;
1739 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1740 object->OriginalIndex = Index;
1741 object->glIndex = -1;
1742 object->changed = TRUE;
1744 /* Add to the END of the chain of lights changes to be replayed */
1745 if (This->UpdateStateBlock->lights == NULL) {
1746 This->UpdateStateBlock->lights = object;
1747 } else {
1748 temp = This->UpdateStateBlock->lights;
1749 while (temp->next != NULL) temp=temp->next;
1750 temp->next = object;
1752 TRACE("Recording... not performing anything more\n");
1753 return D3D_OK;
1756 /* Ok, not recording any longer so do real work */
1757 object = This->StateBlock->lights;
1758 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1760 /* If we didn't find it in the list of lights, time to add it */
1761 if (object == NULL) {
1762 PLIGHTINFOEL *insertAt,*prevPos;
1764 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1765 if (NULL == object) {
1766 return D3DERR_OUTOFVIDEOMEMORY;
1768 object->OriginalIndex = Index;
1769 object->glIndex = -1;
1771 /* Add it to the front of list with the idea that lights will be changed as needed
1772 BUT after any lights currently assigned GL indexes */
1773 insertAt = This->StateBlock->lights;
1774 prevPos = NULL;
1775 while (insertAt != NULL && insertAt->glIndex != -1) {
1776 prevPos = insertAt;
1777 insertAt = insertAt->next;
1780 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1781 This->StateBlock->lights = object;
1782 } else if (insertAt == NULL) { /* End of list */
1783 prevPos->next = object;
1784 object->prev = prevPos;
1785 } else { /* Middle of chain */
1786 if (prevPos == NULL) {
1787 This->StateBlock->lights = object;
1788 } else {
1789 prevPos->next = object;
1791 object->prev = prevPos;
1792 object->next = insertAt;
1793 insertAt->prev = object;
1797 /* Initialze the object */
1798 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,
1799 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1800 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1801 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1802 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1803 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1804 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1806 /* Save away the information */
1807 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1809 switch (pLight->Type) {
1810 case D3DLIGHT_POINT:
1811 /* Position */
1812 object->lightPosn[0] = pLight->Position.x;
1813 object->lightPosn[1] = pLight->Position.y;
1814 object->lightPosn[2] = pLight->Position.z;
1815 object->lightPosn[3] = 1.0f;
1816 object->cutoff = 180.0f;
1817 /* FIXME: Range */
1818 break;
1820 case D3DLIGHT_DIRECTIONAL:
1821 /* Direction */
1822 object->lightPosn[0] = -pLight->Direction.x;
1823 object->lightPosn[1] = -pLight->Direction.y;
1824 object->lightPosn[2] = -pLight->Direction.z;
1825 object->lightPosn[3] = 0.0;
1826 object->exponent = 0.0f;
1827 object->cutoff = 180.0f;
1828 break;
1830 case D3DLIGHT_SPOT:
1831 /* Position */
1832 object->lightPosn[0] = pLight->Position.x;
1833 object->lightPosn[1] = pLight->Position.y;
1834 object->lightPosn[2] = pLight->Position.z;
1835 object->lightPosn[3] = 1.0;
1837 /* Direction */
1838 object->lightDirn[0] = pLight->Direction.x;
1839 object->lightDirn[1] = pLight->Direction.y;
1840 object->lightDirn[2] = pLight->Direction.z;
1841 object->lightDirn[3] = 1.0;
1844 * opengl-ish and d3d-ish spot lights use too different models for the
1845 * light "intensity" as a function of the angle towards the main light direction,
1846 * so we only can approximate very roughly.
1847 * however spot lights are rather rarely used in games (if ever used at all).
1848 * furthermore if still used, probably nobody pays attention to such details.
1850 if (pLight->Falloff == 0) {
1851 rho = 6.28f;
1852 } else {
1853 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1855 if (rho < 0.0001) rho = 0.0001f;
1856 object->exponent = -0.3/log(cos(rho/2));
1857 object->cutoff = pLight->Phi*90/M_PI;
1859 /* FIXME: Range */
1860 break;
1862 default:
1863 FIXME("Unrecognized light type %d\n", pLight->Type);
1866 /* Update the live definitions if the light is currently assigned a glIndex */
1867 if (object->glIndex != -1) {
1868 setup_light(iface, object->glIndex, object);
1870 return D3D_OK;
1872 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1873 PLIGHTINFOEL *lightInfo = NULL;
1874 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1875 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1877 /* Locate the light in the live lights */
1878 lightInfo = This->StateBlock->lights;
1879 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1881 if (lightInfo == NULL) {
1882 TRACE("Light information requested but light not defined\n");
1883 return D3DERR_INVALIDCALL;
1886 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1887 return D3D_OK;
1889 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1890 PLIGHTINFOEL *lightInfo = NULL;
1891 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1892 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1894 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1895 if (This->isRecordingState) {
1896 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1897 if (NULL == lightInfo) {
1898 return D3DERR_OUTOFVIDEOMEMORY;
1900 lightInfo->OriginalIndex = Index;
1901 lightInfo->glIndex = -1;
1902 lightInfo->enabledChanged = TRUE;
1904 /* Add to the END of the chain of lights changes to be replayed */
1905 if (This->UpdateStateBlock->lights == NULL) {
1906 This->UpdateStateBlock->lights = lightInfo;
1907 } else {
1908 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1909 while (temp->next != NULL) temp=temp->next;
1910 temp->next = lightInfo;
1912 TRACE("Recording... not performing anything more\n");
1913 return D3D_OK;
1916 /* Not recording... So, locate the light in the live lights */
1917 lightInfo = This->StateBlock->lights;
1918 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1920 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1921 if (lightInfo == NULL) {
1922 D3DLIGHT8 lightParms;
1923 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1924 wait until someone confirms it seems to work! */
1925 TRACE("Light enabled requested but light not defined, so defining one!\n");
1926 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1927 lightParms.Diffuse.r = 1.0;
1928 lightParms.Diffuse.g = 1.0;
1929 lightParms.Diffuse.b = 1.0;
1930 lightParms.Diffuse.a = 0.0;
1931 lightParms.Specular.r = 0.0;
1932 lightParms.Specular.g = 0.0;
1933 lightParms.Specular.b = 0.0;
1934 lightParms.Specular.a = 0.0;
1935 lightParms.Ambient.r = 0.0;
1936 lightParms.Ambient.g = 0.0;
1937 lightParms.Ambient.b = 0.0;
1938 lightParms.Ambient.a = 0.0;
1939 lightParms.Position.x = 0.0;
1940 lightParms.Position.y = 0.0;
1941 lightParms.Position.z = 0.0;
1942 lightParms.Direction.x = 0.0;
1943 lightParms.Direction.y = 0.0;
1944 lightParms.Direction.z = 1.0;
1945 lightParms.Range = 0.0;
1946 lightParms.Falloff = 0.0;
1947 lightParms.Attenuation0 = 0.0;
1948 lightParms.Attenuation1 = 0.0;
1949 lightParms.Attenuation2 = 0.0;
1950 lightParms.Theta = 0.0;
1951 lightParms.Phi = 0.0;
1952 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1954 /* Search for it again! Should be fairly quick as near head of list */
1955 lightInfo = This->StateBlock->lights;
1956 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1957 if (lightInfo == NULL) {
1958 FIXME("Adding default lights has failed dismally\n");
1959 return D3DERR_INVALIDCALL;
1963 /* OK, we now have a light... */
1964 if (Enable == FALSE) {
1966 /* If we are disabling it, check it was enabled, and
1967 still only do something if it has assigned a glIndex (which it should have!) */
1968 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1969 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1970 ENTER_GL();
1971 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1972 checkGLcall("glDisable GL_LIGHT0+Index");
1973 LEAVE_GL();
1974 } else {
1975 TRACE("Nothing to do as light was not enabled\n");
1977 lightInfo->lightEnabled = FALSE;
1978 } else {
1980 /* We are enabling it. If it is enabled, its really simple */
1981 if (lightInfo->lightEnabled == TRUE) {
1982 /* nop */
1983 TRACE("Nothing to do as light was enabled\n");
1985 /* If it already has a glIndex, its still simple */
1986 } else if (lightInfo->glIndex != -1) {
1987 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1988 lightInfo->lightEnabled = TRUE;
1989 ENTER_GL();
1990 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1991 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1992 LEAVE_GL();
1994 /* Otherwise got to find space - lights are ordered gl indexes first */
1995 } else {
1996 PLIGHTINFOEL *bsf = NULL;
1997 PLIGHTINFOEL *pos = This->StateBlock->lights;
1998 PLIGHTINFOEL *prev = NULL;
1999 int Index= 0;
2000 int glIndex = -1;
2002 /* Try to minimize changes as much as possible */
2003 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2005 /* Try to remember which index can be replaced if necessary */
2006 if (bsf==NULL && pos->lightEnabled == FALSE) {
2007 /* Found a light we can replace, save as best replacement */
2008 bsf = pos;
2011 /* Step to next space */
2012 prev = pos;
2013 pos = pos->next;
2014 Index ++;
2017 /* If we have too many active lights, fail the call */
2018 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2019 FIXME("Program requests too many concurrent lights\n");
2020 return D3DERR_INVALIDCALL;
2022 /* If we have allocated all lights, but not all are enabled,
2023 reuse one which is not enabled */
2024 } else if (Index == This->maxConcurrentLights) {
2025 /* use bsf - Simply swap the new light and the BSF one */
2026 PLIGHTINFOEL *bsfNext = bsf->next;
2027 PLIGHTINFOEL *bsfPrev = bsf->prev;
2029 /* Sort out ends */
2030 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2031 if (bsf->prev != NULL) {
2032 bsf->prev->next = lightInfo;
2033 } else {
2034 This->StateBlock->lights = lightInfo;
2037 /* If not side by side, lots of chains to update */
2038 if (bsf->next != lightInfo) {
2039 lightInfo->prev->next = bsf;
2040 bsf->next->prev = lightInfo;
2041 bsf->next = lightInfo->next;
2042 bsf->prev = lightInfo->prev;
2043 lightInfo->next = bsfNext;
2044 lightInfo->prev = bsfPrev;
2046 } else {
2047 /* Simple swaps */
2048 bsf->prev = lightInfo;
2049 bsf->next = lightInfo->next;
2050 lightInfo->next = bsf;
2051 lightInfo->prev = bsfPrev;
2055 /* Update states */
2056 glIndex = bsf->glIndex;
2057 bsf->glIndex = -1;
2058 lightInfo->glIndex = glIndex;
2059 lightInfo->lightEnabled = TRUE;
2061 /* Finally set up the light in gl itself */
2062 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2063 ENTER_GL();
2064 setup_light(iface, glIndex, lightInfo);
2065 glEnable(GL_LIGHT0 + glIndex);
2066 checkGLcall("glEnable GL_LIGHT0 new setup");
2067 LEAVE_GL();
2069 /* If we reached the end of the allocated lights, with space in the
2070 gl lights, setup a new light */
2071 } else if (pos->glIndex == -1) {
2073 /* We reached the end of the allocated gl lights, so already
2074 know the index of the next one! */
2075 glIndex = Index;
2076 lightInfo->glIndex = glIndex;
2077 lightInfo->lightEnabled = TRUE;
2079 /* In an ideal world, its already in the right place */
2080 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2081 /* No need to move it */
2082 } else {
2083 /* Remove this light from the list */
2084 lightInfo->prev->next = lightInfo->next;
2085 if (lightInfo->next != NULL) {
2086 lightInfo->next->prev = lightInfo->prev;
2089 /* Add in at appropriate place (inbetween prev and pos) */
2090 lightInfo->prev = prev;
2091 lightInfo->next = pos;
2092 if (prev == NULL) {
2093 This->StateBlock->lights = lightInfo;
2094 } else {
2095 prev->next = lightInfo;
2097 if (pos != NULL) {
2098 pos->prev = lightInfo;
2102 /* Finally set up the light in gl itself */
2103 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2104 ENTER_GL();
2105 setup_light(iface, glIndex, lightInfo);
2106 glEnable(GL_LIGHT0 + glIndex);
2107 checkGLcall("glEnable GL_LIGHT0 new setup");
2108 LEAVE_GL();
2113 return D3D_OK;
2115 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2117 PLIGHTINFOEL *lightInfo = NULL;
2118 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2119 TRACE("(%p) : for idx(%ld)\n", This, Index);
2121 /* Locate the light in the live lights */
2122 lightInfo = This->StateBlock->lights;
2123 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2125 if (lightInfo == NULL) {
2126 TRACE("Light enabled state requested but light not defined\n");
2127 return D3DERR_INVALIDCALL;
2129 *pEnable = lightInfo->lightEnabled;
2130 return D3D_OK;
2132 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2133 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2134 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2136 /* Validate Index */
2137 if (Index >= GL_LIMITS(clipplanes)) {
2138 TRACE("Application has requested clipplane this device doesn't support\n");
2139 return D3DERR_INVALIDCALL;
2142 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2143 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2144 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2145 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2146 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2147 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2149 /* Handle recording of state blocks */
2150 if (This->isRecordingState) {
2151 TRACE("Recording... not performing anything\n");
2152 return D3D_OK;
2155 /* Apply it */
2157 ENTER_GL();
2159 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2160 glMatrixMode(GL_MODELVIEW);
2161 glPushMatrix();
2162 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2164 TRACE("Clipplane [%f,%f,%f,%f]\n",
2165 This->UpdateStateBlock->clipplane[Index][0],
2166 This->UpdateStateBlock->clipplane[Index][1],
2167 This->UpdateStateBlock->clipplane[Index][2],
2168 This->UpdateStateBlock->clipplane[Index][3]);
2169 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2170 checkGLcall("glClipPlane");
2172 glPopMatrix();
2174 LEAVE_GL();
2176 return D3D_OK;
2178 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2179 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2180 TRACE("(%p) : for idx %ld\n", This, Index);
2182 /* Validate Index */
2183 if (Index >= GL_LIMITS(clipplanes)) {
2184 TRACE("Application has requested clipplane this device doesn't support\n");
2185 return D3DERR_INVALIDCALL;
2188 pPlane[0] = This->StateBlock->clipplane[Index][0];
2189 pPlane[1] = This->StateBlock->clipplane[Index][1];
2190 pPlane[2] = This->StateBlock->clipplane[Index][2];
2191 pPlane[3] = This->StateBlock->clipplane[Index][3];
2192 return D3D_OK;
2194 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2195 union {
2196 DWORD d;
2197 float f;
2198 } tmpvalue;
2199 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2200 DWORD OldValue = This->StateBlock->renderstate[State];
2202 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2203 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2204 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2205 This->UpdateStateBlock->renderstate[State] = Value;
2207 /* Handle recording of state blocks */
2208 if (This->isRecordingState) {
2209 TRACE("Recording... not performing anything\n");
2210 return D3D_OK;
2213 ENTER_GL();
2215 switch (State) {
2216 case D3DRS_FILLMODE :
2217 switch ((D3DFILLMODE) Value) {
2218 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2219 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2220 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2221 default:
2222 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2224 checkGLcall("glPolygonMode (fillmode)");
2225 break;
2227 case D3DRS_LIGHTING :
2228 if (Value) {
2229 glEnable(GL_LIGHTING);
2230 checkGLcall("glEnable GL_LIGHTING");
2231 } else {
2232 glDisable(GL_LIGHTING);
2233 checkGLcall("glDisable GL_LIGHTING");
2235 break;
2237 case D3DRS_ZENABLE :
2238 switch ((D3DZBUFFERTYPE) Value) {
2239 case D3DZB_FALSE:
2240 glDisable(GL_DEPTH_TEST);
2241 checkGLcall("glDisable GL_DEPTH_TEST");
2242 break;
2243 case D3DZB_TRUE:
2244 glEnable(GL_DEPTH_TEST);
2245 checkGLcall("glEnable GL_DEPTH_TEST");
2246 break;
2247 case D3DZB_USEW:
2248 glEnable(GL_DEPTH_TEST);
2249 checkGLcall("glEnable GL_DEPTH_TEST");
2250 FIXME("W buffer is not well handled\n");
2251 break;
2252 default:
2253 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2255 break;
2257 case D3DRS_CULLMODE :
2259 /* If we are culling "back faces with clockwise vertices" then
2260 set front faces to be counter clockwise and enable culling
2261 of back faces */
2262 switch ((D3DCULL) Value) {
2263 case D3DCULL_NONE:
2264 glDisable(GL_CULL_FACE);
2265 checkGLcall("glDisable GL_CULL_FACE");
2266 break;
2267 case D3DCULL_CW:
2268 glEnable(GL_CULL_FACE);
2269 checkGLcall("glEnable GL_CULL_FACE");
2270 if (This->renderUpsideDown) {
2271 glFrontFace(GL_CW);
2272 checkGLcall("glFrontFace GL_CW");
2273 } else {
2274 glFrontFace(GL_CCW);
2275 checkGLcall("glFrontFace GL_CCW");
2277 glCullFace(GL_BACK);
2278 break;
2279 case D3DCULL_CCW:
2280 glEnable(GL_CULL_FACE);
2281 checkGLcall("glEnable GL_CULL_FACE");
2282 if (This->renderUpsideDown) {
2283 glFrontFace(GL_CCW);
2284 checkGLcall("glFrontFace GL_CCW");
2285 } else {
2286 glFrontFace(GL_CW);
2287 checkGLcall("glFrontFace GL_CW");
2289 glCullFace(GL_BACK);
2290 break;
2291 default:
2292 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2294 break;
2296 case D3DRS_SHADEMODE :
2297 switch ((D3DSHADEMODE) Value) {
2298 case D3DSHADE_FLAT:
2299 glShadeModel(GL_FLAT);
2300 checkGLcall("glShadeModel");
2301 break;
2302 case D3DSHADE_GOURAUD:
2303 glShadeModel(GL_SMOOTH);
2304 checkGLcall("glShadeModel");
2305 break;
2306 case D3DSHADE_PHONG:
2307 FIXME("D3DSHADE_PHONG isn't supported?\n");
2309 LEAVE_GL();
2310 return D3DERR_INVALIDCALL;
2311 default:
2312 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2314 break;
2316 case D3DRS_DITHERENABLE :
2317 if (Value) {
2318 glEnable(GL_DITHER);
2319 checkGLcall("glEnable GL_DITHER");
2320 } else {
2321 glDisable(GL_DITHER);
2322 checkGLcall("glDisable GL_DITHER");
2324 break;
2326 case D3DRS_ZWRITEENABLE :
2327 if (Value) {
2328 glDepthMask(1);
2329 checkGLcall("glDepthMask");
2330 } else {
2331 glDepthMask(0);
2332 checkGLcall("glDepthMask");
2334 break;
2336 case D3DRS_ZFUNC :
2338 int glParm = GL_LESS;
2340 switch ((D3DCMPFUNC) Value) {
2341 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2342 case D3DCMP_LESS: glParm=GL_LESS; break;
2343 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2344 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2345 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2346 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2347 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2348 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2349 default:
2350 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2352 glDepthFunc(glParm);
2353 checkGLcall("glDepthFunc");
2355 break;
2357 case D3DRS_AMBIENT :
2359 float col[4];
2360 D3DCOLORTOGLFLOAT4(Value, col);
2361 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2362 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2363 checkGLcall("glLightModel for MODEL_AMBIENT");
2366 break;
2368 case D3DRS_ALPHABLENDENABLE :
2369 if (Value) {
2370 glEnable(GL_BLEND);
2371 checkGLcall("glEnable GL_BLEND");
2372 } else {
2373 glDisable(GL_BLEND);
2374 checkGLcall("glDisable GL_BLEND");
2376 break;
2378 case D3DRS_SRCBLEND :
2379 case D3DRS_DESTBLEND :
2381 int newVal = GL_ZERO;
2382 switch (Value) {
2383 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2384 case D3DBLEND_ONE : newVal = GL_ONE; break;
2385 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2386 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2387 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2388 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2389 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2390 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2391 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2392 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2393 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2395 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2396 This->srcBlend = newVal;
2397 This->dstBlend = newVal;
2398 break;
2400 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2401 This->srcBlend = newVal;
2402 This->dstBlend = newVal;
2403 break;
2404 default:
2405 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2408 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2409 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2410 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2411 glBlendFunc(This->srcBlend, This->dstBlend);
2413 checkGLcall("glBlendFunc");
2415 break;
2417 case D3DRS_ALPHATESTENABLE :
2418 if (Value) {
2419 glEnable(GL_ALPHA_TEST);
2420 checkGLcall("glEnable GL_ALPHA_TEST");
2421 } else {
2422 glDisable(GL_ALPHA_TEST);
2423 checkGLcall("glDisable GL_ALPHA_TEST");
2425 break;
2427 case D3DRS_ALPHAFUNC :
2429 int glParm = GL_LESS;
2430 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2432 switch ((D3DCMPFUNC) Value) {
2433 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2434 case D3DCMP_LESS: glParm = GL_LESS; break;
2435 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2436 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2437 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2438 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2439 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2440 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2441 default:
2442 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2444 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2445 glAlphaFunc(glParm, ref);
2446 This->alphafunc = glParm;
2447 checkGLcall("glAlphaFunc");
2449 break;
2451 case D3DRS_ALPHAREF :
2453 int glParm = This->alphafunc;
2454 float ref = 1.0f;
2456 ref = ((float) Value) / 255.0f;
2457 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2458 glAlphaFunc(glParm, ref);
2459 checkGLcall("glAlphaFunc");
2461 break;
2463 case D3DRS_CLIPPLANEENABLE :
2464 case D3DRS_CLIPPING :
2466 /* Ensure we only do the changed clip planes */
2467 DWORD enable = 0xFFFFFFFF;
2468 DWORD disable = 0x00000000;
2470 /* If enabling / disabling all */
2471 if (State == D3DRS_CLIPPING) {
2472 if (Value) {
2473 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2474 disable = 0x00;
2475 } else {
2476 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2477 enable = 0x00;
2479 } else {
2480 enable = Value & ~OldValue;
2481 disable = ~Value & OldValue;
2484 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2485 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2486 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2487 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2488 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2489 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2491 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2492 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2493 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2494 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2495 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2496 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2498 /** update clipping status */
2499 if (enable) {
2500 This->StateBlock->clip_status.ClipUnion = 0;
2501 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2502 } else {
2503 This->StateBlock->clip_status.ClipUnion = 0;
2504 This->StateBlock->clip_status.ClipIntersection = 0;
2507 break;
2509 case D3DRS_BLENDOP :
2511 int glParm = GL_FUNC_ADD;
2513 switch ((D3DBLENDOP) Value) {
2514 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2515 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2516 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2517 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2518 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2519 default:
2520 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2522 TRACE("glBlendEquation(%x)\n", glParm);
2523 glBlendEquation(glParm);
2524 checkGLcall("glBlendEquation");
2526 break;
2528 case D3DRS_TEXTUREFACTOR :
2530 unsigned int i;
2532 /* Note the texture color applies to all textures whereas
2533 GL_TEXTURE_ENV_COLOR applies to active only */
2534 float col[4];
2535 D3DCOLORTOGLFLOAT4(Value, col);
2536 /* Set the default alpha blend color */
2537 glBlendColor(col[0], col[1], col[2], col[3]);
2538 checkGLcall("glBlendColor");
2540 /* And now the default texture color as well */
2541 for (i = 0; i < GL_LIMITS(textures); i++) {
2543 /* Note the D3DRS value applies to all textures, but GL has one
2544 per texture, so apply it now ready to be used! */
2545 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2546 #if defined(GL_VERSION_1_3)
2547 glActiveTexture(GL_TEXTURE0 + i);
2548 #else
2549 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2550 #endif
2551 checkGLcall("Activate texture.. to update const color");
2552 } else if (i>0) {
2553 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2556 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2557 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2560 break;
2562 case D3DRS_SPECULARENABLE :
2564 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2565 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2566 specular color. This is wrong:
2567 Separate specular color means the specular colour is maintained separately, whereas
2568 single color means it is merged in. However in both cases they are being used to
2569 some extent.
2570 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2571 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2572 running 1.4 yet!
2574 if (Value) {
2575 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2576 checkGLcall("glMaterialfv");
2577 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2578 glEnable(GL_COLOR_SUM_EXT);
2579 } else {
2580 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2582 checkGLcall("glEnable(GL_COLOR_SUM)");
2583 } else {
2584 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2586 /* for the case of enabled lighting: */
2587 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2588 checkGLcall("glMaterialfv");
2590 /* for the case of disabled lighting: */
2591 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2592 glDisable(GL_COLOR_SUM_EXT);
2593 } else {
2594 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2596 checkGLcall("glDisable(GL_COLOR_SUM)");
2599 break;
2601 case D3DRS_STENCILENABLE :
2602 if (Value) {
2603 glEnable(GL_STENCIL_TEST);
2604 checkGLcall("glEnable GL_STENCIL_TEST");
2605 } else {
2606 glDisable(GL_STENCIL_TEST);
2607 checkGLcall("glDisable GL_STENCIL_TEST");
2609 break;
2611 case D3DRS_STENCILFUNC :
2613 int glParm = GL_ALWAYS;
2614 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2615 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2617 switch ((D3DCMPFUNC) Value) {
2618 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2619 case D3DCMP_LESS: glParm=GL_LESS; break;
2620 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2621 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2622 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2623 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2624 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2625 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2626 default:
2627 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2629 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2630 This->stencilfunc = glParm;
2631 glStencilFunc(glParm, ref, mask);
2632 checkGLcall("glStencilFunc");
2634 break;
2636 case D3DRS_STENCILREF :
2638 int glParm = This->stencilfunc;
2639 int ref = 0;
2640 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2642 ref = Value;
2643 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2644 glStencilFunc(glParm, ref, mask);
2645 checkGLcall("glStencilFunc");
2647 break;
2649 case D3DRS_STENCILMASK :
2651 int glParm = This->stencilfunc;
2652 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2653 GLuint mask = Value;
2655 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2656 glStencilFunc(glParm, ref, mask);
2657 checkGLcall("glStencilFunc");
2659 break;
2661 case D3DRS_STENCILFAIL :
2663 GLenum fail ;
2664 GLenum zpass ;
2665 GLenum zfail ;
2667 fail = StencilOp(Value);
2668 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2669 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2670 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2671 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2673 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2674 glStencilOp(fail, zfail, zpass);
2675 checkGLcall("glStencilOp(fail, zfail, zpass);");
2677 break;
2678 case D3DRS_STENCILZFAIL :
2680 GLenum fail ;
2681 GLenum zpass ;
2682 GLenum zfail ;
2684 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2685 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2686 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2687 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2688 zfail = StencilOp(Value);
2690 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2691 glStencilOp(fail, zfail, zpass);
2692 checkGLcall("glStencilOp(fail, zfail, zpass);");
2694 break;
2695 case D3DRS_STENCILPASS :
2697 GLenum fail ;
2698 GLenum zpass ;
2699 GLenum zfail ;
2701 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2702 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2703 zpass = StencilOp(Value);
2704 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2705 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2707 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2708 glStencilOp(fail, zfail, zpass);
2709 checkGLcall("glStencilOp(fail, zfail, zpass);");
2711 break;
2713 case D3DRS_STENCILWRITEMASK :
2715 glStencilMask(Value);
2716 TRACE("glStencilMask(%lu)\n", Value);
2717 checkGLcall("glStencilMask");
2719 break;
2721 case D3DRS_FOGENABLE :
2723 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2724 glEnable(GL_FOG);
2725 checkGLcall("glEnable GL_FOG");
2726 } else {
2727 glDisable(GL_FOG);
2728 checkGLcall("glDisable GL_FOG");
2731 break;
2733 case D3DRS_RANGEFOGENABLE :
2735 if (Value) {
2736 TRACE("Enabled RANGEFOG");
2737 } else {
2738 TRACE("Disabled RANGEFOG");
2741 break;
2743 case D3DRS_FOGCOLOR :
2745 float col[4];
2746 D3DCOLORTOGLFLOAT4(Value, col);
2747 /* Set the default alpha blend color */
2748 glFogfv(GL_FOG_COLOR, &col[0]);
2749 checkGLcall("glFog GL_FOG_COLOR");
2751 break;
2753 case D3DRS_FOGTABLEMODE :
2755 glHint(GL_FOG_HINT, GL_NICEST);
2756 switch (Value) {
2757 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2758 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2759 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2760 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2761 default:
2762 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2764 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2765 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2768 break;
2770 case D3DRS_FOGVERTEXMODE :
2772 glHint(GL_FOG_HINT, GL_FASTEST);
2773 switch (Value) {
2774 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2775 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2776 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2777 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2778 default:
2779 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2781 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2782 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2785 break;
2787 case D3DRS_FOGSTART :
2789 tmpvalue.d = Value;
2790 glFogfv(GL_FOG_START, &tmpvalue.f);
2791 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2792 TRACE("Fog Start == %f\n", tmpvalue.f);
2794 break;
2796 case D3DRS_FOGEND :
2798 tmpvalue.d = Value;
2799 glFogfv(GL_FOG_END, &tmpvalue.f);
2800 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2801 TRACE("Fog End == %f\n", tmpvalue.f);
2803 break;
2805 case D3DRS_FOGDENSITY :
2807 tmpvalue.d = Value;
2808 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2809 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2811 break;
2813 case D3DRS_VERTEXBLEND :
2815 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2816 TRACE("Vertex Blending state to %ld\n", Value);
2818 break;
2820 case D3DRS_TWEENFACTOR :
2822 tmpvalue.d = Value;
2823 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2824 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2826 break;
2828 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2830 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2832 break;
2834 case D3DRS_COLORVERTEX :
2835 case D3DRS_DIFFUSEMATERIALSOURCE :
2836 case D3DRS_SPECULARMATERIALSOURCE :
2837 case D3DRS_AMBIENTMATERIALSOURCE :
2838 case D3DRS_EMISSIVEMATERIALSOURCE :
2840 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2842 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2843 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2844 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2845 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2846 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2847 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2849 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2850 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2851 Parm = GL_AMBIENT_AND_DIFFUSE;
2852 } else {
2853 Parm = GL_DIFFUSE;
2855 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2856 Parm = GL_AMBIENT;
2857 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2858 Parm = GL_EMISSION;
2859 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2860 Parm = GL_SPECULAR;
2861 } else {
2862 Parm = -1;
2865 if (Parm == -1) {
2866 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2867 } else {
2868 This->tracking_color = NEEDS_TRACKING;
2869 This->tracking_parm = Parm;
2872 } else {
2873 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2876 break;
2878 case D3DRS_LINEPATTERN :
2880 union {
2881 DWORD d;
2882 D3DLINEPATTERN lp;
2883 } tmppattern;
2884 tmppattern.d = Value;
2886 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2888 if (tmppattern.lp.wRepeatFactor) {
2889 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2890 checkGLcall("glLineStipple(repeat, linepattern)");
2891 glEnable(GL_LINE_STIPPLE);
2892 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2893 } else {
2894 glDisable(GL_LINE_STIPPLE);
2895 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2898 break;
2900 case D3DRS_ZBIAS :
2902 if (Value) {
2903 tmpvalue.d = Value;
2904 TRACE("ZBias value %f\n", tmpvalue.f);
2905 glPolygonOffset(0, -tmpvalue.f);
2906 checkGLcall("glPolygonOffset(0, -Value)");
2907 glEnable(GL_POLYGON_OFFSET_FILL);
2908 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2909 glEnable(GL_POLYGON_OFFSET_LINE);
2910 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2911 glEnable(GL_POLYGON_OFFSET_POINT);
2912 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2913 } else {
2914 glDisable(GL_POLYGON_OFFSET_FILL);
2915 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2916 glDisable(GL_POLYGON_OFFSET_LINE);
2917 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2918 glDisable(GL_POLYGON_OFFSET_POINT);
2919 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2922 break;
2924 case D3DRS_NORMALIZENORMALS :
2925 if (Value) {
2926 glEnable(GL_NORMALIZE);
2927 checkGLcall("glEnable(GL_NORMALIZE);");
2928 } else {
2929 glDisable(GL_NORMALIZE);
2930 checkGLcall("glDisable(GL_NORMALIZE);");
2932 break;
2934 case D3DRS_POINTSIZE :
2935 tmpvalue.d = Value;
2936 TRACE("Set point size to %f\n", tmpvalue.f);
2937 glPointSize(tmpvalue.f);
2938 checkGLcall("glPointSize(...);");
2939 break;
2941 case D3DRS_POINTSIZE_MIN :
2942 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2943 tmpvalue.d = Value;
2944 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2945 checkGLcall("glPointParameterfEXT(...);");
2946 } else {
2947 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2949 break;
2951 case D3DRS_POINTSIZE_MAX :
2952 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2953 tmpvalue.d = Value;
2954 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2955 checkGLcall("glPointParameterfEXT(...);");
2956 } else {
2957 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2959 break;
2961 case D3DRS_POINTSCALE_A :
2962 case D3DRS_POINTSCALE_B :
2963 case D3DRS_POINTSCALE_C :
2964 case D3DRS_POINTSCALEENABLE :
2966 /* If enabled, supply the parameters, otherwise fall back to defaults */
2967 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2968 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2969 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2970 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2971 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2973 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2974 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2975 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2976 } else {
2977 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2979 } else {
2980 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2981 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2982 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2983 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2984 } else {
2985 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2988 break;
2991 case D3DRS_COLORWRITEENABLE :
2993 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2994 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2995 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2996 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2997 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2998 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2999 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3000 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3001 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3002 checkGLcall("glColorMask(...)");
3004 break;
3006 case D3DRS_LOCALVIEWER :
3008 GLint state = (Value) ? 1 : 0;
3009 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3010 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3012 break;
3014 case D3DRS_LASTPIXEL :
3016 if (Value) {
3017 TRACE("Last Pixel Drawing Enabled\n");
3018 } else {
3019 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3022 break;
3024 case D3DRS_SOFTWAREVERTEXPROCESSING :
3026 if (Value) {
3027 TRACE("Software Processing Enabled\n");
3028 } else {
3029 TRACE("Software Processing Disabled\n");
3032 break;
3034 /** not supported */
3035 case D3DRS_ZVISIBLE :
3037 LEAVE_GL();
3038 return D3DERR_INVALIDCALL;
3041 /* Unhandled yet...! */
3042 case D3DRS_EDGEANTIALIAS :
3043 case D3DRS_WRAP0 :
3044 case D3DRS_WRAP1 :
3045 case D3DRS_WRAP2 :
3046 case D3DRS_WRAP3 :
3047 case D3DRS_WRAP4 :
3048 case D3DRS_WRAP5 :
3049 case D3DRS_WRAP6 :
3050 case D3DRS_WRAP7 :
3051 case D3DRS_POINTSPRITEENABLE :
3052 case D3DRS_MULTISAMPLEANTIALIAS :
3053 case D3DRS_MULTISAMPLEMASK :
3054 case D3DRS_PATCHEDGESTYLE :
3055 case D3DRS_PATCHSEGMENTS :
3056 case D3DRS_DEBUGMONITORTOKEN :
3057 case D3DRS_POSITIONORDER :
3058 case D3DRS_NORMALORDER :
3059 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3060 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3061 break;
3062 default:
3063 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3066 LEAVE_GL();
3068 return D3D_OK;
3070 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3071 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3072 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3073 *pValue = This->StateBlock->renderstate[State];
3074 return D3D_OK;
3076 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3077 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3079 TRACE("(%p)\n", This);
3081 return IDirect3DDeviceImpl_BeginStateBlock(This);
3083 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3084 IDirect3DStateBlockImpl* pSB;
3085 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3086 HRESULT res;
3088 TRACE("(%p)\n", This);
3090 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3091 *pToken = (DWORD) pSB;
3092 return res;
3095 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3096 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3097 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3099 TRACE("(%p)\n", This);
3101 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3104 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3105 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3106 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3108 TRACE("(%p)\n", This);
3110 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3112 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3113 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3114 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3116 TRACE("(%p)\n", This);
3118 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3121 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3122 IDirect3DStateBlockImpl* pSB;
3123 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3124 HRESULT res;
3126 TRACE("(%p) : for type %d\n", This, Type);
3128 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3129 *pToken = (DWORD) pSB;
3130 return res;
3133 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3134 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3135 FIXME("(%p) : stub\n", This);
3136 if (NULL == pClipStatus) {
3137 return D3DERR_INVALIDCALL;
3139 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3140 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3141 return D3D_OK;
3143 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3144 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3145 FIXME("(%p) : stub\n", This);
3146 if (NULL == pClipStatus) {
3147 return D3DERR_INVALIDCALL;
3149 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3150 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3151 return D3D_OK;
3153 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3154 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3155 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3156 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3157 if (*ppTexture)
3158 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3159 return D3D_OK;
3161 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3163 IDirect3DBaseTexture8 *oldTxt;
3164 BOOL reapplyStates = TRUE;
3165 INT oldTextureDimensions = -1;
3166 DWORD reapplyFlags = 0;
3168 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3169 D3DRESOURCETYPE textureType;
3171 oldTxt = This->UpdateStateBlock->textures[Stage];
3172 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3174 /* Reject invalid texture units */
3175 if (Stage >= GL_LIMITS(textures)) {
3176 TRACE("Attempt to access invalid texture rejected\n");
3177 return D3DERR_INVALIDCALL;
3180 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3181 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3182 This->UpdateStateBlock->textures[Stage] = pTexture;
3184 /* Handle recording of state blocks */
3185 if (This->isRecordingState) {
3186 TRACE("Recording... not performing anything\n");
3187 return D3D_OK;
3190 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3191 ENTER_GL();
3193 /* Make appropriate texture active */
3194 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3195 #if defined(GL_VERSION_1_3)
3196 glActiveTexture(GL_TEXTURE0 + Stage);
3197 checkGLcall("glActiveTexture");
3198 #else
3199 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3200 checkGLcall("glActiveTextureARB");
3201 #endif
3202 } else if (Stage>0) {
3203 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3206 /* Decrement the count of the previous texture */
3207 if (NULL != oldTxt) {
3208 IDirect3DBaseTexture8Impl_Release(oldTxt);
3211 if (NULL != pTexture) {
3212 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3214 /* Now setup the texture appropraitly */
3215 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3217 if (textureType == D3DRTYPE_TEXTURE) {
3218 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3219 TRACE("Skipping setting texture as old == new\n");
3220 reapplyStates = FALSE;
3221 } else {
3222 /* Standard 2D texture */
3223 TRACE("Standard 2d texture\n");
3224 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3226 /* Load up the texture now */
3227 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3229 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3230 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3231 TRACE("Skipping setting texture as old == new\n");
3232 reapplyStates = FALSE;
3233 } else {
3234 /* Standard 3D (volume) texture */
3235 TRACE("Standard 3d texture\n");
3236 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3238 /* Load up the texture now */
3239 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3241 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3242 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3243 TRACE("Skipping setting texture as old == new\n");
3244 reapplyStates = FALSE;
3245 } else {
3246 /* Standard Cube texture */
3247 TRACE("Standard Cube texture\n");
3248 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3250 /* Load up the texture now */
3251 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3253 } else {
3254 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3256 } else {
3257 TRACE("Setting to no texture (ie default texture)\n");
3258 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3259 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3260 checkGLcall("glBindTexture");
3261 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3264 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3265 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3266 glDisable(oldTextureDimensions);
3267 checkGLcall("Disable oldTextureDimensions");
3268 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3269 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3270 checkGLcall("glEnable new texture dimensions");
3273 /* If Alpha arg1 is texture then handle the special case when there changes between a
3274 texture and no texture - See comments in set_tex_op */
3275 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3276 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3278 reapplyFlags |= REAPPLY_ALPHAOP;
3283 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3284 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3285 if (reapplyStates) {
3286 setupTextureStates(iface, Stage, reapplyFlags);
3289 LEAVE_GL();
3291 return D3D_OK;
3294 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3295 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3296 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3297 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3298 return D3D_OK;
3301 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3302 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3303 union {
3304 float f;
3305 DWORD d;
3306 } tmpvalue;
3308 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3310 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3312 /* Reject invalid texture units */
3313 if (Stage >= GL_LIMITS(textures)) {
3314 TRACE("Attempt to access invalid texture rejected\n");
3315 return D3DERR_INVALIDCALL;
3318 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3319 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3320 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3322 /* Handle recording of state blocks */
3323 if (This->isRecordingState) {
3324 TRACE("Recording... not performing anything\n");
3325 return D3D_OK;
3328 ENTER_GL();
3330 /* Make appropriate texture active */
3331 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3332 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3333 #if defined(GL_VERSION_1_3)
3334 glActiveTexture(GL_TEXTURE0 + Stage);
3335 vcheckGLcall("glActiveTexture");
3336 #else
3337 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3338 vcheckGLcall("glActiveTextureARB");
3339 #endif
3340 } else if (Stage > 0) {
3341 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3344 switch (Type) {
3346 case D3DTSS_MINFILTER :
3347 case D3DTSS_MIPFILTER :
3349 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3350 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3351 GLint realVal = GL_LINEAR;
3353 if (ValueMIN == D3DTEXF_NONE) {
3354 /* Doesn't really make sense - Windows just seems to disable
3355 mipmapping when this occurs */
3356 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3357 realVal = GL_LINEAR;
3358 } else if (ValueMIN == D3DTEXF_POINT) {
3359 /* GL_NEAREST_* */
3360 if (ValueMIP == D3DTEXF_NONE) {
3361 realVal = GL_NEAREST;
3362 } else if (ValueMIP == D3DTEXF_POINT) {
3363 realVal = GL_NEAREST_MIPMAP_NEAREST;
3364 } else if (ValueMIP == D3DTEXF_LINEAR) {
3365 realVal = GL_NEAREST_MIPMAP_LINEAR;
3366 } else {
3367 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3368 realVal = GL_NEAREST;
3370 } else if (ValueMIN == D3DTEXF_LINEAR) {
3371 /* GL_LINEAR_* */
3372 if (ValueMIP == D3DTEXF_NONE) {
3373 realVal = GL_LINEAR;
3374 } else if (ValueMIP == D3DTEXF_POINT) {
3375 realVal = GL_LINEAR_MIPMAP_NEAREST;
3376 } else if (ValueMIP == D3DTEXF_LINEAR) {
3377 realVal = GL_LINEAR_MIPMAP_LINEAR;
3378 } else {
3379 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3380 realVal = GL_LINEAR;
3382 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3383 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3384 if (ValueMIP == D3DTEXF_NONE) {
3385 realVal = GL_LINEAR_MIPMAP_LINEAR;
3386 } else if (ValueMIP == D3DTEXF_POINT) {
3387 realVal = GL_LINEAR_MIPMAP_NEAREST;
3388 } else if (ValueMIP == D3DTEXF_LINEAR) {
3389 realVal = GL_LINEAR_MIPMAP_LINEAR;
3390 } else {
3391 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3392 realVal = GL_LINEAR;
3394 } else {
3395 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3396 realVal = GL_LINEAR;
3398 } else {
3399 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3400 realVal = GL_LINEAR_MIPMAP_LINEAR;
3403 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3404 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3405 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3407 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3409 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3410 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3411 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3412 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3413 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3416 break;
3418 case D3DTSS_MAGFILTER :
3420 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3421 GLint realVal = GL_NEAREST;
3423 if (ValueMAG == D3DTEXF_POINT) {
3424 realVal = GL_NEAREST;
3425 } else if (ValueMAG == D3DTEXF_LINEAR) {
3426 realVal = GL_LINEAR;
3427 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3428 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3429 realVal = GL_LINEAR;
3430 } else {
3431 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3432 realVal = GL_NEAREST;
3434 } else {
3435 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3436 realVal = GL_NEAREST;
3438 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3439 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3440 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3442 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3444 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3445 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3446 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3447 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3448 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3451 break;
3453 case D3DTSS_MAXMIPLEVEL :
3456 * Not really the same, but the more apprioprate than nothing
3458 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3459 GL_TEXTURE_BASE_LEVEL,
3460 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3461 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3463 break;
3465 case D3DTSS_MAXANISOTROPY :
3467 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3468 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3469 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3470 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3471 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3474 break;
3476 case D3DTSS_MIPMAPLODBIAS :
3478 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3479 tmpvalue.d = Value;
3480 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3481 GL_TEXTURE_LOD_BIAS_EXT,
3482 tmpvalue.f);
3483 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3486 break;
3488 case D3DTSS_ALPHAOP :
3489 case D3DTSS_COLOROP :
3492 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3493 /* TODO: Disable by making this and all later levels disabled */
3494 glDisable(GL_TEXTURE_1D);
3495 checkGLcall("Disable GL_TEXTURE_1D");
3496 glDisable(GL_TEXTURE_2D);
3497 checkGLcall("Disable GL_TEXTURE_2D");
3498 glDisable(GL_TEXTURE_3D);
3499 checkGLcall("Disable GL_TEXTURE_3D");
3500 break; /* Don't bother setting the texture operations */
3501 } else {
3502 /* Enable only the appropriate texture dimension */
3503 if (Type == D3DTSS_COLOROP) {
3504 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3505 glEnable(GL_TEXTURE_1D);
3506 checkGLcall("Enable GL_TEXTURE_1D");
3507 } else {
3508 glDisable(GL_TEXTURE_1D);
3509 checkGLcall("Disable GL_TEXTURE_1D");
3511 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3512 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3513 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3514 checkGLcall("Enable GL_TEXTURE_2D");
3515 } else {
3516 glEnable(GL_TEXTURE_2D);
3517 checkGLcall("Enable GL_TEXTURE_2D");
3519 } else {
3520 glDisable(GL_TEXTURE_2D);
3521 checkGLcall("Disable GL_TEXTURE_2D");
3523 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3524 glEnable(GL_TEXTURE_3D);
3525 checkGLcall("Enable GL_TEXTURE_3D");
3526 } else {
3527 glDisable(GL_TEXTURE_3D);
3528 checkGLcall("Disable GL_TEXTURE_3D");
3530 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3531 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3532 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3533 } else {
3534 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3535 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3539 /* Drop through... (Except disable case) */
3540 case D3DTSS_COLORARG0 :
3541 case D3DTSS_COLORARG1 :
3542 case D3DTSS_COLORARG2 :
3543 case D3DTSS_ALPHAARG0 :
3544 case D3DTSS_ALPHAARG1 :
3545 case D3DTSS_ALPHAARG2 :
3547 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3548 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3549 if (isAlphaArg) {
3550 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3551 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3552 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3553 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3554 } else {
3555 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3556 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3557 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3558 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3561 break;
3564 case D3DTSS_ADDRESSU :
3565 case D3DTSS_ADDRESSV :
3566 case D3DTSS_ADDRESSW :
3568 GLint wrapParm = GL_REPEAT;
3570 switch (Value) {
3571 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3572 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3573 case D3DTADDRESS_BORDER:
3575 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3576 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3577 } else {
3578 /* FIXME: Not right, but better */
3579 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3580 wrapParm = GL_REPEAT;
3583 break;
3584 case D3DTADDRESS_MIRROR:
3586 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3587 wrapParm = GL_MIRRORED_REPEAT_ARB;
3588 } else {
3589 /* Unsupported in OpenGL pre-1.4 */
3590 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3591 wrapParm = GL_REPEAT;
3594 break;
3595 case D3DTADDRESS_MIRRORONCE:
3597 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3598 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3599 } else {
3600 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3601 wrapParm = GL_REPEAT;
3604 break;
3606 default:
3607 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3608 wrapParm = GL_REPEAT;
3611 switch (Type) {
3612 case D3DTSS_ADDRESSU:
3613 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3614 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3615 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3616 break;
3617 case D3DTSS_ADDRESSV:
3618 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3619 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3620 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3621 break;
3622 case D3DTSS_ADDRESSW:
3623 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3624 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3625 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3626 break;
3627 default: /* nop */
3628 break; /** stupic compilator */
3631 break;
3633 case D3DTSS_BORDERCOLOR :
3635 float col[4];
3636 D3DCOLORTOGLFLOAT4(Value, col);
3637 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3638 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3639 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3641 break;
3643 case D3DTSS_TEXCOORDINDEX :
3645 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3647 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3648 one flag, you can still specify an index value, which the system uses to
3649 determine the texture wrapping mode.
3650 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3651 means use the vertex position (camera-space) as the input texture coordinates
3652 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3653 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3654 to the TEXCOORDINDEX value */
3656 /**
3657 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3659 switch (Value & 0xFFFF0000) {
3660 case D3DTSS_TCI_PASSTHRU:
3661 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3662 glDisable(GL_TEXTURE_GEN_S);
3663 glDisable(GL_TEXTURE_GEN_T);
3664 glDisable(GL_TEXTURE_GEN_R);
3665 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3666 break;
3668 case D3DTSS_TCI_CAMERASPACEPOSITION:
3669 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3670 as the input texture coordinates for this stage's texture transformation. This
3671 equates roughly to EYE_LINEAR */
3673 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3674 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3675 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3676 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3677 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3679 glMatrixMode(GL_MODELVIEW);
3680 glPushMatrix();
3681 glLoadIdentity();
3682 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3683 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3684 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3685 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3686 glPopMatrix();
3688 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3689 glEnable(GL_TEXTURE_GEN_S);
3690 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3691 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3692 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3693 glEnable(GL_TEXTURE_GEN_T);
3694 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3695 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3696 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3697 glEnable(GL_TEXTURE_GEN_R);
3698 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3699 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3700 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3702 break;
3704 case D3DTSS_TCI_CAMERASPACENORMAL:
3706 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3707 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3708 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3709 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3710 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3711 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3713 glMatrixMode(GL_MODELVIEW);
3714 glPushMatrix();
3715 glLoadIdentity();
3716 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3717 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3718 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3719 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3720 glPopMatrix();
3722 glEnable(GL_TEXTURE_GEN_S);
3723 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3724 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3725 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3726 glEnable(GL_TEXTURE_GEN_T);
3727 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3728 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3729 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3730 glEnable(GL_TEXTURE_GEN_R);
3731 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3732 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3733 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3736 break;
3738 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3740 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3741 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3742 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3743 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3744 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3745 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3747 glMatrixMode(GL_MODELVIEW);
3748 glPushMatrix();
3749 glLoadIdentity();
3750 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3751 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3752 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3753 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3754 glPopMatrix();
3756 glEnable(GL_TEXTURE_GEN_S);
3757 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3758 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3759 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3760 glEnable(GL_TEXTURE_GEN_T);
3761 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3762 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3763 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3764 glEnable(GL_TEXTURE_GEN_R);
3765 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3766 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3767 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3770 break;
3772 /* Unhandled types: */
3773 default:
3774 /* Todo: */
3775 /* ? disable GL_TEXTURE_GEN_n ? */
3776 glDisable(GL_TEXTURE_GEN_S);
3777 glDisable(GL_TEXTURE_GEN_T);
3778 glDisable(GL_TEXTURE_GEN_R);
3779 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3780 break;
3783 break;
3785 /* Unhandled */
3786 case D3DTSS_TEXTURETRANSFORMFLAGS :
3787 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3788 break;
3790 case D3DTSS_BUMPENVMAT00 :
3791 case D3DTSS_BUMPENVMAT01 :
3792 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3793 break;
3794 case D3DTSS_BUMPENVMAT10 :
3795 case D3DTSS_BUMPENVMAT11 :
3796 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3797 break;
3799 case D3DTSS_BUMPENVLSCALE :
3800 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3801 break;
3803 case D3DTSS_BUMPENVLOFFSET :
3804 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3805 break;
3807 case D3DTSS_RESULTARG :
3808 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3809 break;
3811 default:
3812 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3813 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3816 LEAVE_GL();
3818 return D3D_OK;
3820 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3821 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3822 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3823 return D3D_OK;
3825 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3826 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3827 FIXME("(%p) : stub\n", This);
3828 return D3D_OK;
3830 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3831 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3832 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3833 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3834 if (PaletteNumber >= MAX_PALETTES) {
3835 return D3DERR_INVALIDCALL;
3837 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3838 return D3D_OK;
3840 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3841 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3842 if (PaletteNumber >= MAX_PALETTES) {
3843 return D3DERR_INVALIDCALL;
3845 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3846 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3847 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3848 return D3D_OK;
3850 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3851 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3852 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3853 if (PaletteNumber >= MAX_PALETTES) {
3854 return D3DERR_INVALIDCALL;
3856 This->currentPalette = PaletteNumber;
3858 #if defined(GL_EXT_paletted_texture)
3859 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3861 ENTER_GL();
3863 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3864 GL_RGBA, /* internal format */
3865 256, /* table size */
3866 GL_RGBA, /* table format */
3867 GL_UNSIGNED_BYTE, /* table type */
3868 This->palettes[PaletteNumber]);
3869 checkGLcall("glColorTableEXT");
3871 LEAVE_GL();
3873 } else {
3874 /* Delayed palette handling ... waiting for software emulation into preload code */
3876 #endif
3877 return D3D_OK;
3879 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3880 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3881 *PaletteNumber = This->currentPalette;
3882 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3883 return D3D_OK;
3885 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3887 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3888 This->StateBlock->streamIsUP = FALSE;
3890 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3891 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3893 return D3D_OK;
3895 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3896 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3897 UINT idxStride = 2;
3898 IDirect3DIndexBuffer8 *pIB;
3899 D3DINDEXBUFFER_DESC IdxBufDsc;
3901 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3902 pIB = This->StateBlock->pIndexData;
3903 This->StateBlock->streamIsUP = FALSE;
3905 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3906 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3907 minIndex, NumVertices, startIndex, primCount);
3909 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3910 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3911 idxStride = 2;
3912 } else {
3913 idxStride = 4;
3916 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3917 minIndex);
3919 return D3D_OK;
3921 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3922 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3924 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3925 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3927 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3929 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3930 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3931 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3932 This->StateBlock->streamIsUP = TRUE;
3933 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3934 This->StateBlock->stream_stride[0] = 0;
3935 This->StateBlock->stream_source[0] = NULL;
3937 /*stream zero settings set to null at end */
3938 return D3D_OK;
3940 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3941 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3942 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3943 UINT VertexStreamZeroStride) {
3944 int idxStride;
3945 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3946 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),
3947 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3949 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3950 if (IndexDataFormat == D3DFMT_INDEX16) {
3951 idxStride = 2;
3952 } else {
3953 idxStride = 4;
3956 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3957 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3958 This->StateBlock->streamIsUP = TRUE;
3959 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3960 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3962 /*stream zero settings set to null at end */
3963 This->StateBlock->stream_source[0] = NULL;
3964 This->StateBlock->stream_stride[0] = 0;
3965 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3967 return D3D_OK;
3969 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3970 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3971 FIXME("(%p) : stub\n", This); return D3D_OK;
3973 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3974 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3975 IDirect3DVertexShaderImpl* object;
3976 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3977 HRESULT res;
3978 UINT i;
3980 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3981 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3982 return D3DERR_INVALIDCALL;
3984 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3985 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3986 return D3DERR_OUTOFVIDEOMEMORY;
3989 /** Create the Vertex Shader */
3990 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3991 /** TODO: check FAILED(res) */
3993 /** Create and Bind the Vertex Shader Declaration */
3994 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3995 /** TODO: check FAILED(res) */
3997 VertexShaders[i] = object;
3998 VertexShaderDeclarations[i] = attached_decl;
3999 *pHandle = VS_HIGHESTFIXEDFXF + i;
4000 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4002 return D3D_OK;
4004 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4005 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4007 This->UpdateStateBlock->VertexShader = Handle;
4008 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4009 This->UpdateStateBlock->Set.vertexShader = TRUE;
4011 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4012 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4013 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4014 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4015 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4016 } else { /* use a fvf, so desactivate the vshader decl */
4017 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4018 This->UpdateStateBlock->vertexShaderDecl = NULL;
4019 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4020 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4022 /* Handle recording of state blocks */
4023 if (This->isRecordingState) {
4024 TRACE("Recording... not performing anything\n");
4025 return D3D_OK;
4028 * TODO: merge HAL shaders context switching from prototype
4030 return D3D_OK;
4032 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4033 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4034 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4035 *pHandle = This->StateBlock->VertexShader;
4036 return D3D_OK;
4039 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4040 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4041 IDirect3DVertexShaderImpl* object;
4042 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4044 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4045 return D3DERR_INVALIDCALL;
4049 * Delete Vertex Shader
4051 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4052 if (NULL == object) {
4053 return D3DERR_INVALIDCALL;
4055 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4056 /* TODO: check validity of object */
4057 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4058 if (object->prgId != 0) {
4059 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4061 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4062 HeapFree(GetProcessHeap(), 0, (void *)object);
4063 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4066 * Delete Vertex Shader Declaration
4068 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4069 if (NULL == attached_decl) {
4070 return D3DERR_INVALIDCALL;
4072 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4073 /* TODO: check validity of object */
4074 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4075 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4076 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4078 return D3D_OK;
4081 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4082 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4084 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4085 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4086 return D3DERR_INVALIDCALL;
4088 if (NULL == pConstantData) {
4089 return D3DERR_INVALIDCALL;
4091 if (ConstantCount > 1) {
4092 FLOAT* f = (FLOAT*)pConstantData;
4093 UINT i;
4094 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4095 for (i = 0; i < ConstantCount; ++i) {
4096 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4097 f += 4;
4099 } else {
4100 FLOAT* f = (FLOAT*) pConstantData;
4101 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4103 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4104 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4105 return D3D_OK;
4107 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4108 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4110 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4111 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4112 return D3DERR_INVALIDCALL;
4114 if (NULL == pConstantData) {
4115 return D3DERR_INVALIDCALL;
4117 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4118 return D3D_OK;
4120 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4121 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4122 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4124 attached_decl = VERTEX_SHADER_DECL(Handle);
4125 if (NULL == attached_decl) {
4126 return D3DERR_INVALIDCALL;
4128 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4130 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4131 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4132 IDirect3DVertexShaderImpl* object;
4134 object = VERTEX_SHADER(Handle);
4135 if (NULL == object) {
4136 return D3DERR_INVALIDCALL;
4138 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4141 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4142 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4143 IDirect3DIndexBuffer8 *oldIdxs;
4145 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4146 oldIdxs = This->StateBlock->pIndexData;
4148 This->UpdateStateBlock->Changed.Indices = TRUE;
4149 This->UpdateStateBlock->Set.Indices = TRUE;
4150 This->UpdateStateBlock->pIndexData = pIndexData;
4151 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4153 /* Handle recording of state blocks */
4154 if (This->isRecordingState) {
4155 TRACE("Recording... not performing anything\n");
4156 return D3D_OK;
4159 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4160 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4161 return D3D_OK;
4163 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4164 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4165 FIXME("(%p) : stub\n", This);
4167 *ppIndexData = This->StateBlock->pIndexData;
4168 /* up ref count on ppindexdata */
4169 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4170 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4172 return D3D_OK;
4174 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4175 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4176 IDirect3DPixelShaderImpl* object;
4177 HRESULT res;
4178 UINT i;
4180 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4181 if (NULL == pFunction || NULL == pHandle) {
4182 return D3DERR_INVALIDCALL;
4184 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4185 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4186 return D3DERR_OUTOFVIDEOMEMORY;
4189 /** Create the Pixel Shader */
4190 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4191 if (SUCCEEDED(res)) {
4192 PixelShaders[i] = object;
4193 *pHandle = VS_HIGHESTFIXEDFXF + i;
4194 return D3D_OK;
4196 *pHandle = 0xFFFFFFFF;
4197 return res;
4200 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4201 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4203 This->UpdateStateBlock->PixelShader = Handle;
4204 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4205 This->UpdateStateBlock->Set.pixelShader = TRUE;
4207 /* Handle recording of state blocks */
4208 if (This->isRecordingState) {
4209 TRACE_(d3d_shader)("Recording... not performing anything\n");
4210 return D3D_OK;
4213 if (Handle != 0) {
4214 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4215 } else {
4216 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4219 return D3D_OK;
4222 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4223 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4224 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4225 *pHandle = This->StateBlock->PixelShader;
4226 return D3D_OK;
4229 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4230 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4231 IDirect3DPixelShaderImpl* object;
4233 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4234 return D3DERR_INVALIDCALL;
4236 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4237 if (NULL == object) {
4238 return D3DERR_INVALIDCALL;
4240 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4241 /* TODO: check validity of object before free */
4242 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4243 if (object->prgId != 0) {
4244 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4246 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4247 HeapFree(GetProcessHeap(), 0, (void *)object);
4248 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4250 return D3D_OK;
4253 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4254 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4256 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4257 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4258 return D3DERR_INVALIDCALL;
4260 if (NULL == pConstantData) {
4261 return D3DERR_INVALIDCALL;
4263 if (ConstantCount > 1) {
4264 FLOAT* f = (FLOAT*)pConstantData;
4265 UINT i;
4266 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4267 for (i = 0; i < ConstantCount; ++i) {
4268 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4269 f += 4;
4271 } else {
4272 FLOAT* f = (FLOAT*) pConstantData;
4273 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4275 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4276 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4277 return D3D_OK;
4279 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4280 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4282 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4283 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4284 return D3DERR_INVALIDCALL;
4286 if (NULL == pConstantData) {
4287 return D3DERR_INVALIDCALL;
4289 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4290 return D3D_OK;
4292 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4293 IDirect3DPixelShaderImpl* object;
4295 object = PIXEL_SHADER(Handle);
4296 if (NULL == object) {
4297 return D3DERR_INVALIDCALL;
4299 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4301 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4302 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4303 FIXME("(%p) : stub\n", This); return D3D_OK;
4305 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4306 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4307 FIXME("(%p) : stub\n", This); return D3D_OK;
4309 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4310 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4311 FIXME("(%p) : stub\n", This); return D3D_OK;
4314 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4315 IDirect3DVertexBuffer8 *oldSrc;
4316 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4318 oldSrc = This->StateBlock->stream_source[StreamNumber];
4319 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4321 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4322 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4323 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4324 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4326 /* Handle recording of state blocks */
4327 if (This->isRecordingState) {
4328 TRACE("Recording... not performing anything\n");
4329 return D3D_OK;
4332 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4333 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4334 return D3D_OK;
4336 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4337 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4338 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4339 *pStream = This->StateBlock->stream_source[StreamNumber];
4340 *pStride = This->StateBlock->stream_stride[StreamNumber];
4341 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4342 return D3D_OK;
4346 IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4348 IDirect3DDevice8Impl_QueryInterface,
4349 IDirect3DDevice8Impl_AddRef,
4350 IDirect3DDevice8Impl_Release,
4351 IDirect3DDevice8Impl_TestCooperativeLevel,
4352 IDirect3DDevice8Impl_GetAvailableTextureMem,
4353 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4354 IDirect3DDevice8Impl_GetDirect3D,
4355 IDirect3DDevice8Impl_GetDeviceCaps,
4356 IDirect3DDevice8Impl_GetDisplayMode,
4357 IDirect3DDevice8Impl_GetCreationParameters,
4358 IDirect3DDevice8Impl_SetCursorProperties,
4359 IDirect3DDevice8Impl_SetCursorPosition,
4360 IDirect3DDevice8Impl_ShowCursor,
4361 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4362 IDirect3DDevice8Impl_Reset,
4363 IDirect3DDevice8Impl_Present,
4364 IDirect3DDevice8Impl_GetBackBuffer,
4365 IDirect3DDevice8Impl_GetRasterStatus,
4366 IDirect3DDevice8Impl_SetGammaRamp,
4367 IDirect3DDevice8Impl_GetGammaRamp,
4368 IDirect3DDevice8Impl_CreateTexture,
4369 IDirect3DDevice8Impl_CreateVolumeTexture,
4370 IDirect3DDevice8Impl_CreateCubeTexture,
4371 IDirect3DDevice8Impl_CreateVertexBuffer,
4372 IDirect3DDevice8Impl_CreateIndexBuffer,
4373 IDirect3DDevice8Impl_CreateRenderTarget,
4374 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4375 IDirect3DDevice8Impl_CreateImageSurface,
4376 IDirect3DDevice8Impl_CopyRects,
4377 IDirect3DDevice8Impl_UpdateTexture,
4378 IDirect3DDevice8Impl_GetFrontBuffer,
4379 IDirect3DDevice8Impl_SetRenderTarget,
4380 IDirect3DDevice8Impl_GetRenderTarget,
4381 IDirect3DDevice8Impl_GetDepthStencilSurface,
4382 IDirect3DDevice8Impl_BeginScene,
4383 IDirect3DDevice8Impl_EndScene,
4384 IDirect3DDevice8Impl_Clear,
4385 IDirect3DDevice8Impl_SetTransform,
4386 IDirect3DDevice8Impl_GetTransform,
4387 IDirect3DDevice8Impl_MultiplyTransform,
4388 IDirect3DDevice8Impl_SetViewport,
4389 IDirect3DDevice8Impl_GetViewport,
4390 IDirect3DDevice8Impl_SetMaterial,
4391 IDirect3DDevice8Impl_GetMaterial,
4392 IDirect3DDevice8Impl_SetLight,
4393 IDirect3DDevice8Impl_GetLight,
4394 IDirect3DDevice8Impl_LightEnable,
4395 IDirect3DDevice8Impl_GetLightEnable,
4396 IDirect3DDevice8Impl_SetClipPlane,
4397 IDirect3DDevice8Impl_GetClipPlane,
4398 IDirect3DDevice8Impl_SetRenderState,
4399 IDirect3DDevice8Impl_GetRenderState,
4400 IDirect3DDevice8Impl_BeginStateBlock,
4401 IDirect3DDevice8Impl_EndStateBlock,
4402 IDirect3DDevice8Impl_ApplyStateBlock,
4403 IDirect3DDevice8Impl_CaptureStateBlock,
4404 IDirect3DDevice8Impl_DeleteStateBlock,
4405 IDirect3DDevice8Impl_CreateStateBlock,
4406 IDirect3DDevice8Impl_SetClipStatus,
4407 IDirect3DDevice8Impl_GetClipStatus,
4408 IDirect3DDevice8Impl_GetTexture,
4409 IDirect3DDevice8Impl_SetTexture,
4410 IDirect3DDevice8Impl_GetTextureStageState,
4411 IDirect3DDevice8Impl_SetTextureStageState,
4412 IDirect3DDevice8Impl_ValidateDevice,
4413 IDirect3DDevice8Impl_GetInfo,
4414 IDirect3DDevice8Impl_SetPaletteEntries,
4415 IDirect3DDevice8Impl_GetPaletteEntries,
4416 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4417 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4418 IDirect3DDevice8Impl_DrawPrimitive,
4419 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4420 IDirect3DDevice8Impl_DrawPrimitiveUP,
4421 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4422 IDirect3DDevice8Impl_ProcessVertices,
4423 IDirect3DDevice8Impl_CreateVertexShader,
4424 IDirect3DDevice8Impl_SetVertexShader,
4425 IDirect3DDevice8Impl_GetVertexShader,
4426 IDirect3DDevice8Impl_DeleteVertexShader,
4427 IDirect3DDevice8Impl_SetVertexShaderConstant,
4428 IDirect3DDevice8Impl_GetVertexShaderConstant,
4429 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4430 IDirect3DDevice8Impl_GetVertexShaderFunction,
4431 IDirect3DDevice8Impl_SetStreamSource,
4432 IDirect3DDevice8Impl_GetStreamSource,
4433 IDirect3DDevice8Impl_SetIndices,
4434 IDirect3DDevice8Impl_GetIndices,
4435 IDirect3DDevice8Impl_CreatePixelShader,
4436 IDirect3DDevice8Impl_SetPixelShader,
4437 IDirect3DDevice8Impl_GetPixelShader,
4438 IDirect3DDevice8Impl_DeletePixelShader,
4439 IDirect3DDevice8Impl_SetPixelShaderConstant,
4440 IDirect3DDevice8Impl_GetPixelShaderConstant,
4441 IDirect3DDevice8Impl_GetPixelShaderFunction,
4442 IDirect3DDevice8Impl_DrawRectPatch,
4443 IDirect3DDevice8Impl_DrawTriPatch,
4444 IDirect3DDevice8Impl_DeletePatch
4447 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4449 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4450 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4452 ENTER_GL();
4454 #if 0
4455 if (This->glCtx != This->render_ctx) {
4456 glXDestroyContext(This->display, This->render_ctx);
4457 This->render_ctx = This->glCtx;
4459 #endif
4460 if (This->win != This->drawable) {
4461 glXDestroyPbuffer(This->display, This->drawable);
4462 This->drawable = This->win;
4465 LEAVE_GL();
4467 #endif
4468 return D3D_OK;
4471 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4472 IDirect3DSurface8* RenderSurface,
4473 IDirect3DSurface8* StencilSurface) {
4475 HRESULT ret = D3DERR_INVALIDCALL;
4477 * Currently only active for GLX >= 1.3
4478 * for others versions we'll have to use GLXPixmaps
4480 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4481 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4482 * so only check OpenGL version
4484 #if defined(GL_VERSION_1_3)
4485 GLXFBConfig* cfgs = NULL;
4486 int nCfgs = 0;
4487 int attribs[256];
4488 int nAttribs = 0;
4489 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4490 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4491 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4492 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4493 IDirect3DSurface8Impl* tmp;
4495 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4497 #define PUSH1(att) attribs[nAttribs++] = (att);
4498 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4500 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4501 PUSH2(GLX_X_RENDERABLE, TRUE);
4502 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4504 switch (BackBufferFormat) {
4505 /* color buffer */
4506 case D3DFMT_P8:
4507 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4508 PUSH2(GLX_BUFFER_SIZE, 8);
4509 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4510 break;
4512 case D3DFMT_R3G3B2:
4513 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4514 PUSH2(GLX_RED_SIZE, 3);
4515 PUSH2(GLX_GREEN_SIZE, 3);
4516 PUSH2(GLX_BLUE_SIZE, 2);
4517 break;
4519 case D3DFMT_A1R5G5B5:
4520 PUSH2(GLX_ALPHA_SIZE, 1);
4521 case D3DFMT_X1R5G5B5:
4522 PUSH2(GLX_RED_SIZE, 5);
4523 PUSH2(GLX_GREEN_SIZE, 5);
4524 PUSH2(GLX_BLUE_SIZE, 5);
4525 break;
4527 case D3DFMT_R5G6B5:
4528 PUSH2(GLX_RED_SIZE, 5);
4529 PUSH2(GLX_GREEN_SIZE, 6);
4530 PUSH2(GLX_BLUE_SIZE, 5);
4531 break;
4533 case D3DFMT_A4R4G4B4:
4534 PUSH2(GLX_ALPHA_SIZE, 4);
4535 case D3DFMT_X4R4G4B4:
4536 PUSH2(GLX_RED_SIZE, 4);
4537 PUSH2(GLX_GREEN_SIZE, 4);
4538 PUSH2(GLX_BLUE_SIZE, 4);
4539 break;
4541 case D3DFMT_A8R8G8B8:
4542 PUSH2(GLX_ALPHA_SIZE, 8);
4543 case D3DFMT_R8G8B8:
4544 case D3DFMT_X8R8G8B8:
4545 PUSH2(GLX_RED_SIZE, 8);
4546 PUSH2(GLX_GREEN_SIZE, 8);
4547 PUSH2(GLX_BLUE_SIZE, 8);
4548 break;
4550 default:
4551 break;
4554 switch (StencilBufferFormat) {
4555 case D3DFMT_D16_LOCKABLE:
4556 case D3DFMT_D16:
4557 PUSH2(GLX_DEPTH_SIZE, 16);
4558 break;
4560 case D3DFMT_D15S1:
4561 PUSH2(GLX_DEPTH_SIZE, 15);
4562 break;
4564 case D3DFMT_D24X8:
4565 PUSH2(GLX_DEPTH_SIZE, 24);
4566 break;
4568 case D3DFMT_D24X4S4:
4569 PUSH2(GLX_DEPTH_SIZE, 24);
4570 PUSH2(GLX_STENCIL_SIZE, 4);
4571 break;
4573 case D3DFMT_D24S8:
4574 PUSH2(GLX_DEPTH_SIZE, 24);
4575 PUSH2(GLX_STENCIL_SIZE, 8);
4576 break;
4578 case D3DFMT_D32:
4579 PUSH2(GLX_DEPTH_SIZE, 32);
4580 break;
4582 default:
4583 break;
4586 PUSH1(None);
4588 ENTER_GL();
4590 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4591 if (NULL != cfgs) {
4592 #ifdef EXTRA_TRACES
4593 int i;
4594 for (i = 0; i < nCfgs; ++i) {
4595 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4597 #endif
4599 if (NULL != This->renderTarget) {
4600 /*GLenum prev_read; */
4601 glFlush();
4602 vcheckGLcall("glFlush");
4604 #ifdef EXTRA_TRACES
4605 /** very very usefull debug code */
4606 glXSwapBuffers(This->display, This->drawable);
4607 printf("Hit Enter to get next frame ...\n");
4608 getchar();
4609 #endif
4611 #if 0
4612 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4613 vcheckGLcall("glIntegerv");
4614 glReadBuffer(GL_BACK);
4615 vcheckGLcall("glReadBuffer");
4617 long j;
4618 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4620 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4621 pitch = pitch / 2;
4623 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4624 glReadPixels(0,
4625 This->renderTarget->myDesc.Height - j - 1,
4626 This->renderTarget->myDesc.Width,
4628 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4629 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4630 This->renderTarget->allocatedMemory + j * pitch);
4631 vcheckGLcall("glReadPixels");
4634 glReadBuffer(prev_read);
4635 vcheckGLcall("glReadBuffer");
4636 #endif
4639 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4640 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4641 nAttribs = 0;
4642 PUSH2(GLX_PBUFFER_WIDTH, Width);
4643 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4644 PUSH1(None);
4645 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4647 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4648 if (NULL == This->render_ctx) {
4649 ERR("cannot create glxContext\n");
4652 glFlush();
4653 glXSwapBuffers(This->display, This->drawable);
4654 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4655 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4657 checkGLcall("glXMakeContextCurrent");
4660 tmp = This->renderTarget;
4661 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4662 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4663 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4665 tmp = This->stencilBufferTarget;
4666 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4667 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4668 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4671 DWORD value;
4672 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4673 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4674 /* Force updating the cull mode */
4675 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4676 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4677 /* Force updating projection matrix */
4678 This->last_was_rhw = FALSE;
4679 This->proj_valid = FALSE;
4682 ret = D3D_OK;
4684 } else {
4685 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4688 #undef PUSH1
4689 #undef PUSH2
4691 LEAVE_GL();
4693 #endif
4695 return ret;