Authors: Christian Costa <titan.costa@wanadoo.fr>, Jason Edmeades <us@the-edmeades...
[wine/multimedia.git] / dlls / d3d8 / device.c
blob80bda422e1ae9e5619743478e75cbd7faa746b89
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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 ICOM_THIS(IDirect3DDevice8Impl,iface);
333 FIXME("(%p) : stub\n", This); return D3D_OK;
335 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
336 ICOM_THIS(IDirect3DDevice8Impl,iface);
337 TRACE("(%p) : returning %p\n", This, This->direct3d8);
339 /* Inc ref count */
340 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
342 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
343 return D3D_OK;
345 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
346 ICOM_THIS(IDirect3DDevice8Impl,iface);
347 FIXME("(%p) : stub, calling idirect3d for now\n", This);
348 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
349 return D3D_OK;
351 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
353 HDC hdc;
354 int bpp = 0;
356 ICOM_THIS(IDirect3DDevice8Impl,iface);
357 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
358 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
359 pMode->RefreshRate = 85; /*FIXME: How to identify? */
361 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
362 bpp = GetDeviceCaps(hdc, BITSPIXEL);
363 DeleteDC(hdc);
365 switch (bpp) {
366 case 8: pMode->Format = D3DFMT_R8G8B8; break;
367 case 16: pMode->Format = D3DFMT_R5G6B5; break;
368 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
369 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
370 default:
371 FIXME("Unrecognized display mode format\n");
372 pMode->Format = D3DFMT_UNKNOWN;
375 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
376 pMode->Format, debug_d3dformat(pMode->Format));
377 return D3D_OK;
379 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
380 ICOM_THIS(IDirect3DDevice8Impl,iface);
381 TRACE("(%p) copying to %p\n", This, pParameters);
382 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
383 return D3D_OK;
385 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
386 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
387 ICOM_THIS(IDirect3DDevice8Impl,iface);
388 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
390 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
391 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
392 return D3DERR_INVALIDCALL;
394 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
395 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
396 return D3DERR_INVALIDCALL;
399 This->xHotSpot = XHotSpot;
400 This->yHotSpot = YHotSpot;
401 return D3D_OK;
403 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
404 ICOM_THIS(IDirect3DDevice8Impl,iface);
405 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
406 This->xScreenSpace = XScreenSpace;
407 This->yScreenSpace = YScreenSpace;
408 return;
410 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
411 ICOM_THIS(IDirect3DDevice8Impl,iface);
412 TRACE("(%p) : visible(%d)\n", This, bShow);
413 This->bCursorVisible = bShow;
414 return D3D_OK;
416 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
417 IDirect3DSwapChain8Impl* object;
418 ICOM_THIS(IDirect3DDevice8Impl,iface);
419 FIXME("(%p) : stub\n", This);
421 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
422 if (NULL == object) {
423 return D3DERR_OUTOFVIDEOMEMORY;
425 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
426 object->ref = 1;
428 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
429 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
430 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
432 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
433 (pPresentationParameters->BackBufferHeight == 0))) {
434 RECT Rect;
436 GetClientRect(This->win_handle, &Rect);
438 if (pPresentationParameters->BackBufferWidth == 0) {
439 pPresentationParameters->BackBufferWidth = Rect.right;
440 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
442 if (pPresentationParameters->BackBufferHeight == 0) {
443 pPresentationParameters->BackBufferHeight = Rect.bottom;
444 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
448 /* Save the presentation parms now filled in correctly */
449 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
451 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
452 pPresentationParameters->BackBufferWidth,
453 pPresentationParameters->BackBufferHeight,
454 pPresentationParameters->BackBufferFormat,
455 pPresentationParameters->MultiSampleType,
456 TRUE,
457 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
459 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
460 pPresentationParameters->BackBufferWidth,
461 pPresentationParameters->BackBufferHeight,
462 pPresentationParameters->BackBufferFormat,
463 pPresentationParameters->MultiSampleType,
464 TRUE,
465 (LPDIRECT3DSURFACE8*) &object->backBuffer);
467 if (pPresentationParameters->EnableAutoDepthStencil) {
468 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
469 pPresentationParameters->BackBufferWidth,
470 pPresentationParameters->BackBufferHeight,
471 pPresentationParameters->AutoDepthStencilFormat,
472 D3DMULTISAMPLE_NONE,
473 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
474 } else {
475 object->depthStencilBuffer = NULL;
478 *pSwapChain = (IDirect3DSwapChain8*) object;
479 return D3D_OK;
481 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
482 ICOM_THIS(IDirect3DDevice8Impl,iface);
483 FIXME("(%p) : stub\n", This); return D3D_OK;
485 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
486 CONST RECT* pSourceRect, CONST RECT* pDestRect,
487 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
488 ICOM_THIS(IDirect3DDevice8Impl,iface);
489 TRACE("(%p) : complete stub!\n", This);
491 ENTER_GL();
493 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
496 glXSwapBuffers(This->display, This->drawable);
497 /* Don't call checkGLcall, as glGetError is not applicable here */
498 TRACE("glXSwapBuffers called, Starting new frame\n");
500 /* FPS support */
501 if (TRACE_ON(d3d_fps))
503 static long prev_time, frames;
505 DWORD time = GetTickCount();
506 frames++;
507 /* every 1.5 seconds */
508 if (time - prev_time > 1500) {
509 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
510 prev_time = time;
511 frames = 0;
515 #if defined(FRAME_DEBUGGING)
517 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
518 if (!isOn) {
519 isOn = TRUE;
520 FIXME("Enabling D3D Trace\n");
521 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
522 #if defined(SHOW_FRAME_MAKEUP)
523 FIXME("Singe Frame snapshots Starting\n");
524 isDumpingFrames = TRUE;
525 glClear(GL_COLOR_BUFFER_BIT);
526 #endif
528 #if defined(SINGLE_FRAME_DEBUGGING)
529 } else {
530 #if defined(SHOW_FRAME_MAKEUP)
531 FIXME("Singe Frame snapshots Finishing\n");
532 isDumpingFrames = FALSE;
533 #endif
534 FIXME("Singe Frame trace complete\n");
535 DeleteFileA("C:\\D3DTRACE");
536 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
537 #endif
539 } else {
540 if (isOn) {
541 isOn = FALSE;
542 #if defined(SHOW_FRAME_MAKEUP)
543 FIXME("Singe Frame snapshots Finishing\n");
544 isDumpingFrames = FALSE;
545 #endif
546 FIXME("Disabling D3D Trace\n");
547 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
551 #endif
553 LEAVE_GL();
554 /* Although this is not strictly required, a simple demo showed this does occur
555 on (at least non-debug) d3d */
556 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
557 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
560 return D3D_OK;
562 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
563 ICOM_THIS(IDirect3DDevice8Impl,iface);
564 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
565 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
567 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
568 FIXME("Only one backBuffer currently supported\n");
569 return D3DERR_INVALIDCALL;
572 /* Note inc ref on returned surface */
573 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
575 return D3D_OK;
577 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
578 ICOM_THIS(IDirect3DDevice8Impl,iface);
579 FIXME("(%p) : stub\n", This);
580 return D3D_OK;
582 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
583 HDC hDC;
584 ICOM_THIS(IDirect3DDevice8Impl,iface);
586 FIXME("(%p) : pRamp@%p\n", This, pRamp);
587 hDC = GetDC(This->win_handle);
588 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
589 ReleaseDC(This->win_handle, hDC);
590 return;
592 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
593 HDC hDC;
594 ICOM_THIS(IDirect3DDevice8Impl,iface);
596 FIXME("(%p) : pRamp@%p\n", This, pRamp);
597 hDC = GetDC(This->win_handle);
598 GetDeviceGammaRamp(hDC, pRamp);
599 ReleaseDC(This->win_handle, hDC);
600 return;
602 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
603 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
604 IDirect3DTexture8Impl *object;
605 int i;
606 UINT tmpW;
607 UINT tmpH;
609 ICOM_THIS(IDirect3DDevice8Impl,iface);
611 /* Allocate the storage for the device */
612 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);
613 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
614 object->lpVtbl = &Direct3DTexture8_Vtbl;
615 object->Device = This;
616 object->ResourceType = D3DRTYPE_TEXTURE;
617 object->ref = 1;
618 object->width = Width;
619 object->height = Height;
620 object->levels = Levels;
621 object->usage = Usage;
622 object->format = Format;
624 /* Calculate levels for mip mapping */
625 if (Levels == 0) {
626 object->levels++;
627 tmpW = Width;
628 tmpH = Height;
629 while (tmpW > 1 && tmpH > 1) {
630 tmpW = max(1, tmpW / 2);
631 tmpH = max(1, tmpH / 2);
632 object->levels++;
634 TRACE("Calculated levels = %d\n", object->levels);
637 /* Generate all the surfaces */
638 tmpW = Width;
639 tmpH = Height;
640 for (i = 0; i < object->levels; i++)
642 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
643 object->surfaces[i]->Container = (IUnknown*) object;
644 object->surfaces[i]->myDesc.Usage = Usage;
645 object->surfaces[i]->myDesc.Pool = Pool;
646 /**
647 * As written in msdn in IDirect3DTexture8::LockRect
648 * Textures created in D3DPOOL_DEFAULT are not lockable.
650 if (D3DPOOL_DEFAULT == Pool) {
651 object->surfaces[i]->lockable = FALSE;
654 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
655 tmpW = max(1, tmpW / 2);
656 tmpH = max(1, tmpH / 2);
659 *ppTexture = (LPDIRECT3DTEXTURE8) object;
660 TRACE("(%p) : Created texture %p\n", This, object);
661 return D3D_OK;
663 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
664 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
665 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
667 IDirect3DVolumeTexture8Impl *object;
668 int i;
669 UINT tmpW;
670 UINT tmpH;
671 UINT tmpD;
673 ICOM_THIS(IDirect3DDevice8Impl,iface);
675 /* Allocate the storage for it */
676 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));
677 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
678 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
679 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
680 object->Device = This;
681 object->ref = 1;
683 object->width = Width;
684 object->height = Height;
685 object->depth = Depth;
686 object->levels = Levels;
687 object->usage = Usage;
688 object->format = Format;
690 /* Calculate levels for mip mapping */
691 if (Levels == 0) {
692 object->levels++;
693 tmpW = Width;
694 tmpH = Height;
695 tmpD = Depth;
696 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
697 tmpW = max(1, tmpW / 2);
698 tmpH = max(1, tmpH / 2);
699 tmpD = max(1, tmpD / 2);
700 object->levels++;
702 TRACE("Calculated levels = %d\n", object->levels);
705 /* Generate all the surfaces */
706 tmpW = Width;
707 tmpH = Height;
708 tmpD = Depth;
710 for (i = 0; i < object->levels; i++)
712 IDirect3DVolume8Impl* volume;
714 /* Create the volume - No entry point for this seperately?? */
715 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
716 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
718 volume->lpVtbl = &Direct3DVolume8_Vtbl;
719 volume->Device = This;
720 volume->ResourceType = D3DRTYPE_VOLUME;
721 volume->Container = (IUnknown*) object;
722 volume->ref = 1;
724 volume->myDesc.Width = Width;
725 volume->myDesc.Height = Height;
726 volume->myDesc.Depth = Depth;
727 volume->myDesc.Format = Format;
728 volume->myDesc.Type = D3DRTYPE_VOLUME;
729 volume->myDesc.Pool = Pool;
730 volume->myDesc.Usage = Usage;
731 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
732 /* Note: Volume textures cannot be dxtn, hence no need to check here */
733 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
734 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
736 volume->lockable = TRUE;
737 volume->locked = FALSE;
738 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
739 volume->Dirty = FALSE;
740 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
742 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
743 This, Width, Height, Depth, Format, debug_d3dformat(Format),
744 volume, volume->allocatedMemory, volume->myDesc.Size);
746 tmpW = max(1, tmpW / 2);
747 tmpH = max(1, tmpH / 2);
748 tmpD = max(1, tmpD / 2);
751 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
752 TRACE("(%p) : Created volume texture %p\n", This, object);
753 return D3D_OK;
755 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
756 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
758 IDirect3DCubeTexture8Impl *object;
759 ICOM_THIS(IDirect3DDevice8Impl,iface);
760 int i,j;
761 UINT tmpW;
763 /* Allocate the storage for it */
764 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));
765 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
766 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
767 object->ref = 1;
768 object->Device = This;
769 object->ResourceType = D3DRTYPE_CUBETEXTURE;
771 object->edgeLength = EdgeLength;
772 object->levels = Levels;
773 object->usage = Usage;
774 object->format = Format;
776 /* Calculate levels for mip mapping */
777 if (Levels == 0) {
778 object->levels++;
779 tmpW = EdgeLength;
780 while (tmpW > 1) {
781 tmpW = max(1, tmpW / 2);
782 object->levels++;
784 TRACE("Calculated levels = %d\n", object->levels);
787 /* Generate all the surfaces */
788 tmpW = EdgeLength;
789 for (i = 0; i < object->levels; i++) {
790 /* Create the 6 faces */
791 for (j = 0; j < 6; j++) {
792 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
793 object->surfaces[j][i]->Container = (IUnknown*) object;
794 object->surfaces[j][i]->myDesc.Usage = Usage;
795 object->surfaces[j][i]->myDesc.Pool = Pool;
796 /**
797 * As written in msdn in IDirect3DCubeTexture8::LockRect
798 * Textures created in D3DPOOL_DEFAULT are not lockable.
800 if (D3DPOOL_DEFAULT == Pool) {
801 object->surfaces[j][i]->lockable = FALSE;
804 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
806 tmpW = max(1, tmpW / 2);
809 TRACE("(%p) : Iface@%p\n", This, object);
810 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
811 return D3D_OK;
813 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
814 IDirect3DVertexBuffer8Impl *object;
816 ICOM_THIS(IDirect3DDevice8Impl,iface);
818 /* Allocate the storage for the device */
819 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
820 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
821 object->Device = This;
822 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
823 object->ref = 1;
824 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
825 object->currentDesc.Usage = Usage;
826 object->currentDesc.Pool = Pool;
827 object->currentDesc.FVF = FVF;
828 object->currentDesc.Size = Size;
830 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
832 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
834 return D3D_OK;
836 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
837 IDirect3DIndexBuffer8Impl *object;
839 ICOM_THIS(IDirect3DDevice8Impl,iface);
840 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
842 /* Allocate the storage for the device */
843 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
844 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
845 object->Device = This;
846 object->ref = 1;
847 object->ResourceType = D3DRTYPE_INDEXBUFFER;
849 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
850 object->currentDesc.Usage = Usage;
851 object->currentDesc.Pool = Pool;
852 object->currentDesc.Format = Format;
853 object->currentDesc.Size = Length;
855 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
857 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
859 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
861 return D3D_OK;
863 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
864 IDirect3DSurface8Impl *object;
865 ICOM_THIS(IDirect3DDevice8Impl,iface);
867 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
868 if (NULL == object) {
869 *ppSurface = NULL;
870 return D3DERR_OUTOFVIDEOMEMORY;
872 *ppSurface = (LPDIRECT3DSURFACE8) object;
873 object->lpVtbl = &Direct3DSurface8_Vtbl;
874 object->Device = This;
875 object->ResourceType = D3DRTYPE_SURFACE;
876 object->Container = (IUnknown*) This;
878 object->ref = 1;
879 object->myDesc.Width = Width;
880 object->myDesc.Height = Height;
881 object->myDesc.Format = Format;
882 object->myDesc.Type = D3DRTYPE_SURFACE;
883 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
884 object->myDesc.Pool = D3DPOOL_DEFAULT;
885 object->myDesc.MultiSampleType = MultiSample;
886 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
887 if (Format == D3DFMT_DXT1) {
888 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
889 } else {
890 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
892 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
893 object->lockable = Lockable;
894 object->locked = FALSE;
895 memset(&object->lockedRect, 0, sizeof(RECT));
896 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
898 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);
899 return D3D_OK;
901 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
902 IDirect3DSurface8Impl *object;
904 ICOM_THIS(IDirect3DDevice8Impl,iface);
906 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
907 if (NULL == object) {
908 *ppSurface = NULL;
909 return D3DERR_OUTOFVIDEOMEMORY;
911 *ppSurface = (LPDIRECT3DSURFACE8) object;
912 object->lpVtbl = &Direct3DSurface8_Vtbl;
913 object->Device = This;
914 object->ResourceType = D3DRTYPE_SURFACE;
915 object->Container = (IUnknown*) This;
917 object->ref = 1;
918 object->myDesc.Width = Width;
919 object->myDesc.Height = Height;
920 object->myDesc.Format = Format;
921 object->myDesc.Type = D3DRTYPE_SURFACE;
922 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
923 object->myDesc.Pool = D3DPOOL_DEFAULT;
924 object->myDesc.MultiSampleType = MultiSample;
925 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
926 if (Format == D3DFMT_DXT1) {
927 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
928 } else {
929 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
931 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
932 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
933 object->locked = FALSE;
934 memset(&object->lockedRect, 0, sizeof(RECT));
935 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
937 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);
938 return D3D_OK;
940 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
941 IDirect3DSurface8Impl *object;
943 ICOM_THIS(IDirect3DDevice8Impl,iface);
945 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
946 *ppSurface = (LPDIRECT3DSURFACE8) object;
947 object->lpVtbl = &Direct3DSurface8_Vtbl;
948 object->Device = This;
949 object->ResourceType = D3DRTYPE_SURFACE;
950 object->Container = (IUnknown*) This;
952 object->ref = 1;
953 object->myDesc.Width = Width;
954 object->myDesc.Height = Height;
955 object->myDesc.Format = Format;
956 object->myDesc.Type = D3DRTYPE_SURFACE;
957 object->myDesc.Usage = 0;
958 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
959 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
960 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
961 it is based around 4x4 pixel blocks it requires padding, so allocate enough
962 space! */
963 if (Format == D3DFMT_DXT1) {
964 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
965 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
966 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
967 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
968 } else {
969 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
971 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
972 object->lockable = TRUE;
973 object->locked = FALSE;
974 memset(&object->lockedRect, 0, sizeof(RECT));
975 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
977 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);
978 return D3D_OK;
980 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
981 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
982 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
984 HRESULT rc = D3D_OK;
985 IDirect3DBaseTexture8* texture = NULL;
988 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
989 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
991 ICOM_THIS(IDirect3DDevice8Impl,iface);
992 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
993 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
995 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
996 a sample and doesn't seem to break anything as far as I can tell */
997 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
998 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
999 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1000 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1001 rc = D3DERR_INVALIDCALL;
1003 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1004 TRACE("Converting dest to same format as source, since dest was unknown\n");
1005 dst->myDesc.Format = src->myDesc.Format;
1007 /* Convert container as well */
1008 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1009 if (SUCCEEDED(rc) && NULL != texture) {
1010 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1011 /** Releasing texture after GetContainer */
1012 IDirect3DBaseTexture8_Release(texture);
1013 texture = NULL;
1017 /* Quick if complete copy ... */
1018 if (SUCCEEDED(rc)) {
1019 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1021 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1023 D3DLOCKED_RECT lrSrc;
1024 D3DLOCKED_RECT lrDst;
1025 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1026 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1027 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1029 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1031 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1032 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1033 TRACE("Unlocked src and dst\n");
1035 } else {
1037 FIXME("Wanted to copy all surfaces but size not compatible\n");
1038 rc = D3DERR_INVALIDCALL;
1042 } else {
1044 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1046 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1047 int i;
1049 /* Copy rect by rect */
1050 for (i = 0; i < cRects; i++) {
1051 CONST RECT* r = &pSourceRectsArray[i];
1052 CONST POINT* p = &pDestPointsArray[i];
1053 int copyperline;
1054 int j;
1055 D3DLOCKED_RECT lrSrc;
1056 D3DLOCKED_RECT lrDst;
1057 RECT dest_rect;
1059 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1060 if (src->myDesc.Format == D3DFMT_DXT1) {
1061 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1062 } else {
1063 copyperline = ((r->right - r->left) * bytesPerPixel);
1065 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1066 dest_rect.left = p->x;
1067 dest_rect.top = p->y;
1068 dest_rect.right = p->x + (r->right - r->left);
1069 dest_rect.bottom= p->y + (r->bottom - r->top);
1070 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1071 TRACE("Locked src and dst\n");
1073 /* Find where to start */
1074 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1075 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1077 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1078 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1079 TRACE("Unlocked src and dst\n");
1081 } else {
1082 FIXME("Wanted to copy partial surfaces not implemented\n");
1083 rc = D3DERR_INVALIDCALL;
1088 return rc;
1090 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1091 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1092 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1093 D3DRESOURCETYPE srcType;
1094 D3DRESOURCETYPE dstType;
1096 ICOM_THIS(IDirect3DDevice8Impl,iface);
1097 TRACE("(%p) : first try\n", This);
1099 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1100 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1102 if (srcType != dstType) {
1103 return D3DERR_INVALIDCALL;
1105 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1106 return D3DERR_INVALIDCALL;
1108 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1109 return D3DERR_INVALIDCALL;
1111 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1112 /** Only copy Dirty textures */
1113 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1114 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1115 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1116 UINT i, j;
1118 for (i = skipLevels; i < srcLevelCnt; ++i) {
1119 HRESULT hr;
1121 switch (srcType) {
1122 case D3DRTYPE_TEXTURE:
1124 IDirect3DSurface8* srcSur = NULL;
1125 IDirect3DSurface8* dstSur = NULL;
1126 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1127 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1129 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1130 about dst with less levels than the source?) */
1131 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1133 IDirect3DSurface8Impl_Release(srcSur);
1134 IDirect3DSurface8Impl_Release(dstSur);
1136 break;
1137 case D3DRTYPE_VOLUMETEXTURE:
1139 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1141 break;
1142 case D3DRTYPE_CUBETEXTURE:
1144 IDirect3DSurface8* srcSur = NULL;
1145 IDirect3DSurface8* dstSur = NULL;
1146 for (j = 0; j < 5; ++j) {
1147 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1148 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1149 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1150 IDirect3DSurface8Impl_Release(srcSur);
1151 IDirect3DSurface8Impl_Release(dstSur);
1154 break;
1155 default:
1156 break;
1159 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1162 return D3D_OK;
1164 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1165 HRESULT hr;
1166 D3DLOCKED_RECT lockedRect;
1167 RECT wantedRect;
1168 GLint prev_store;
1169 GLenum prev_read;
1171 ICOM_THIS(IDirect3DDevice8Impl,iface);
1173 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1175 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1176 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1177 return D3DERR_INVALIDCALL;
1180 wantedRect.left = 0;
1181 wantedRect.top = 0;
1182 wantedRect.right = This->PresentParms.BackBufferWidth;
1183 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1185 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1186 if (FAILED(hr)) {
1187 ERR("(%p) : cannot lock surface\n", This);
1188 return D3DERR_INVALIDCALL;
1191 ENTER_GL();
1193 glFlush();
1194 vcheckGLcall("glFlush");
1195 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1196 vcheckGLcall("glIntegerv");
1197 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1198 vcheckGLcall("glIntegerv");
1200 glReadBuffer(GL_FRONT);
1201 vcheckGLcall("glReadBuffer");
1202 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1203 vcheckGLcall("glPixelStorei");
1204 /* stupid copy */
1206 long j;
1207 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1208 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1209 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1210 vcheckGLcall("glReadPixels");
1213 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1214 vcheckGLcall("glPixelStorei");
1215 glReadBuffer(prev_read);
1216 vcheckGLcall("glReadBuffer");
1218 LEAVE_GL();
1220 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1221 return hr;
1223 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1224 HRESULT hr = D3D_OK;
1225 D3DVIEWPORT8 viewport;
1227 ICOM_THIS(IDirect3DDevice8Impl,iface);
1229 /* If pRenderTarget == NULL, it seems to default to back buffer */
1230 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1232 /* For ease of code later on, handle a null depth as leave alone
1233 - Have not tested real d3d for this case but doing this avoids
1234 numerous null pointer checks */
1235 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1237 /* If we are trying to set what we already have, dont bother */
1238 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1239 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1240 } else {
1241 /* Otherwise, set the render target up */
1242 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1243 IDirect3DDevice8Impl_CleanRender(iface);
1244 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1247 if (SUCCEEDED(hr)) {
1248 /* Finally, reset the viewport as the MSDN states. */
1249 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1250 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1251 viewport.X = 0;
1252 viewport.Y = 0;
1253 viewport.MaxZ = 1.0f;
1254 viewport.MinZ = 0.0f;
1255 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1258 return hr;
1261 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1262 ICOM_THIS(IDirect3DDevice8Impl,iface);
1264 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1266 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1267 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1269 return D3D_OK;
1272 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1273 ICOM_THIS(IDirect3DDevice8Impl,iface);
1275 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1277 /* Note inc ref on returned surface */
1278 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1279 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1281 return D3D_OK;
1284 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1285 ICOM_THIS(IDirect3DDevice8Impl,iface);
1286 TRACE("(%p) : stub\n", This);
1287 return D3D_OK;
1290 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1291 IDirect3DBaseTexture8* cont = NULL;
1292 HRESULT hr;
1293 ICOM_THIS(IDirect3DDevice8Impl,iface);
1294 TRACE("(%p)\n", This);
1296 ENTER_GL();
1298 glFlush();
1299 checkGLcall("glFlush");
1301 #if 0 /* Useful for debugging sometimes! */
1302 printf("Hit Enter ...\n");
1303 getchar();
1304 #endif
1306 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1307 #if 0
1308 GLenum prev_read;
1309 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1310 vcheckGLcall("glIntegerv");
1311 glReadBuffer(GL_FRONT);
1312 vcheckGLcall("glReadBuffer");
1314 long j;
1315 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1317 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1318 pitch = pitch / 2;
1320 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1321 glReadPixels(0,
1322 This->renderTarget->myDesc.Height - j - 1,
1323 This->renderTarget->myDesc.Width,
1325 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1326 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1327 This->renderTarget->allocatedMemory + j * pitch);
1328 vcheckGLcall("glReadPixels");
1331 glReadBuffer(prev_read);
1332 vcheckGLcall("glReadBuffer");
1333 #endif
1335 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1336 if (SUCCEEDED(hr) && NULL != cont) {
1337 /** always dirtify for now. we must find a better way to see that surface have been modified */
1338 This->renderTarget->inPBuffer = TRUE;
1339 This->renderTarget->inTexture = FALSE;
1340 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1341 IDirect3DBaseTexture8_PreLoad(cont);
1342 This->renderTarget->inPBuffer = FALSE;
1343 IDirect3DBaseTexture8Impl_Release(cont);
1344 cont = NULL;
1348 LEAVE_GL();
1349 return D3D_OK;
1351 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1352 ICOM_THIS(IDirect3DDevice8Impl,iface);
1354 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1355 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1356 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1357 GLbitfield glMask = 0;
1358 GLboolean old_ztest;
1359 GLfloat old_z_clear_value;
1360 GLint old_stencil_clear_value;
1361 GLfloat old_color_clear_value[4];
1362 int i;
1363 CONST D3DRECT* curRect;
1365 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1366 Count, pRects, Flags, Z, Stencil);
1368 ENTER_GL();
1369 glEnable(GL_SCISSOR_TEST);
1370 checkGLcall("glEnable GL_SCISSOR_TEST");
1371 if (Count > 0 && pRects) {
1372 curRect = pRects;
1373 } else {
1374 curRect = NULL;
1377 /* Only set the values up once, as they are not changing */
1378 if (Flags & D3DCLEAR_STENCIL) {
1379 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1380 glClearStencil(Stencil);
1381 checkGLcall("glClearStencil");
1382 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1383 glStencilMask(0xFFFFFFFF);
1386 if (Flags & D3DCLEAR_ZBUFFER) {
1387 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1388 glDepthMask(GL_TRUE);
1389 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1390 glClearDepth(Z);
1391 checkGLcall("glClearDepth");
1392 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1395 if (Flags & D3DCLEAR_TARGET) {
1396 TRACE("Clearing screen with glClear to color %lx\n", Color);
1397 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1398 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1399 ((Color >> 8) & 0xFF) / 255.0f,
1400 ((Color >> 0) & 0xFF) / 255.0f,
1401 ((Color >> 24) & 0xFF) / 255.0f);
1402 checkGLcall("glClearColor");
1404 /* Clear ALL colors! */
1405 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1406 glMask = glMask | GL_COLOR_BUFFER_BIT;
1409 /* Now process each rect in turn */
1410 for (i = 0; i < Count || i == 0; i++) {
1412 if (curRect) {
1413 /* Note gl uses lower left, width/height */
1414 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1415 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1416 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1417 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1418 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1419 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1420 checkGLcall("glScissor");
1421 } else {
1422 glScissor(This->StateBlock->viewport.X,
1423 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1424 This->StateBlock->viewport.Width,
1425 This->StateBlock->viewport.Height);
1426 checkGLcall("glScissor");
1429 /* Clear the selected rectangle (or full screen) */
1430 glClear(glMask);
1431 checkGLcall("glClear");
1433 /* Step to the next rectangle */
1434 if (curRect) curRect = curRect + sizeof(D3DRECT);
1437 /* Restore the old values (why..?) */
1438 if (Flags & D3DCLEAR_STENCIL) {
1439 glClearStencil(old_stencil_clear_value);
1440 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1442 if (Flags & D3DCLEAR_ZBUFFER) {
1443 glDepthMask(old_ztest);
1444 glClearDepth(old_z_clear_value);
1446 if (Flags & D3DCLEAR_TARGET) {
1447 glClearColor(old_color_clear_value[0],
1448 old_color_clear_value[1],
1449 old_color_clear_value[2],
1450 old_color_clear_value[3]);
1451 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1452 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1453 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1454 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1457 glDisable(GL_SCISSOR_TEST);
1458 checkGLcall("glDisable");
1459 LEAVE_GL();
1461 return D3D_OK;
1463 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1464 ICOM_THIS(IDirect3DDevice8Impl,iface);
1465 int k;
1467 /* Most of this routine, comments included copied from ddraw tree initially: */
1468 TRACE("(%p) : State=%d\n", This, d3dts);
1470 /* Handle recording of state blocks */
1471 if (This->isRecordingState) {
1472 TRACE("Recording... not performing anything\n");
1473 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1474 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1475 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1476 return D3D_OK;
1480 * if the new matrix is the same as the current one,
1481 * we cut off any further processing. this seems to be a reasonable
1482 * optimization because as was noticed, some apps (warcraft3 for example)
1483 * tend towards setting the same matrix repeatedly for some dumb reason.
1485 * From here on we assume that the new matrix is different, wherever it matters
1486 * but note
1488 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1489 TRACE("The app is setting the same matrix over again\n");
1490 return D3D_OK;
1491 } else {
1492 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1496 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1497 where ViewMat = Camera space, WorldMat = world space.
1499 In OpenGL, camera and world space is combined into GL_MODELVIEW
1500 matrix. The Projection matrix stay projection matrix.
1503 /* Capture the times we can just ignore the change */
1504 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1505 This->modelview_valid = FALSE;
1506 return D3D_OK;
1508 } else if (d3dts == D3DTS_PROJECTION) {
1509 This->proj_valid = FALSE;
1510 return D3D_OK;
1512 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1513 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1514 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1515 return D3D_OK;
1518 /* Chances are we really are going to have to change a matrix */
1519 ENTER_GL();
1521 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1522 if (d3dts < GL_LIMITS(textures)) {
1523 int tex = d3dts - D3DTS_TEXTURE0;
1524 #if defined(GL_VERSION_1_3)
1525 glActiveTexture(GL_TEXTURE0 + tex);
1526 checkGLcall("glActiveTexture");
1527 #else
1528 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1529 checkGLcall("glActiveTextureARB");
1530 #endif
1531 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1534 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1536 PLIGHTINFOEL *lightChain = NULL;
1537 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1538 This->modelview_valid = FALSE;
1539 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1540 glMatrixMode(GL_MODELVIEW);
1541 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1542 glPushMatrix();
1543 glLoadMatrixf((float *)lpmatrix);
1544 checkGLcall("glLoadMatrixf(...)");
1546 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1547 * NOTE: We have to reset the positions even if the light/plane is not currently
1548 * enabled, since the call to enable it will not reset the position.
1549 * NOTE2: Apparently texture transforms do NOT need reapplying
1552 /* Reset lights */
1553 lightChain = This->StateBlock->lights;
1554 while (lightChain && lightChain->glIndex != -1) {
1555 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1556 checkGLcall("glLightfv posn");
1557 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1558 checkGLcall("glLightfv dirn");
1559 lightChain = lightChain->next;
1561 /* Reset Clipping Planes if clipping is enabled */
1562 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1563 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1564 checkGLcall("glClipPlane");
1566 glPopMatrix();
1568 } else { /* What was requested!?? */
1569 WARN("invalid matrix specified: %i\n", d3dts);
1573 /* Release lock, all done */
1574 LEAVE_GL();
1575 return D3D_OK;
1578 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1579 ICOM_THIS(IDirect3DDevice8Impl,iface);
1580 TRACE("(%p) : for State %d\n", This, State);
1581 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1582 return D3D_OK;
1585 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1586 D3DMATRIX *mat = NULL;
1587 D3DMATRIX temp;
1589 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1590 but works regardless of recording being on.
1591 If this is found to be wrong, change to StateBlock. */
1592 ICOM_THIS(IDirect3DDevice8Impl,iface);
1593 TRACE("(%p) : For state %u\n", This, State);
1595 if (State < HIGHEST_TRANSFORMSTATE)
1597 mat = &This->UpdateStateBlock->transforms[State];
1598 } else {
1599 FIXME("Unhandled transform state!!\n");
1602 /* Copied from ddraw code: */
1603 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);
1604 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);
1605 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);
1606 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);
1608 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);
1609 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);
1610 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);
1611 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);
1613 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);
1614 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);
1615 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);
1616 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);
1618 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);
1619 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);
1620 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);
1621 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);
1623 /* Apply change via set transform - will reapply to eg. lights this way */
1624 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1625 return D3D_OK;
1627 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1628 ICOM_THIS(IDirect3DDevice8Impl,iface);
1630 TRACE("(%p)\n", This);
1631 This->UpdateStateBlock->Changed.viewport = TRUE;
1632 This->UpdateStateBlock->Set.viewport = TRUE;
1633 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1635 /* Handle recording of state blocks */
1636 if (This->isRecordingState) {
1637 TRACE("Recording... not performing anything\n");
1638 return D3D_OK;
1641 ENTER_GL();
1643 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1644 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1646 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1647 checkGLcall("glDepthRange");
1648 /* Note: GL requires lower left, DirectX supplies upper left */
1649 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1650 pViewport->Width, pViewport->Height);
1651 checkGLcall("glViewport");
1653 LEAVE_GL();
1655 return D3D_OK;
1658 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1659 ICOM_THIS(IDirect3DDevice8Impl,iface);
1660 TRACE("(%p)\n", This);
1661 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1662 return D3D_OK;
1665 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1666 ICOM_THIS(IDirect3DDevice8Impl,iface);
1668 This->UpdateStateBlock->Changed.material = TRUE;
1669 This->UpdateStateBlock->Set.material = TRUE;
1670 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1672 /* Handle recording of state blocks */
1673 if (This->isRecordingState) {
1674 TRACE("Recording... not performing anything\n");
1675 return D3D_OK;
1678 ENTER_GL();
1679 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1680 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1681 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1682 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1683 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1685 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1686 checkGLcall("glMaterialfv");
1687 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1688 checkGLcall("glMaterialfv");
1690 /* Only change material color if specular is enabled, otherwise it is set to black */
1691 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1692 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1693 checkGLcall("glMaterialfv");
1694 } else {
1695 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1696 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1697 checkGLcall("glMaterialfv");
1699 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1700 checkGLcall("glMaterialfv");
1701 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1702 checkGLcall("glMaterialf");
1704 LEAVE_GL();
1705 return D3D_OK;
1707 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1708 ICOM_THIS(IDirect3DDevice8Impl,iface);
1709 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1710 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1711 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1712 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1713 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1714 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1715 return D3D_OK;
1718 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1719 you can reference any indexes you want as long as that number max are enabled are any
1720 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1721 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1722 but when recording, just build a chain pretty much of commands to be replayed. */
1724 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1725 float rho;
1726 PLIGHTINFOEL *object, *temp;
1728 ICOM_THIS(IDirect3DDevice8Impl,iface);
1729 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1731 /* If recording state block, just add to end of lights chain */
1732 if (This->isRecordingState) {
1733 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1734 if (NULL == object) {
1735 return D3DERR_OUTOFVIDEOMEMORY;
1737 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1738 object->OriginalIndex = Index;
1739 object->glIndex = -1;
1740 object->changed = TRUE;
1742 /* Add to the END of the chain of lights changes to be replayed */
1743 if (This->UpdateStateBlock->lights == NULL) {
1744 This->UpdateStateBlock->lights = object;
1745 } else {
1746 temp = This->UpdateStateBlock->lights;
1747 while (temp->next != NULL) temp=temp->next;
1748 temp->next = object;
1750 TRACE("Recording... not performing anything more\n");
1751 return D3D_OK;
1754 /* Ok, not recording any longer so do real work */
1755 object = This->StateBlock->lights;
1756 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1758 /* If we didn't find it in the list of lights, time to add it */
1759 if (object == NULL) {
1760 PLIGHTINFOEL *insertAt,*prevPos;
1762 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1763 if (NULL == object) {
1764 return D3DERR_OUTOFVIDEOMEMORY;
1766 object->OriginalIndex = Index;
1767 object->glIndex = -1;
1769 /* Add it to the front of list with the idea that lights will be changed as needed
1770 BUT after any lights currently assigned GL indexes */
1771 insertAt = This->StateBlock->lights;
1772 prevPos = NULL;
1773 while (insertAt != NULL && insertAt->glIndex != -1) {
1774 prevPos = insertAt;
1775 insertAt = insertAt->next;
1778 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1779 This->StateBlock->lights = object;
1780 } else if (insertAt == NULL) { /* End of list */
1781 prevPos->next = object;
1782 object->prev = prevPos;
1783 } else { /* Middle of chain */
1784 if (prevPos == NULL) {
1785 This->StateBlock->lights = object;
1786 } else {
1787 prevPos->next = object;
1789 object->prev = prevPos;
1790 object->next = insertAt;
1791 insertAt->prev = object;
1795 /* Initialze the object */
1796 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,
1797 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1798 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1799 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1800 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1801 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1802 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1804 /* Save away the information */
1805 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1807 switch (pLight->Type) {
1808 case D3DLIGHT_POINT:
1809 /* Position */
1810 object->lightPosn[0] = pLight->Position.x;
1811 object->lightPosn[1] = pLight->Position.y;
1812 object->lightPosn[2] = pLight->Position.z;
1813 object->lightPosn[3] = 1.0f;
1814 object->cutoff = 180.0f;
1815 /* FIXME: Range */
1816 break;
1818 case D3DLIGHT_DIRECTIONAL:
1819 /* Direction */
1820 object->lightPosn[0] = -pLight->Direction.x;
1821 object->lightPosn[1] = -pLight->Direction.y;
1822 object->lightPosn[2] = -pLight->Direction.z;
1823 object->lightPosn[3] = 0.0;
1824 object->exponent = 0.0f;
1825 object->cutoff = 180.0f;
1826 break;
1828 case D3DLIGHT_SPOT:
1829 /* Position */
1830 object->lightPosn[0] = pLight->Position.x;
1831 object->lightPosn[1] = pLight->Position.y;
1832 object->lightPosn[2] = pLight->Position.z;
1833 object->lightPosn[3] = 1.0;
1835 /* Direction */
1836 object->lightDirn[0] = pLight->Direction.x;
1837 object->lightDirn[1] = pLight->Direction.y;
1838 object->lightDirn[2] = pLight->Direction.z;
1839 object->lightDirn[3] = 1.0;
1842 * opengl-ish and d3d-ish spot lights use too different models for the
1843 * light "intensity" as a function of the angle towards the main light direction,
1844 * so we only can approximate very roughly.
1845 * however spot lights are rather rarely used in games (if ever used at all).
1846 * furthermore if still used, probably nobody pays attention to such details.
1848 if (pLight->Falloff == 0) {
1849 rho = 6.28f;
1850 } else {
1851 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1853 if (rho < 0.0001) rho = 0.0001f;
1854 object->exponent = -0.3/log(cos(rho/2));
1855 object->cutoff = pLight->Phi*90/M_PI;
1857 /* FIXME: Range */
1858 break;
1860 default:
1861 FIXME("Unrecognized light type %d\n", pLight->Type);
1864 /* Update the live definitions if the light is currently assigned a glIndex */
1865 if (object->glIndex != -1) {
1866 setup_light(iface, object->glIndex, object);
1868 return D3D_OK;
1870 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1871 PLIGHTINFOEL *lightInfo = NULL;
1872 ICOM_THIS(IDirect3DDevice8Impl,iface);
1873 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1875 /* Locate the light in the live lights */
1876 lightInfo = This->StateBlock->lights;
1877 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1879 if (lightInfo == NULL) {
1880 TRACE("Light information requested but light not defined\n");
1881 return D3DERR_INVALIDCALL;
1884 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1885 return D3D_OK;
1887 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1888 PLIGHTINFOEL *lightInfo = NULL;
1889 ICOM_THIS(IDirect3DDevice8Impl,iface);
1890 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1892 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1893 if (This->isRecordingState) {
1894 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1895 if (NULL == lightInfo) {
1896 return D3DERR_OUTOFVIDEOMEMORY;
1898 lightInfo->OriginalIndex = Index;
1899 lightInfo->glIndex = -1;
1900 lightInfo->enabledChanged = TRUE;
1902 /* Add to the END of the chain of lights changes to be replayed */
1903 if (This->UpdateStateBlock->lights == NULL) {
1904 This->UpdateStateBlock->lights = lightInfo;
1905 } else {
1906 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1907 while (temp->next != NULL) temp=temp->next;
1908 temp->next = lightInfo;
1910 TRACE("Recording... not performing anything more\n");
1911 return D3D_OK;
1914 /* Not recording... So, locate the light in the live lights */
1915 lightInfo = This->StateBlock->lights;
1916 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1918 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1919 if (lightInfo == NULL) {
1920 D3DLIGHT8 lightParms;
1921 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1922 wait until someone confirms it seems to work! */
1923 TRACE("Light enabled requested but light not defined, so defining one!\n");
1924 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1925 lightParms.Diffuse.r = 1.0;
1926 lightParms.Diffuse.g = 1.0;
1927 lightParms.Diffuse.b = 1.0;
1928 lightParms.Diffuse.a = 0.0;
1929 lightParms.Specular.r = 0.0;
1930 lightParms.Specular.g = 0.0;
1931 lightParms.Specular.b = 0.0;
1932 lightParms.Specular.a = 0.0;
1933 lightParms.Ambient.r = 0.0;
1934 lightParms.Ambient.g = 0.0;
1935 lightParms.Ambient.b = 0.0;
1936 lightParms.Ambient.a = 0.0;
1937 lightParms.Position.x = 0.0;
1938 lightParms.Position.y = 0.0;
1939 lightParms.Position.z = 0.0;
1940 lightParms.Direction.x = 0.0;
1941 lightParms.Direction.y = 0.0;
1942 lightParms.Direction.z = 1.0;
1943 lightParms.Range = 0.0;
1944 lightParms.Falloff = 0.0;
1945 lightParms.Attenuation0 = 0.0;
1946 lightParms.Attenuation1 = 0.0;
1947 lightParms.Attenuation2 = 0.0;
1948 lightParms.Theta = 0.0;
1949 lightParms.Phi = 0.0;
1950 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1952 /* Search for it again! Should be fairly quick as near head of list */
1953 lightInfo = This->StateBlock->lights;
1954 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1955 if (lightInfo == NULL) {
1956 FIXME("Adding default lights has failed dismally\n");
1957 return D3DERR_INVALIDCALL;
1961 /* OK, we now have a light... */
1962 if (Enable == FALSE) {
1964 /* If we are disabling it, check it was enabled, and
1965 still only do something if it has assigned a glIndex (which it should have!) */
1966 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1967 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1968 ENTER_GL();
1969 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1970 checkGLcall("glDisable GL_LIGHT0+Index");
1971 LEAVE_GL();
1972 } else {
1973 TRACE("Nothing to do as light was not enabled\n");
1975 lightInfo->lightEnabled = FALSE;
1976 } else {
1978 /* We are enabling it. If it is enabled, its really simple */
1979 if (lightInfo->lightEnabled == TRUE) {
1980 /* nop */
1981 TRACE("Nothing to do as light was enabled\n");
1983 /* If it already has a glIndex, its still simple */
1984 } else if (lightInfo->glIndex != -1) {
1985 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1986 lightInfo->lightEnabled = TRUE;
1987 ENTER_GL();
1988 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1989 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1990 LEAVE_GL();
1992 /* Otherwise got to find space - lights are ordered gl indexes first */
1993 } else {
1994 PLIGHTINFOEL *bsf = NULL;
1995 PLIGHTINFOEL *pos = This->StateBlock->lights;
1996 PLIGHTINFOEL *prev = NULL;
1997 int Index= 0;
1998 int glIndex = -1;
2000 /* Try to minimize changes as much as possible */
2001 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2003 /* Try to remember which index can be replaced if necessary */
2004 if (bsf==NULL && pos->lightEnabled == FALSE) {
2005 /* Found a light we can replace, save as best replacement */
2006 bsf = pos;
2009 /* Step to next space */
2010 prev = pos;
2011 pos = pos->next;
2012 Index ++;
2015 /* If we have too many active lights, fail the call */
2016 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2017 FIXME("Program requests too many concurrent lights\n");
2018 return D3DERR_INVALIDCALL;
2020 /* If we have allocated all lights, but not all are enabled,
2021 reuse one which is not enabled */
2022 } else if (Index == This->maxConcurrentLights) {
2023 /* use bsf - Simply swap the new light and the BSF one */
2024 PLIGHTINFOEL *bsfNext = bsf->next;
2025 PLIGHTINFOEL *bsfPrev = bsf->prev;
2027 /* Sort out ends */
2028 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2029 if (bsf->prev != NULL) {
2030 bsf->prev->next = lightInfo;
2031 } else {
2032 This->StateBlock->lights = lightInfo;
2035 /* If not side by side, lots of chains to update */
2036 if (bsf->next != lightInfo) {
2037 lightInfo->prev->next = bsf;
2038 bsf->next->prev = lightInfo;
2039 bsf->next = lightInfo->next;
2040 bsf->prev = lightInfo->prev;
2041 lightInfo->next = bsfNext;
2042 lightInfo->prev = bsfPrev;
2044 } else {
2045 /* Simple swaps */
2046 bsf->prev = lightInfo;
2047 bsf->next = lightInfo->next;
2048 lightInfo->next = bsf;
2049 lightInfo->prev = bsfPrev;
2053 /* Update states */
2054 glIndex = bsf->glIndex;
2055 bsf->glIndex = -1;
2056 lightInfo->glIndex = glIndex;
2057 lightInfo->lightEnabled = TRUE;
2059 /* Finally set up the light in gl itself */
2060 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2061 ENTER_GL();
2062 setup_light(iface, glIndex, lightInfo);
2063 glEnable(GL_LIGHT0 + glIndex);
2064 checkGLcall("glEnable GL_LIGHT0 new setup");
2065 LEAVE_GL();
2067 /* If we reached the end of the allocated lights, with space in the
2068 gl lights, setup a new light */
2069 } else if (pos->glIndex == -1) {
2071 /* We reached the end of the allocated gl lights, so already
2072 know the index of the next one! */
2073 glIndex = Index;
2074 lightInfo->glIndex = glIndex;
2075 lightInfo->lightEnabled = TRUE;
2077 /* In an ideal world, its already in the right place */
2078 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2079 /* No need to move it */
2080 } else {
2081 /* Remove this light from the list */
2082 lightInfo->prev->next = lightInfo->next;
2083 if (lightInfo->next != NULL) {
2084 lightInfo->next->prev = lightInfo->prev;
2087 /* Add in at appropriate place (inbetween prev and pos) */
2088 lightInfo->prev = prev;
2089 lightInfo->next = pos;
2090 if (prev == NULL) {
2091 This->StateBlock->lights = lightInfo;
2092 } else {
2093 prev->next = lightInfo;
2095 if (pos != NULL) {
2096 pos->prev = lightInfo;
2100 /* Finally set up the light in gl itself */
2101 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2102 ENTER_GL();
2103 setup_light(iface, glIndex, lightInfo);
2104 glEnable(GL_LIGHT0 + glIndex);
2105 checkGLcall("glEnable GL_LIGHT0 new setup");
2106 LEAVE_GL();
2111 return D3D_OK;
2113 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2115 PLIGHTINFOEL *lightInfo = NULL;
2116 ICOM_THIS(IDirect3DDevice8Impl,iface);
2117 TRACE("(%p) : for idx(%ld)\n", This, Index);
2119 /* Locate the light in the live lights */
2120 lightInfo = This->StateBlock->lights;
2121 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2123 if (lightInfo == NULL) {
2124 TRACE("Light enabled state requested but light not defined\n");
2125 return D3DERR_INVALIDCALL;
2127 *pEnable = lightInfo->lightEnabled;
2128 return D3D_OK;
2130 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2131 ICOM_THIS(IDirect3DDevice8Impl,iface);
2132 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2134 /* Validate Index */
2135 if (Index >= GL_LIMITS(clipplanes)) {
2136 TRACE("Application has requested clipplane this device doesn't support\n");
2137 return D3DERR_INVALIDCALL;
2140 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2141 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2142 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2143 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2144 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2145 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2147 /* Handle recording of state blocks */
2148 if (This->isRecordingState) {
2149 TRACE("Recording... not performing anything\n");
2150 return D3D_OK;
2153 /* Apply it */
2155 ENTER_GL();
2157 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2158 glMatrixMode(GL_MODELVIEW);
2159 glPushMatrix();
2160 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2162 TRACE("Clipplane [%f,%f,%f,%f]\n",
2163 This->UpdateStateBlock->clipplane[Index][0],
2164 This->UpdateStateBlock->clipplane[Index][1],
2165 This->UpdateStateBlock->clipplane[Index][2],
2166 This->UpdateStateBlock->clipplane[Index][3]);
2167 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2168 checkGLcall("glClipPlane");
2170 glPopMatrix();
2172 LEAVE_GL();
2174 return D3D_OK;
2176 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2177 ICOM_THIS(IDirect3DDevice8Impl,iface);
2178 TRACE("(%p) : for idx %ld\n", This, Index);
2180 /* Validate Index */
2181 if (Index >= GL_LIMITS(clipplanes)) {
2182 TRACE("Application has requested clipplane this device doesn't support\n");
2183 return D3DERR_INVALIDCALL;
2186 pPlane[0] = This->StateBlock->clipplane[Index][0];
2187 pPlane[1] = This->StateBlock->clipplane[Index][1];
2188 pPlane[2] = This->StateBlock->clipplane[Index][2];
2189 pPlane[3] = This->StateBlock->clipplane[Index][3];
2190 return D3D_OK;
2192 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2193 union {
2194 DWORD d;
2195 float f;
2196 } tmpvalue;
2197 ICOM_THIS(IDirect3DDevice8Impl,iface);
2198 DWORD OldValue = This->StateBlock->renderstate[State];
2200 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2201 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2202 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2203 This->UpdateStateBlock->renderstate[State] = Value;
2205 /* Handle recording of state blocks */
2206 if (This->isRecordingState) {
2207 TRACE("Recording... not performing anything\n");
2208 return D3D_OK;
2211 ENTER_GL();
2213 switch (State) {
2214 case D3DRS_FILLMODE :
2215 switch ((D3DFILLMODE) Value) {
2216 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2217 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2218 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2219 default:
2220 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2222 checkGLcall("glPolygonMode (fillmode)");
2223 break;
2225 case D3DRS_LIGHTING :
2226 if (Value) {
2227 glEnable(GL_LIGHTING);
2228 checkGLcall("glEnable GL_LIGHTING");
2229 } else {
2230 glDisable(GL_LIGHTING);
2231 checkGLcall("glDisable GL_LIGHTING");
2233 break;
2235 case D3DRS_ZENABLE :
2236 switch ((D3DZBUFFERTYPE) Value) {
2237 case D3DZB_FALSE:
2238 glDisable(GL_DEPTH_TEST);
2239 checkGLcall("glDisable GL_DEPTH_TEST");
2240 break;
2241 case D3DZB_TRUE:
2242 glEnable(GL_DEPTH_TEST);
2243 checkGLcall("glEnable GL_DEPTH_TEST");
2244 break;
2246 case D3DZB_USEW:
2247 default:
2248 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2250 break;
2252 case D3DRS_CULLMODE :
2254 /* If we are culling "back faces with clockwise vertices" then
2255 set front faces to be counter clockwise and enable culling
2256 of back faces */
2257 switch ((D3DCULL) Value) {
2258 case D3DCULL_NONE:
2259 glDisable(GL_CULL_FACE);
2260 checkGLcall("glDisable GL_CULL_FACE");
2261 break;
2262 case D3DCULL_CW:
2263 glEnable(GL_CULL_FACE);
2264 checkGLcall("glEnable GL_CULL_FACE");
2265 if (This->renderUpsideDown) {
2266 glFrontFace(GL_CW);
2267 checkGLcall("glFrontFace GL_CW");
2268 } else {
2269 glFrontFace(GL_CCW);
2270 checkGLcall("glFrontFace GL_CCW");
2272 glCullFace(GL_BACK);
2273 break;
2274 case D3DCULL_CCW:
2275 glEnable(GL_CULL_FACE);
2276 checkGLcall("glEnable GL_CULL_FACE");
2277 if (This->renderUpsideDown) {
2278 glFrontFace(GL_CCW);
2279 checkGLcall("glFrontFace GL_CCW");
2280 } else {
2281 glFrontFace(GL_CW);
2282 checkGLcall("glFrontFace GL_CW");
2284 glCullFace(GL_BACK);
2285 break;
2286 default:
2287 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2289 break;
2291 case D3DRS_SHADEMODE :
2292 switch ((D3DSHADEMODE) Value) {
2293 case D3DSHADE_FLAT:
2294 glShadeModel(GL_FLAT);
2295 checkGLcall("glShadeModel");
2296 break;
2297 case D3DSHADE_GOURAUD:
2298 glShadeModel(GL_SMOOTH);
2299 checkGLcall("glShadeModel");
2300 break;
2301 case D3DSHADE_PHONG:
2302 FIXME("D3DSHADE_PHONG isn't supported?\n");
2304 LEAVE_GL();
2305 return D3DERR_INVALIDCALL;
2306 default:
2307 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2309 break;
2311 case D3DRS_DITHERENABLE :
2312 if (Value) {
2313 glEnable(GL_DITHER);
2314 checkGLcall("glEnable GL_DITHER");
2315 } else {
2316 glDisable(GL_DITHER);
2317 checkGLcall("glDisable GL_DITHER");
2319 break;
2321 case D3DRS_ZWRITEENABLE :
2322 if (Value) {
2323 glDepthMask(1);
2324 checkGLcall("glDepthMask");
2325 } else {
2326 glDepthMask(0);
2327 checkGLcall("glDepthMask");
2329 break;
2331 case D3DRS_ZFUNC :
2333 int glParm = GL_LESS;
2335 switch ((D3DCMPFUNC) Value) {
2336 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2337 case D3DCMP_LESS: glParm=GL_LESS; break;
2338 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2339 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2340 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2341 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2342 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2343 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2344 default:
2345 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2347 glDepthFunc(glParm);
2348 checkGLcall("glDepthFunc");
2350 break;
2352 case D3DRS_AMBIENT :
2354 float col[4];
2355 D3DCOLORTOGLFLOAT4(Value, col);
2356 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2357 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2358 checkGLcall("glLightModel for MODEL_AMBIENT");
2361 break;
2363 case D3DRS_ALPHABLENDENABLE :
2364 if (Value) {
2365 glEnable(GL_BLEND);
2366 checkGLcall("glEnable GL_BLEND");
2367 } else {
2368 glDisable(GL_BLEND);
2369 checkGLcall("glDisable GL_BLEND");
2371 break;
2373 case D3DRS_SRCBLEND :
2374 case D3DRS_DESTBLEND :
2376 int newVal = GL_ZERO;
2377 switch (Value) {
2378 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2379 case D3DBLEND_ONE : newVal = GL_ONE; break;
2380 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2381 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2382 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2383 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2384 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2385 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2386 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2387 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2388 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2390 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2391 This->srcBlend = newVal;
2392 This->dstBlend = newVal;
2393 break;
2395 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2396 This->srcBlend = newVal;
2397 This->dstBlend = newVal;
2398 break;
2399 default:
2400 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2403 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2404 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2405 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2406 glBlendFunc(This->srcBlend, This->dstBlend);
2408 checkGLcall("glBlendFunc");
2410 break;
2412 case D3DRS_ALPHATESTENABLE :
2413 if (Value) {
2414 glEnable(GL_ALPHA_TEST);
2415 checkGLcall("glEnable GL_ALPHA_TEST");
2416 } else {
2417 glDisable(GL_ALPHA_TEST);
2418 checkGLcall("glDisable GL_ALPHA_TEST");
2420 break;
2422 case D3DRS_ALPHAFUNC :
2424 int glParm = GL_LESS;
2425 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2427 switch ((D3DCMPFUNC) Value) {
2428 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2429 case D3DCMP_LESS: glParm = GL_LESS; break;
2430 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2431 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2432 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2433 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2434 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2435 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2436 default:
2437 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2439 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2440 glAlphaFunc(glParm, ref);
2441 This->alphafunc = glParm;
2442 checkGLcall("glAlphaFunc");
2444 break;
2446 case D3DRS_ALPHAREF :
2448 int glParm = This->alphafunc;
2449 float ref = 1.0f;
2451 ref = ((float) Value) / 255.0f;
2452 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2453 glAlphaFunc(glParm, ref);
2454 checkGLcall("glAlphaFunc");
2456 break;
2458 case D3DRS_CLIPPLANEENABLE :
2459 case D3DRS_CLIPPING :
2461 /* Ensure we only do the changed clip planes */
2462 DWORD enable = 0xFFFFFFFF;
2463 DWORD disable = 0x00000000;
2465 /* If enabling / disabling all */
2466 if (State == D3DRS_CLIPPING) {
2467 if (Value) {
2468 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2469 disable = 0x00;
2470 } else {
2471 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2472 enable = 0x00;
2474 } else {
2475 enable = Value & ~OldValue;
2476 disable = ~Value & OldValue;
2479 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2480 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2481 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2482 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2483 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2484 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2486 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2487 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2488 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2489 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2490 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2491 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2493 break;
2495 case D3DRS_BLENDOP :
2497 int glParm = GL_FUNC_ADD;
2499 switch ((D3DBLENDOP) Value) {
2500 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2501 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2502 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2503 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2504 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2505 default:
2506 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2508 TRACE("glBlendEquation(%x)\n", glParm);
2509 glBlendEquation(glParm);
2510 checkGLcall("glBlendEquation");
2512 break;
2514 case D3DRS_TEXTUREFACTOR :
2516 int i;
2518 /* Note the texture color applies to all textures whereas
2519 GL_TEXTURE_ENV_COLOR applies to active only */
2520 float col[4];
2521 D3DCOLORTOGLFLOAT4(Value, col);
2522 /* Set the default alpha blend color */
2523 glBlendColor(col[0], col[1], col[2], col[3]);
2524 checkGLcall("glBlendColor");
2526 /* And now the default texture color as well */
2527 for (i = 0; i < GL_LIMITS(textures); i++) {
2529 /* Note the D3DRS value applies to all textures, but GL has one
2530 per texture, so apply it now ready to be used! */
2531 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2532 #if defined(GL_VERSION_1_3)
2533 glActiveTexture(GL_TEXTURE0 + i);
2534 #else
2535 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2536 #endif
2537 checkGLcall("Activate texture.. to update const color");
2538 } else if (i>0) {
2539 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2542 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2543 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2546 break;
2548 case D3DRS_SPECULARENABLE :
2550 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2551 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2552 specular color. This is wrong:
2553 Separate specular color means the specular colour is maintained separately, whereas
2554 single color means it is merged in. However in both cases they are being used to
2555 some extent.
2556 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2557 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2558 running 1.4 yet!
2560 if (Value) {
2561 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2562 checkGLcall("glMaterialfv");
2563 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2564 glEnable(GL_COLOR_SUM_EXT);
2565 } else {
2566 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2568 checkGLcall("glEnable(GL_COLOR_SUM)");
2569 } else {
2570 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2572 /* for the case of enabled lighting: */
2573 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2574 checkGLcall("glMaterialfv");
2576 /* for the case of disabled lighting: */
2577 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2578 glDisable(GL_COLOR_SUM_EXT);
2579 } else {
2580 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2582 checkGLcall("glDisable(GL_COLOR_SUM)");
2585 break;
2587 case D3DRS_STENCILENABLE :
2588 if (Value) {
2589 glEnable(GL_STENCIL_TEST);
2590 checkGLcall("glEnable GL_STENCIL_TEST");
2591 } else {
2592 glDisable(GL_STENCIL_TEST);
2593 checkGLcall("glDisable GL_STENCIL_TEST");
2595 break;
2597 case D3DRS_STENCILFUNC :
2599 int glParm = GL_ALWAYS;
2600 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2601 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2603 switch ((D3DCMPFUNC) Value) {
2604 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2605 case D3DCMP_LESS: glParm=GL_LESS; break;
2606 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2607 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2608 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2609 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2610 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2611 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2612 default:
2613 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2615 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2616 This->stencilfunc = glParm;
2617 glStencilFunc(glParm, ref, mask);
2618 checkGLcall("glStencilFunc");
2620 break;
2622 case D3DRS_STENCILREF :
2624 int glParm = This->stencilfunc;
2625 int ref = 0;
2626 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2628 ref = Value;
2629 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2630 glStencilFunc(glParm, ref, mask);
2631 checkGLcall("glStencilFunc");
2633 break;
2635 case D3DRS_STENCILMASK :
2637 int glParm = This->stencilfunc;
2638 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2639 GLuint mask = Value;
2641 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2642 glStencilFunc(glParm, ref, mask);
2643 checkGLcall("glStencilFunc");
2645 break;
2647 case D3DRS_STENCILFAIL :
2649 GLenum fail ;
2650 GLenum zpass ;
2651 GLenum zfail ;
2653 fail = StencilOp(Value);
2654 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2655 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2656 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2657 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2659 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2660 glStencilOp(fail, zfail, zpass);
2661 checkGLcall("glStencilOp(fail, zfail, zpass);");
2663 break;
2664 case D3DRS_STENCILZFAIL :
2666 GLenum fail ;
2667 GLenum zpass ;
2668 GLenum zfail ;
2670 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2671 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2672 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2673 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2674 zfail = StencilOp(Value);
2676 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2677 glStencilOp(fail, zfail, zpass);
2678 checkGLcall("glStencilOp(fail, zfail, zpass);");
2680 break;
2681 case D3DRS_STENCILPASS :
2683 GLenum fail ;
2684 GLenum zpass ;
2685 GLenum zfail ;
2687 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2688 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2689 zpass = StencilOp(Value);
2690 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2691 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2693 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2694 glStencilOp(fail, zfail, zpass);
2695 checkGLcall("glStencilOp(fail, zfail, zpass);");
2697 break;
2699 case D3DRS_STENCILWRITEMASK :
2701 glStencilMask(Value);
2702 TRACE("glStencilMask(%lu)\n", Value);
2703 checkGLcall("glStencilMask");
2705 break;
2707 case D3DRS_FOGENABLE :
2709 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2710 glEnable(GL_FOG);
2711 checkGLcall("glEnable GL_FOG");
2712 } else {
2713 glDisable(GL_FOG);
2714 checkGLcall("glDisable GL_FOG");
2717 break;
2719 case D3DRS_RANGEFOGENABLE :
2721 if (Value) {
2722 TRACE("Enabled RANGEFOG");
2723 } else {
2724 TRACE("Disabled RANGEFOG");
2727 break;
2729 case D3DRS_FOGCOLOR :
2731 float col[4];
2732 D3DCOLORTOGLFLOAT4(Value, col);
2733 /* Set the default alpha blend color */
2734 glFogfv(GL_FOG_COLOR, &col[0]);
2735 checkGLcall("glFog GL_FOG_COLOR");
2737 break;
2739 case D3DRS_FOGTABLEMODE :
2741 glHint(GL_FOG_HINT, GL_NICEST);
2742 switch (Value) {
2743 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2744 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2745 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2746 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2747 default:
2748 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2750 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2751 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2754 break;
2756 case D3DRS_FOGVERTEXMODE :
2758 glHint(GL_FOG_HINT, GL_FASTEST);
2759 switch (Value) {
2760 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2761 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2762 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2763 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2764 default:
2765 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2767 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2768 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2771 break;
2773 case D3DRS_FOGSTART :
2775 tmpvalue.d = Value;
2776 glFogfv(GL_FOG_START, &tmpvalue.f);
2777 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2778 TRACE("Fog Start == %f\n", tmpvalue.f);
2780 break;
2782 case D3DRS_FOGEND :
2784 tmpvalue.d = Value;
2785 glFogfv(GL_FOG_END, &tmpvalue.f);
2786 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2787 TRACE("Fog End == %f\n", tmpvalue.f);
2789 break;
2791 case D3DRS_FOGDENSITY :
2793 tmpvalue.d = Value;
2794 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2795 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2797 break;
2799 case D3DRS_VERTEXBLEND :
2801 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2802 TRACE("Vertex Blending state to %ld\n", Value);
2804 break;
2806 case D3DRS_TWEENFACTOR :
2808 tmpvalue.d = Value;
2809 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2810 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2812 break;
2814 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2816 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2818 break;
2820 case D3DRS_COLORVERTEX :
2821 case D3DRS_DIFFUSEMATERIALSOURCE :
2822 case D3DRS_SPECULARMATERIALSOURCE :
2823 case D3DRS_AMBIENTMATERIALSOURCE :
2824 case D3DRS_EMISSIVEMATERIALSOURCE :
2826 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2828 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2829 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2830 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2831 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2832 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2833 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2835 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2836 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2837 Parm = GL_AMBIENT_AND_DIFFUSE;
2838 } else {
2839 Parm = GL_DIFFUSE;
2841 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2842 Parm = GL_AMBIENT;
2843 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2844 Parm = GL_EMISSION;
2845 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2846 Parm = GL_SPECULAR;
2847 } else {
2848 Parm = -1;
2851 if (Parm == -1) {
2852 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2853 } else {
2854 This->tracking_color = NEEDS_TRACKING;
2855 This->tracking_parm = Parm;
2858 } else {
2859 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2862 break;
2864 case D3DRS_LINEPATTERN :
2866 union {
2867 DWORD d;
2868 D3DLINEPATTERN lp;
2869 } tmppattern;
2870 tmppattern.d = Value;
2872 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2874 if (tmppattern.lp.wRepeatFactor) {
2875 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2876 checkGLcall("glLineStipple(repeat, linepattern)");
2877 glEnable(GL_LINE_STIPPLE);
2878 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2879 } else {
2880 glDisable(GL_LINE_STIPPLE);
2881 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2884 break;
2886 case D3DRS_ZBIAS :
2888 if (Value) {
2889 tmpvalue.d = Value;
2890 TRACE("ZBias value %f\n", tmpvalue.f);
2891 glPolygonOffset(0, -tmpvalue.f);
2892 checkGLcall("glPolygonOffset(0, -Value)");
2893 glEnable(GL_POLYGON_OFFSET_FILL);
2894 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2895 glEnable(GL_POLYGON_OFFSET_LINE);
2896 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2897 glEnable(GL_POLYGON_OFFSET_POINT);
2898 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2899 } else {
2900 glDisable(GL_POLYGON_OFFSET_FILL);
2901 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2902 glDisable(GL_POLYGON_OFFSET_LINE);
2903 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2904 glDisable(GL_POLYGON_OFFSET_POINT);
2905 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2908 break;
2910 case D3DRS_NORMALIZENORMALS :
2911 if (Value) {
2912 glEnable(GL_NORMALIZE);
2913 checkGLcall("glEnable(GL_NORMALIZE);");
2914 } else {
2915 glDisable(GL_NORMALIZE);
2916 checkGLcall("glDisable(GL_NORMALIZE);");
2918 break;
2920 case D3DRS_POINTSIZE :
2921 tmpvalue.d = Value;
2922 TRACE("Set point size to %f\n", tmpvalue.f);
2923 glPointSize(tmpvalue.f);
2924 checkGLcall("glPointSize(...);");
2925 break;
2927 case D3DRS_POINTSIZE_MIN :
2928 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2929 tmpvalue.d = Value;
2930 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2931 checkGLcall("glPointParameterfEXT(...);");
2932 } else {
2933 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2935 break;
2937 case D3DRS_POINTSIZE_MAX :
2938 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2939 tmpvalue.d = Value;
2940 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2941 checkGLcall("glPointParameterfEXT(...);");
2942 } else {
2943 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2945 break;
2947 case D3DRS_POINTSCALE_A :
2948 case D3DRS_POINTSCALE_B :
2949 case D3DRS_POINTSCALE_C :
2950 case D3DRS_POINTSCALEENABLE :
2952 /* If enabled, supply the parameters, otherwise fall back to defaults */
2953 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2954 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2955 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2956 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2957 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2959 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2960 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2961 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2962 } else {
2963 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2965 } else {
2966 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2967 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2968 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2969 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2970 } else {
2971 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2974 break;
2977 case D3DRS_COLORWRITEENABLE :
2979 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2980 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2981 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2982 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2983 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2984 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2985 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2986 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2987 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2988 checkGLcall("glColorMask(...)");
2990 break;
2992 case D3DRS_LOCALVIEWER :
2994 GLint state = (Value) ? 1 : 0;
2995 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
2996 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2998 break;
3000 /* Unhandled yet...! */
3001 case D3DRS_LASTPIXEL :
3002 case D3DRS_ZVISIBLE :
3003 case D3DRS_EDGEANTIALIAS :
3004 case D3DRS_WRAP0 :
3005 case D3DRS_WRAP1 :
3006 case D3DRS_WRAP2 :
3007 case D3DRS_WRAP3 :
3008 case D3DRS_WRAP4 :
3009 case D3DRS_WRAP5 :
3010 case D3DRS_WRAP6 :
3011 case D3DRS_WRAP7 :
3012 case D3DRS_SOFTWAREVERTEXPROCESSING :
3013 case D3DRS_POINTSPRITEENABLE :
3014 case D3DRS_MULTISAMPLEANTIALIAS :
3015 case D3DRS_MULTISAMPLEMASK :
3016 case D3DRS_PATCHEDGESTYLE :
3017 case D3DRS_PATCHSEGMENTS :
3018 case D3DRS_DEBUGMONITORTOKEN :
3019 case D3DRS_POSITIONORDER :
3020 case D3DRS_NORMALORDER :
3021 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3022 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3023 break;
3024 default:
3025 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3028 LEAVE_GL();
3030 return D3D_OK;
3032 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3033 ICOM_THIS(IDirect3DDevice8Impl,iface);
3034 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3035 *pValue = This->StateBlock->renderstate[State];
3036 return D3D_OK;
3038 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3039 ICOM_THIS(IDirect3DDevice8Impl,iface);
3041 TRACE("(%p)\n", This);
3043 return IDirect3DDeviceImpl_BeginStateBlock(This);
3045 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3046 IDirect3DStateBlockImpl* pSB;
3047 ICOM_THIS(IDirect3DDevice8Impl,iface);
3048 HRESULT res;
3050 TRACE("(%p)\n", This);
3052 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3053 *pToken = (DWORD) pSB;
3054 return res;
3057 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3058 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3059 ICOM_THIS(IDirect3DDevice8Impl,iface);
3061 TRACE("(%p)\n", This);
3063 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3066 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3067 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3068 ICOM_THIS(IDirect3DDevice8Impl,iface);
3070 TRACE("(%p)\n", This);
3072 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3074 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3075 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3076 ICOM_THIS(IDirect3DDevice8Impl,iface);
3078 TRACE("(%p)\n", This);
3080 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3083 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3084 IDirect3DStateBlockImpl* pSB;
3085 ICOM_THIS(IDirect3DDevice8Impl,iface);
3086 HRESULT res;
3088 TRACE("(%p) : for type %d\n", This, Type);
3090 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3091 *pToken = (DWORD) pSB;
3092 return res;
3095 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3096 ICOM_THIS(IDirect3DDevice8Impl,iface);
3097 FIXME("(%p) : stub\n", This); return D3D_OK;
3099 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3100 ICOM_THIS(IDirect3DDevice8Impl,iface);
3101 FIXME("(%p) : stub\n", This); return D3D_OK;
3103 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3104 ICOM_THIS(IDirect3DDevice8Impl,iface);
3105 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3106 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3107 if (*ppTexture)
3108 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3109 return D3D_OK;
3111 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3113 IDirect3DBaseTexture8 *oldTxt;
3114 BOOL reapplyStates = TRUE;
3115 DWORD oldTextureDimensions = -1;
3116 DWORD reapplyFlags = 0;
3118 ICOM_THIS(IDirect3DDevice8Impl,iface);
3119 D3DRESOURCETYPE textureType;
3121 oldTxt = This->UpdateStateBlock->textures[Stage];
3122 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3124 /* Reject invalid texture units */
3125 if (Stage >= GL_LIMITS(textures)) {
3126 TRACE("Attempt to access invalid texture rejected\n");
3127 return D3DERR_INVALIDCALL;
3130 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3131 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3132 This->UpdateStateBlock->textures[Stage] = pTexture;
3134 /* Handle recording of state blocks */
3135 if (This->isRecordingState) {
3136 TRACE("Recording... not performing anything\n");
3137 return D3D_OK;
3140 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3141 ENTER_GL();
3143 /* Make appropriate texture active */
3144 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3145 #if defined(GL_VERSION_1_3)
3146 glActiveTexture(GL_TEXTURE0 + Stage);
3147 checkGLcall("glActiveTexture");
3148 #else
3149 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3150 checkGLcall("glActiveTextureARB");
3151 #endif
3152 } else if (Stage>0) {
3153 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3156 /* Decrement the count of the previous texture */
3157 if (NULL != oldTxt) {
3158 IDirect3DBaseTexture8Impl_Release(oldTxt);
3161 if (NULL != pTexture) {
3162 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3164 /* Now setup the texture appropraitly */
3165 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3167 if (textureType == D3DRTYPE_TEXTURE) {
3168 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3169 TRACE("Skipping setting texture as old == new\n");
3170 reapplyStates = FALSE;
3171 } else {
3172 /* Standard 2D texture */
3173 TRACE("Standard 2d texture\n");
3174 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3176 /* Load up the texture now */
3177 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3179 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3180 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3181 TRACE("Skipping setting texture as old == new\n");
3182 reapplyStates = FALSE;
3183 } else {
3184 /* Standard 3D (volume) texture */
3185 TRACE("Standard 3d texture\n");
3186 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3188 /* Load up the texture now */
3189 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3191 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3192 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3193 TRACE("Skipping setting texture as old == new\n");
3194 reapplyStates = FALSE;
3195 } else {
3196 /* Standard Cube texture */
3197 TRACE("Standard Cube texture\n");
3198 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3200 /* Load up the texture now */
3201 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3203 } else {
3204 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3206 } else {
3207 TRACE("Setting to no texture (ie default texture)\n");
3208 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3209 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3210 checkGLcall("glBindTexture");
3211 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3214 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3215 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3216 glDisable(oldTextureDimensions);
3217 checkGLcall("Disable oldTextureDimensions");
3218 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3219 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3220 checkGLcall("glEnable new texture dimensions");
3223 /* If Alpha arg1 is texture then handle the special case when there changes between a
3224 texture and no texture - See comments in set_tex_op */
3225 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3226 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3228 reapplyFlags |= REAPPLY_ALPHAOP;
3233 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3234 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3235 if (reapplyStates) {
3236 setupTextureStates(iface, Stage, reapplyFlags);
3239 LEAVE_GL();
3241 return D3D_OK;
3244 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3245 ICOM_THIS(IDirect3DDevice8Impl,iface);
3246 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3247 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3248 return D3D_OK;
3251 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3252 ICOM_THIS(IDirect3DDevice8Impl,iface);
3253 union {
3254 float f;
3255 DWORD d;
3256 } tmpvalue;
3258 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3260 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3262 /* Reject invalid texture units */
3263 if (Stage >= GL_LIMITS(textures)) {
3264 TRACE("Attempt to access invalid texture rejected\n");
3265 return D3DERR_INVALIDCALL;
3268 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3269 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3270 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3272 /* Handle recording of state blocks */
3273 if (This->isRecordingState) {
3274 TRACE("Recording... not performing anything\n");
3275 return D3D_OK;
3278 ENTER_GL();
3280 /* Make appropriate texture active */
3281 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3282 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3283 #if defined(GL_VERSION_1_3)
3284 glActiveTexture(GL_TEXTURE0 + Stage);
3285 vcheckGLcall("glActiveTexture");
3286 #else
3287 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3288 vcheckGLcall("glActiveTextureARB");
3289 #endif
3290 } else if (Stage > 0) {
3291 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3294 switch (Type) {
3296 case D3DTSS_MINFILTER :
3297 case D3DTSS_MIPFILTER :
3299 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3300 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3301 GLint realVal = GL_LINEAR;
3303 if (ValueMIN == D3DTEXF_NONE) {
3304 /* Doesn't really make sense - Windows just seems to disable
3305 mipmapping when this occurs */
3306 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3307 realVal = GL_LINEAR;
3308 } else if (ValueMIN == D3DTEXF_POINT) {
3309 /* GL_NEAREST_* */
3310 if (ValueMIP == D3DTEXF_NONE) {
3311 realVal = GL_NEAREST;
3312 } else if (ValueMIP == D3DTEXF_POINT) {
3313 realVal = GL_NEAREST_MIPMAP_NEAREST;
3314 } else if (ValueMIP == D3DTEXF_LINEAR) {
3315 realVal = GL_NEAREST_MIPMAP_LINEAR;
3316 } else {
3317 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3318 realVal = GL_NEAREST;
3320 } else if (ValueMIN == D3DTEXF_LINEAR) {
3321 /* GL_LINEAR_* */
3322 if (ValueMIP == D3DTEXF_NONE) {
3323 realVal = GL_LINEAR;
3324 } else if (ValueMIP == D3DTEXF_POINT) {
3325 realVal = GL_LINEAR_MIPMAP_NEAREST;
3326 } else if (ValueMIP == D3DTEXF_LINEAR) {
3327 realVal = GL_LINEAR_MIPMAP_LINEAR;
3328 } else {
3329 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3330 realVal = GL_LINEAR;
3332 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3333 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3334 if (ValueMIP == D3DTEXF_NONE) {
3335 realVal = GL_LINEAR_MIPMAP_LINEAR;
3336 } else if (ValueMIP == D3DTEXF_POINT) {
3337 realVal = GL_LINEAR_MIPMAP_NEAREST;
3338 } else if (ValueMIP == D3DTEXF_LINEAR) {
3339 realVal = GL_LINEAR_MIPMAP_LINEAR;
3340 } else {
3341 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3342 realVal = GL_LINEAR;
3344 } else {
3345 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3346 realVal = GL_LINEAR;
3348 } else {
3349 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3350 realVal = GL_LINEAR_MIPMAP_LINEAR;
3353 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3354 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3355 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3357 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3359 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3360 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3361 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3362 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3363 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3366 break;
3368 case D3DTSS_MAGFILTER :
3370 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3371 GLint realVal = GL_NEAREST;
3373 if (ValueMAG == D3DTEXF_POINT) {
3374 realVal = GL_NEAREST;
3375 } else if (ValueMAG == D3DTEXF_LINEAR) {
3376 realVal = GL_LINEAR;
3377 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3378 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3379 realVal = GL_LINEAR;
3380 } else {
3381 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3382 realVal = GL_NEAREST;
3384 } else {
3385 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3386 realVal = GL_NEAREST;
3388 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3389 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3390 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3392 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3394 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3395 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3396 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3397 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3398 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3401 break;
3403 case D3DTSS_MAXMIPLEVEL :
3406 * Not really the same, but the more apprioprate than nothing
3408 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3409 GL_TEXTURE_BASE_LEVEL,
3410 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3411 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3413 break;
3415 case D3DTSS_MAXANISOTROPY :
3417 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3418 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3419 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3420 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3421 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3424 break;
3426 case D3DTSS_MIPMAPLODBIAS :
3428 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3429 tmpvalue.d = Value;
3430 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3431 GL_TEXTURE_LOD_BIAS_EXT,
3432 tmpvalue.f);
3433 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3436 break;
3438 case D3DTSS_ALPHAOP :
3439 case D3DTSS_COLOROP :
3442 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3443 /* TODO: Disable by making this and all later levels disabled */
3444 glDisable(GL_TEXTURE_1D);
3445 checkGLcall("Disable GL_TEXTURE_1D");
3446 glDisable(GL_TEXTURE_2D);
3447 checkGLcall("Disable GL_TEXTURE_2D");
3448 glDisable(GL_TEXTURE_3D);
3449 checkGLcall("Disable GL_TEXTURE_3D");
3450 break; /* Don't bother setting the texture operations */
3451 } else {
3452 /* Enable only the appropriate texture dimension */
3453 if (Type == D3DTSS_COLOROP) {
3454 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3455 glEnable(GL_TEXTURE_1D);
3456 checkGLcall("Enable GL_TEXTURE_1D");
3457 } else {
3458 glDisable(GL_TEXTURE_1D);
3459 checkGLcall("Disable GL_TEXTURE_1D");
3461 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3462 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3463 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3464 checkGLcall("Enable GL_TEXTURE_2D");
3465 } else {
3466 glEnable(GL_TEXTURE_2D);
3467 checkGLcall("Enable GL_TEXTURE_2D");
3469 } else {
3470 glDisable(GL_TEXTURE_2D);
3471 checkGLcall("Disable GL_TEXTURE_2D");
3473 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3474 glEnable(GL_TEXTURE_3D);
3475 checkGLcall("Enable GL_TEXTURE_3D");
3476 } else {
3477 glDisable(GL_TEXTURE_3D);
3478 checkGLcall("Disable GL_TEXTURE_3D");
3480 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3481 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3482 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3483 } else {
3484 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3485 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3489 /* Drop through... (Except disable case) */
3490 case D3DTSS_COLORARG0 :
3491 case D3DTSS_COLORARG1 :
3492 case D3DTSS_COLORARG2 :
3493 case D3DTSS_ALPHAARG0 :
3494 case D3DTSS_ALPHAARG1 :
3495 case D3DTSS_ALPHAARG2 :
3497 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3498 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3499 if (isAlphaArg) {
3500 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3501 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3502 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3503 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3504 } else {
3505 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3506 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3507 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3508 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3511 break;
3514 case D3DTSS_ADDRESSU :
3515 case D3DTSS_ADDRESSV :
3516 case D3DTSS_ADDRESSW :
3518 GLint wrapParm = GL_REPEAT;
3520 switch (Value) {
3521 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3522 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3523 case D3DTADDRESS_BORDER:
3525 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3526 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3527 } else {
3528 /* FIXME: Not right, but better */
3529 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3530 wrapParm = GL_REPEAT;
3533 break;
3534 case D3DTADDRESS_MIRROR:
3536 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3537 wrapParm = GL_MIRRORED_REPEAT_ARB;
3538 } else {
3539 /* Unsupported in OpenGL pre-1.4 */
3540 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3541 wrapParm = GL_REPEAT;
3544 break;
3545 case D3DTADDRESS_MIRRORONCE:
3547 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3548 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3549 } else {
3550 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3551 wrapParm = GL_REPEAT;
3554 break;
3556 default:
3557 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3558 wrapParm = GL_REPEAT;
3561 switch (Type) {
3562 case D3DTSS_ADDRESSU:
3563 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3564 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3565 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3566 break;
3567 case D3DTSS_ADDRESSV:
3568 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3569 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3570 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3571 break;
3572 case D3DTSS_ADDRESSW:
3573 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3574 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3575 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3576 break;
3577 default: /* nop */
3578 break; /** stupic compilator */
3581 break;
3583 case D3DTSS_BORDERCOLOR :
3585 float col[4];
3586 D3DCOLORTOGLFLOAT4(Value, col);
3587 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3588 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3589 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3591 break;
3593 case D3DTSS_TEXCOORDINDEX :
3595 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3597 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3598 one flag, you can still specify an index value, which the system uses to
3599 determine the texture wrapping mode.
3600 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3601 means use the vertex position (camera-space) as the input texture coordinates
3602 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3603 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3604 to the TEXCOORDINDEX value */
3606 /**
3607 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3609 switch (Value & 0xFFFF0000) {
3610 case D3DTSS_TCI_PASSTHRU:
3611 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3612 glDisable(GL_TEXTURE_GEN_S);
3613 glDisable(GL_TEXTURE_GEN_T);
3614 glDisable(GL_TEXTURE_GEN_R);
3615 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3616 break;
3618 case D3DTSS_TCI_CAMERASPACEPOSITION:
3619 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3620 as the input texture coordinates for this stage's texture transformation. This
3621 equates roughly to EYE_LINEAR */
3623 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3624 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3625 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3626 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3627 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3629 glMatrixMode(GL_MODELVIEW);
3630 glPushMatrix();
3631 glLoadIdentity();
3632 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3633 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3634 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3635 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3636 glPopMatrix();
3638 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3639 glEnable(GL_TEXTURE_GEN_S);
3640 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3641 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3642 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3643 glEnable(GL_TEXTURE_GEN_T);
3644 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3645 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3646 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3647 glEnable(GL_TEXTURE_GEN_R);
3648 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3649 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3650 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3652 break;
3654 case D3DTSS_TCI_CAMERASPACENORMAL:
3656 if (GL_SUPPORT(GL_NV_texgen_reflection)) {
3657 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3658 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3659 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3660 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3661 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3663 glMatrixMode(GL_MODELVIEW);
3664 glPushMatrix();
3665 glLoadIdentity();
3666 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3667 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3668 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3669 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3670 glPopMatrix();
3672 glEnable(GL_TEXTURE_GEN_S);
3673 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3674 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3675 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3676 glEnable(GL_TEXTURE_GEN_T);
3677 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3678 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3679 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3680 glEnable(GL_TEXTURE_GEN_R);
3681 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3682 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3683 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3686 break;
3688 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3690 if (GL_SUPPORT(GL_NV_texgen_reflection)) {
3691 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3692 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3693 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3694 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3695 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3697 glMatrixMode(GL_MODELVIEW);
3698 glPushMatrix();
3699 glLoadIdentity();
3700 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3701 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3702 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3703 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3704 glPopMatrix();
3706 glEnable(GL_TEXTURE_GEN_S);
3707 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3708 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3709 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3710 glEnable(GL_TEXTURE_GEN_T);
3711 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3712 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3713 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3714 glEnable(GL_TEXTURE_GEN_R);
3715 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3716 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3717 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3720 break;
3722 /* Unhandled types: */
3723 default:
3724 /* Todo: */
3725 /* ? disable GL_TEXTURE_GEN_n ? */
3726 glDisable(GL_TEXTURE_GEN_S);
3727 glDisable(GL_TEXTURE_GEN_T);
3728 glDisable(GL_TEXTURE_GEN_R);
3729 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3730 break;
3733 break;
3735 /* Unhandled */
3736 case D3DTSS_TEXTURETRANSFORMFLAGS :
3737 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3738 break;
3740 case D3DTSS_BUMPENVMAT00 :
3741 case D3DTSS_BUMPENVMAT01 :
3742 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3743 break;
3744 case D3DTSS_BUMPENVMAT10 :
3745 case D3DTSS_BUMPENVMAT11 :
3746 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3747 break;
3749 case D3DTSS_BUMPENVLSCALE :
3750 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3751 break;
3753 case D3DTSS_BUMPENVLOFFSET :
3754 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3755 break;
3757 case D3DTSS_RESULTARG :
3758 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3759 break;
3761 default:
3762 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3763 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3766 LEAVE_GL();
3768 return D3D_OK;
3770 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3771 ICOM_THIS(IDirect3DDevice8Impl,iface);
3772 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3773 return D3D_OK;
3775 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3776 ICOM_THIS(IDirect3DDevice8Impl,iface);
3777 FIXME("(%p) : stub\n", This);
3778 return D3D_OK;
3780 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3781 ICOM_THIS(IDirect3DDevice8Impl,iface);
3782 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3783 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3784 if (PaletteNumber >= MAX_PALETTES) {
3785 return D3DERR_INVALIDCALL;
3787 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3788 return D3D_OK;
3790 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3791 ICOM_THIS(IDirect3DDevice8Impl,iface);
3792 if (PaletteNumber >= MAX_PALETTES) {
3793 return D3DERR_INVALIDCALL;
3795 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3796 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3797 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3798 return D3D_OK;
3800 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3801 ICOM_THIS(IDirect3DDevice8Impl,iface);
3802 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3803 if (PaletteNumber >= MAX_PALETTES) {
3804 return D3DERR_INVALIDCALL;
3806 This->currentPalette = PaletteNumber;
3808 #if defined(GL_EXT_paletted_texture)
3809 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3811 ENTER_GL();
3813 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3814 GL_RGBA, /* internal format */
3815 256, /* table size */
3816 GL_RGBA, /* table format */
3817 GL_UNSIGNED_BYTE, /* table type */
3818 This->palettes[PaletteNumber]);
3819 checkGLcall("glColorTableEXT");
3821 LEAVE_GL();
3823 } else {
3824 /* Delayed palette handling ... waiting for software emulation into preload code */
3826 #endif
3827 return D3D_OK;
3829 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3830 ICOM_THIS(IDirect3DDevice8Impl,iface);
3831 *PaletteNumber = This->currentPalette;
3832 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3833 return D3D_OK;
3835 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3837 ICOM_THIS(IDirect3DDevice8Impl,iface);
3838 This->StateBlock->streamIsUP = FALSE;
3840 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3841 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3843 return D3D_OK;
3845 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3846 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3847 UINT idxStride = 2;
3848 IDirect3DIndexBuffer8 *pIB;
3849 D3DINDEXBUFFER_DESC IdxBufDsc;
3851 ICOM_THIS(IDirect3DDevice8Impl,iface);
3852 pIB = This->StateBlock->pIndexData;
3853 This->StateBlock->streamIsUP = FALSE;
3855 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3856 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3857 minIndex, NumVertices, startIndex, primCount);
3859 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3860 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3861 idxStride = 2;
3862 } else {
3863 idxStride = 4;
3866 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3867 minIndex);
3869 return D3D_OK;
3871 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3872 ICOM_THIS(IDirect3DDevice8Impl,iface);
3874 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3875 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3877 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3879 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3880 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3881 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3882 This->StateBlock->streamIsUP = TRUE;
3883 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3884 This->StateBlock->stream_stride[0] = 0;
3885 This->StateBlock->stream_source[0] = NULL;
3887 /*stream zero settings set to null at end */
3888 return D3D_OK;
3890 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3891 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3892 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3893 UINT VertexStreamZeroStride) {
3894 int idxStride;
3895 ICOM_THIS(IDirect3DDevice8Impl,iface);
3896 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),
3897 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3899 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3900 if (IndexDataFormat == D3DFMT_INDEX16) {
3901 idxStride = 2;
3902 } else {
3903 idxStride = 4;
3906 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3907 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3908 This->StateBlock->streamIsUP = TRUE;
3909 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3910 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3912 /*stream zero settings set to null at end */
3913 This->StateBlock->stream_source[0] = NULL;
3914 This->StateBlock->stream_stride[0] = 0;
3915 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3917 return D3D_OK;
3919 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3920 ICOM_THIS(IDirect3DDevice8Impl,iface);
3921 FIXME("(%p) : stub\n", This); return D3D_OK;
3923 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3924 ICOM_THIS(IDirect3DDevice8Impl,iface);
3925 IDirect3DVertexShaderImpl* object;
3926 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3927 HRESULT res;
3928 UINT i;
3930 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3931 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3932 return D3DERR_INVALIDCALL;
3934 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3935 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3936 return D3DERR_OUTOFVIDEOMEMORY;
3939 /** Create the Vertex Shader */
3940 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3941 /** TODO: check FAILED(res) */
3943 /** Create and Bind the Vertex Shader Declaration */
3944 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3945 /** TODO: check FAILED(res) */
3947 VertexShaders[i] = object;
3948 VertexShaderDeclarations[i] = attached_decl;
3949 *pHandle = VS_HIGHESTFIXEDFXF + i;
3950 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3952 return D3D_OK;
3954 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3955 ICOM_THIS(IDirect3DDevice8Impl,iface);
3957 This->UpdateStateBlock->VertexShader = Handle;
3958 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3959 This->UpdateStateBlock->Set.vertexShader = TRUE;
3961 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3962 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3963 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3964 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3965 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3966 } else { /* use a fvf, so desactivate the vshader decl */
3967 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3968 This->UpdateStateBlock->vertexShaderDecl = NULL;
3969 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3970 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3972 /* Handle recording of state blocks */
3973 if (This->isRecordingState) {
3974 TRACE("Recording... not performing anything\n");
3975 return D3D_OK;
3978 * TODO: merge HAL shaders context switching from prototype
3980 return D3D_OK;
3982 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3983 ICOM_THIS(IDirect3DDevice8Impl,iface);
3984 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3985 *pHandle = This->StateBlock->VertexShader;
3986 return D3D_OK;
3989 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3990 ICOM_THIS(IDirect3DDevice8Impl,iface);
3991 IDirect3DVertexShaderImpl* object;
3992 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3994 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3995 return D3DERR_INVALIDCALL;
3999 * Delete Vertex Shader
4001 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4002 if (NULL == object) {
4003 return D3DERR_INVALIDCALL;
4005 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4006 /* TODO: check validity of object */
4007 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4008 if (object->prgId != 0) {
4009 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4011 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4012 HeapFree(GetProcessHeap(), 0, (void *)object);
4013 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4016 * Delete Vertex Shader Declaration
4018 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4019 if (NULL == attached_decl) {
4020 return D3DERR_INVALIDCALL;
4022 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4023 /* TODO: check validity of object */
4024 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4025 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4026 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4028 return D3D_OK;
4031 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4032 ICOM_THIS(IDirect3DDevice8Impl,iface);
4034 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4035 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4036 return D3DERR_INVALIDCALL;
4038 if (NULL == pConstantData) {
4039 return D3DERR_INVALIDCALL;
4041 if (ConstantCount > 1) {
4042 FLOAT* f = (FLOAT*)pConstantData;
4043 UINT i;
4044 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4045 for (i = 0; i < ConstantCount; ++i) {
4046 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4047 f += 4;
4049 } else {
4050 FLOAT* f = (FLOAT*) pConstantData;
4051 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4053 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4054 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4055 return D3D_OK;
4057 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4058 ICOM_THIS(IDirect3DDevice8Impl,iface);
4060 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4061 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4062 return D3DERR_INVALIDCALL;
4064 if (NULL == pConstantData) {
4065 return D3DERR_INVALIDCALL;
4067 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4068 return D3D_OK;
4070 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4071 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4072 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4074 attached_decl = VERTEX_SHADER_DECL(Handle);
4075 if (NULL == attached_decl) {
4076 return D3DERR_INVALIDCALL;
4078 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4080 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4081 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4082 IDirect3DVertexShaderImpl* object;
4084 object = VERTEX_SHADER(Handle);
4085 if (NULL == object) {
4086 return D3DERR_INVALIDCALL;
4088 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4091 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4092 ICOM_THIS(IDirect3DDevice8Impl,iface);
4093 IDirect3DIndexBuffer8 *oldIdxs;
4095 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4096 oldIdxs = This->StateBlock->pIndexData;
4098 This->UpdateStateBlock->Changed.Indices = TRUE;
4099 This->UpdateStateBlock->Set.Indices = TRUE;
4100 This->UpdateStateBlock->pIndexData = pIndexData;
4101 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4103 /* Handle recording of state blocks */
4104 if (This->isRecordingState) {
4105 TRACE("Recording... not performing anything\n");
4106 return D3D_OK;
4109 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4110 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4111 return D3D_OK;
4113 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4114 ICOM_THIS(IDirect3DDevice8Impl,iface);
4115 FIXME("(%p) : stub\n", This);
4117 *ppIndexData = This->StateBlock->pIndexData;
4118 /* up ref count on ppindexdata */
4119 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4120 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4122 return D3D_OK;
4124 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4125 ICOM_THIS(IDirect3DDevice8Impl,iface);
4126 IDirect3DPixelShaderImpl* object;
4127 HRESULT res;
4128 UINT i;
4130 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4131 if (NULL == pFunction || NULL == pHandle) {
4132 return D3DERR_INVALIDCALL;
4134 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4135 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4136 return D3DERR_OUTOFVIDEOMEMORY;
4139 /** Create the Pixel Shader */
4140 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4141 if (SUCCEEDED(res)) {
4142 PixelShaders[i] = object;
4143 *pHandle = VS_HIGHESTFIXEDFXF + i;
4144 return D3D_OK;
4146 *pHandle = 0xFFFFFFFF;
4147 return res;
4149 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4150 ICOM_THIS(IDirect3DDevice8Impl,iface);
4152 This->UpdateStateBlock->PixelShader = Handle;
4153 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4154 This->UpdateStateBlock->Set.pixelShader = TRUE;
4156 /* Handle recording of state blocks */
4157 if (This->isRecordingState) {
4158 TRACE_(d3d_shader)("Recording... not performing anything\n");
4159 return D3D_OK;
4162 /* FIXME: Quieten when not being used */
4163 if (Handle != 0) {
4164 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4165 } else {
4166 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4169 return D3D_OK;
4171 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4172 ICOM_THIS(IDirect3DDevice8Impl,iface);
4173 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4174 *pHandle = This->StateBlock->PixelShader;
4175 return D3D_OK;
4178 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4179 ICOM_THIS(IDirect3DDevice8Impl,iface);
4180 IDirect3DPixelShaderImpl* object;
4182 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4183 return D3DERR_INVALIDCALL;
4185 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4186 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4187 /* TODO: check validity of object before free */
4188 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4189 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4190 HeapFree(GetProcessHeap(), 0, (void *)object);
4191 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4193 return D3D_OK;
4196 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4197 ICOM_THIS(IDirect3DDevice8Impl,iface);
4199 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4200 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4201 return D3DERR_INVALIDCALL;
4203 if (NULL == pConstantData) {
4204 return D3DERR_INVALIDCALL;
4206 if (ConstantCount > 1) {
4207 FLOAT* f = (FLOAT*)pConstantData;
4208 UINT i;
4209 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4210 for (i = 0; i < ConstantCount; ++i) {
4211 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4212 f += 4;
4214 } else {
4215 FLOAT* f = (FLOAT*) pConstantData;
4216 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4218 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4219 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4220 return D3D_OK;
4222 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4223 ICOM_THIS(IDirect3DDevice8Impl,iface);
4225 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4226 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4227 return D3DERR_INVALIDCALL;
4229 if (NULL == pConstantData) {
4230 return D3DERR_INVALIDCALL;
4232 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4233 return D3D_OK;
4235 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4236 IDirect3DPixelShaderImpl* object;
4238 object = PIXEL_SHADER(Handle);
4239 if (NULL == object) {
4240 return D3DERR_INVALIDCALL;
4242 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4244 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4245 ICOM_THIS(IDirect3DDevice8Impl,iface);
4246 FIXME("(%p) : stub\n", This); return D3D_OK;
4248 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4249 ICOM_THIS(IDirect3DDevice8Impl,iface);
4250 FIXME("(%p) : stub\n", This); return D3D_OK;
4252 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4253 ICOM_THIS(IDirect3DDevice8Impl,iface);
4254 FIXME("(%p) : stub\n", This); return D3D_OK;
4257 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4258 IDirect3DVertexBuffer8 *oldSrc;
4259 ICOM_THIS(IDirect3DDevice8Impl,iface);
4261 oldSrc = This->StateBlock->stream_source[StreamNumber];
4262 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4264 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4265 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4266 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4267 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4269 /* Handle recording of state blocks */
4270 if (This->isRecordingState) {
4271 TRACE("Recording... not performing anything\n");
4272 return D3D_OK;
4275 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4276 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4277 return D3D_OK;
4279 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4280 ICOM_THIS(IDirect3DDevice8Impl,iface);
4281 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4282 *pStream = This->StateBlock->stream_source[StreamNumber];
4283 *pStride = This->StateBlock->stream_stride[StreamNumber];
4284 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4285 return D3D_OK;
4289 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4291 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4292 IDirect3DDevice8Impl_QueryInterface,
4293 IDirect3DDevice8Impl_AddRef,
4294 IDirect3DDevice8Impl_Release,
4295 IDirect3DDevice8Impl_TestCooperativeLevel,
4296 IDirect3DDevice8Impl_GetAvailableTextureMem,
4297 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4298 IDirect3DDevice8Impl_GetDirect3D,
4299 IDirect3DDevice8Impl_GetDeviceCaps,
4300 IDirect3DDevice8Impl_GetDisplayMode,
4301 IDirect3DDevice8Impl_GetCreationParameters,
4302 IDirect3DDevice8Impl_SetCursorProperties,
4303 IDirect3DDevice8Impl_SetCursorPosition,
4304 IDirect3DDevice8Impl_ShowCursor,
4305 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4306 IDirect3DDevice8Impl_Reset,
4307 IDirect3DDevice8Impl_Present,
4308 IDirect3DDevice8Impl_GetBackBuffer,
4309 IDirect3DDevice8Impl_GetRasterStatus,
4310 IDirect3DDevice8Impl_SetGammaRamp,
4311 IDirect3DDevice8Impl_GetGammaRamp,
4312 IDirect3DDevice8Impl_CreateTexture,
4313 IDirect3DDevice8Impl_CreateVolumeTexture,
4314 IDirect3DDevice8Impl_CreateCubeTexture,
4315 IDirect3DDevice8Impl_CreateVertexBuffer,
4316 IDirect3DDevice8Impl_CreateIndexBuffer,
4317 IDirect3DDevice8Impl_CreateRenderTarget,
4318 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4319 IDirect3DDevice8Impl_CreateImageSurface,
4320 IDirect3DDevice8Impl_CopyRects,
4321 IDirect3DDevice8Impl_UpdateTexture,
4322 IDirect3DDevice8Impl_GetFrontBuffer,
4323 IDirect3DDevice8Impl_SetRenderTarget,
4324 IDirect3DDevice8Impl_GetRenderTarget,
4325 IDirect3DDevice8Impl_GetDepthStencilSurface,
4326 IDirect3DDevice8Impl_BeginScene,
4327 IDirect3DDevice8Impl_EndScene,
4328 IDirect3DDevice8Impl_Clear,
4329 IDirect3DDevice8Impl_SetTransform,
4330 IDirect3DDevice8Impl_GetTransform,
4331 IDirect3DDevice8Impl_MultiplyTransform,
4332 IDirect3DDevice8Impl_SetViewport,
4333 IDirect3DDevice8Impl_GetViewport,
4334 IDirect3DDevice8Impl_SetMaterial,
4335 IDirect3DDevice8Impl_GetMaterial,
4336 IDirect3DDevice8Impl_SetLight,
4337 IDirect3DDevice8Impl_GetLight,
4338 IDirect3DDevice8Impl_LightEnable,
4339 IDirect3DDevice8Impl_GetLightEnable,
4340 IDirect3DDevice8Impl_SetClipPlane,
4341 IDirect3DDevice8Impl_GetClipPlane,
4342 IDirect3DDevice8Impl_SetRenderState,
4343 IDirect3DDevice8Impl_GetRenderState,
4344 IDirect3DDevice8Impl_BeginStateBlock,
4345 IDirect3DDevice8Impl_EndStateBlock,
4346 IDirect3DDevice8Impl_ApplyStateBlock,
4347 IDirect3DDevice8Impl_CaptureStateBlock,
4348 IDirect3DDevice8Impl_DeleteStateBlock,
4349 IDirect3DDevice8Impl_CreateStateBlock,
4350 IDirect3DDevice8Impl_SetClipStatus,
4351 IDirect3DDevice8Impl_GetClipStatus,
4352 IDirect3DDevice8Impl_GetTexture,
4353 IDirect3DDevice8Impl_SetTexture,
4354 IDirect3DDevice8Impl_GetTextureStageState,
4355 IDirect3DDevice8Impl_SetTextureStageState,
4356 IDirect3DDevice8Impl_ValidateDevice,
4357 IDirect3DDevice8Impl_GetInfo,
4358 IDirect3DDevice8Impl_SetPaletteEntries,
4359 IDirect3DDevice8Impl_GetPaletteEntries,
4360 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4361 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4362 IDirect3DDevice8Impl_DrawPrimitive,
4363 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4364 IDirect3DDevice8Impl_DrawPrimitiveUP,
4365 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4366 IDirect3DDevice8Impl_ProcessVertices,
4367 IDirect3DDevice8Impl_CreateVertexShader,
4368 IDirect3DDevice8Impl_SetVertexShader,
4369 IDirect3DDevice8Impl_GetVertexShader,
4370 IDirect3DDevice8Impl_DeleteVertexShader,
4371 IDirect3DDevice8Impl_SetVertexShaderConstant,
4372 IDirect3DDevice8Impl_GetVertexShaderConstant,
4373 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4374 IDirect3DDevice8Impl_GetVertexShaderFunction,
4375 IDirect3DDevice8Impl_SetStreamSource,
4376 IDirect3DDevice8Impl_GetStreamSource,
4377 IDirect3DDevice8Impl_SetIndices,
4378 IDirect3DDevice8Impl_GetIndices,
4379 IDirect3DDevice8Impl_CreatePixelShader,
4380 IDirect3DDevice8Impl_SetPixelShader,
4381 IDirect3DDevice8Impl_GetPixelShader,
4382 IDirect3DDevice8Impl_DeletePixelShader,
4383 IDirect3DDevice8Impl_SetPixelShaderConstant,
4384 IDirect3DDevice8Impl_GetPixelShaderConstant,
4385 IDirect3DDevice8Impl_GetPixelShaderFunction,
4386 IDirect3DDevice8Impl_DrawRectPatch,
4387 IDirect3DDevice8Impl_DrawTriPatch,
4388 IDirect3DDevice8Impl_DeletePatch
4391 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4393 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4394 ICOM_THIS(IDirect3DDevice8Impl,iface);
4396 ENTER_GL();
4398 #if 0
4399 if (This->glCtx != This->render_ctx) {
4400 glXDestroyContext(This->display, This->render_ctx);
4401 This->render_ctx = This->glCtx;
4403 #endif
4404 if (This->win != This->drawable) {
4405 glXDestroyPbuffer(This->display, This->drawable);
4406 This->drawable = This->win;
4409 LEAVE_GL();
4411 #endif
4412 return D3D_OK;
4415 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4416 IDirect3DSurface8* RenderSurface,
4417 IDirect3DSurface8* StencilSurface) {
4419 HRESULT ret = D3DERR_INVALIDCALL;
4421 * Currently only active for GLX >= 1.3
4422 * for others versions we'll have to use GLXPixmaps
4424 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4425 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4426 * so only check OpenGL version
4428 #if defined(GL_VERSION_1_3)
4429 GLXFBConfig* cfgs = NULL;
4430 int nCfgs = 0;
4431 int attribs[256];
4432 int nAttribs = 0;
4433 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4434 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4435 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4436 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4437 IDirect3DSurface8Impl* tmp;
4439 ICOM_THIS(IDirect3DDevice8Impl,iface);
4441 #define PUSH1(att) attribs[nAttribs++] = (att);
4442 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4444 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4445 PUSH2(GLX_X_RENDERABLE, TRUE);
4446 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4448 switch (BackBufferFormat) {
4449 /* color buffer */
4450 case D3DFMT_P8:
4451 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4452 PUSH2(GLX_BUFFER_SIZE, 8);
4453 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4454 break;
4456 case D3DFMT_R3G3B2:
4457 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4458 PUSH2(GLX_RED_SIZE, 3);
4459 PUSH2(GLX_GREEN_SIZE, 3);
4460 PUSH2(GLX_BLUE_SIZE, 2);
4461 break;
4463 case D3DFMT_A1R5G5B5:
4464 PUSH2(GLX_ALPHA_SIZE, 1);
4465 case D3DFMT_X1R5G5B5:
4466 PUSH2(GLX_RED_SIZE, 5);
4467 PUSH2(GLX_GREEN_SIZE, 5);
4468 PUSH2(GLX_BLUE_SIZE, 5);
4469 break;
4471 case D3DFMT_R5G6B5:
4472 PUSH2(GLX_RED_SIZE, 5);
4473 PUSH2(GLX_GREEN_SIZE, 6);
4474 PUSH2(GLX_BLUE_SIZE, 5);
4475 break;
4477 case D3DFMT_A4R4G4B4:
4478 PUSH2(GLX_ALPHA_SIZE, 4);
4479 case D3DFMT_X4R4G4B4:
4480 PUSH2(GLX_RED_SIZE, 4);
4481 PUSH2(GLX_GREEN_SIZE, 4);
4482 PUSH2(GLX_BLUE_SIZE, 4);
4483 break;
4485 case D3DFMT_A8R8G8B8:
4486 PUSH2(GLX_ALPHA_SIZE, 8);
4487 case D3DFMT_R8G8B8:
4488 case D3DFMT_X8R8G8B8:
4489 PUSH2(GLX_RED_SIZE, 8);
4490 PUSH2(GLX_GREEN_SIZE, 8);
4491 PUSH2(GLX_BLUE_SIZE, 8);
4492 break;
4494 default:
4495 break;
4498 switch (StencilBufferFormat) {
4499 case D3DFMT_D16_LOCKABLE:
4500 case D3DFMT_D16:
4501 PUSH2(GLX_DEPTH_SIZE, 16);
4502 break;
4504 case D3DFMT_D15S1:
4505 PUSH2(GLX_DEPTH_SIZE, 15);
4506 break;
4508 case D3DFMT_D24X8:
4509 PUSH2(GLX_DEPTH_SIZE, 24);
4510 break;
4512 case D3DFMT_D24X4S4:
4513 PUSH2(GLX_DEPTH_SIZE, 24);
4514 PUSH2(GLX_STENCIL_SIZE, 4);
4515 break;
4517 case D3DFMT_D24S8:
4518 PUSH2(GLX_DEPTH_SIZE, 24);
4519 PUSH2(GLX_STENCIL_SIZE, 8);
4520 break;
4522 case D3DFMT_D32:
4523 PUSH2(GLX_DEPTH_SIZE, 32);
4524 break;
4526 default:
4527 break;
4530 PUSH1(None);
4532 ENTER_GL();
4534 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4535 if (NULL != cfgs) {
4536 #ifdef EXTRA_TRACES
4537 int i;
4538 for (i = 0; i < nCfgs; ++i) {
4539 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4541 #endif
4543 if (NULL != This->renderTarget) {
4544 /*GLenum prev_read; */
4545 glFlush();
4546 vcheckGLcall("glFlush");
4548 #ifdef EXTRA_TRACES
4549 /** very very usefull debug code */
4550 glXSwapBuffers(This->display, This->drawable);
4551 printf("Hit Enter to get next frame ...\n");
4552 getchar();
4553 #endif
4555 #if 0
4556 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4557 vcheckGLcall("glIntegerv");
4558 glReadBuffer(GL_BACK);
4559 vcheckGLcall("glReadBuffer");
4561 long j;
4562 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4564 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4565 pitch = pitch / 2;
4567 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4568 glReadPixels(0,
4569 This->renderTarget->myDesc.Height - j - 1,
4570 This->renderTarget->myDesc.Width,
4572 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4573 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4574 This->renderTarget->allocatedMemory + j * pitch);
4575 vcheckGLcall("glReadPixels");
4578 glReadBuffer(prev_read);
4579 vcheckGLcall("glReadBuffer");
4580 #endif
4583 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4584 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4585 nAttribs = 0;
4586 PUSH2(GLX_PBUFFER_WIDTH, Width);
4587 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4588 PUSH1(None);
4589 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4591 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4592 if (NULL == This->render_ctx) {
4593 ERR("cannot create glxContext\n");
4596 glFlush();
4597 glXSwapBuffers(This->display, This->drawable);
4598 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4599 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4601 checkGLcall("glXMakeContextCurrent");
4604 tmp = This->renderTarget;
4605 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4606 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4607 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4609 tmp = This->stencilBufferTarget;
4610 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4611 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4612 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4615 DWORD value;
4616 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4617 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4618 /* Force updating the cull mode */
4619 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4620 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4621 /* Force updating projection matrix */
4622 This->last_was_rhw = FALSE;
4623 This->proj_valid = FALSE;
4626 ret = D3D_OK;
4628 } else {
4629 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4632 #undef PUSH1
4633 #undef PUSH2
4635 LEAVE_GL();
4637 #endif
4639 return ret;