2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
35 /*#define GL_GLEXT_PROTOTYPES*/
36 /*#undef GLX_GLXEXT_LEGACY*/
37 #include "d3d8_private.h"
39 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
42 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
43 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
44 WINE_DECLARE_DEBUG_CHANNEL(fps);
46 IDirect3DVertexShaderImpl* VertexShaders[64];
47 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
48 IDirect3DPixelShaderImpl* PixelShaders[64];
51 #ifdef FRAME_DEBUGGING
53 BOOL isDumpingFrames = FALSE;
58 * Utility functions or macros
60 #define conv_mat(mat,gl_mat) \
62 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
63 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
64 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
65 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
66 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
69 /* Apply the current values to the specified texture stage */
70 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
71 ICOM_THIS(IDirect3DDevice8Impl,iface);
74 BOOL changeTexture = TRUE;
76 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
77 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
82 /* Performance: For texture states where multiples effect the outcome, only bother
83 applying the last one as it will pick up all the other values */
84 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
85 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
86 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
87 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
88 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
89 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
93 /* Performance: If the texture states only impact settings for the texture unit
94 (compared to the texture object) then there is no need to reapply them. The
95 only time they need applying is the first time, since we cheat and put the
96 values into the stateblock without applying.
97 Per-texture unit: texture function (eg. combine), ops and args
99 texture generation settings
100 Note: Due to some special conditions there may be a need to do particular ones
101 of these, which is what the Flags allows */
103 case D3DTSS_TEXCOORDINDEX:
104 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
108 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
116 /* Performance: Only change to this texture if we have to */
118 /* Make appropriate texture active */
119 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
120 #if defined(GL_VERSION_1_3)
121 glActiveTexture(GL_TEXTURE0 + Stage);
123 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
125 checkGLcall("glActiveTextureARB");
126 } else if (Stage > 0) {
127 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
129 changeTexture = FALSE;
132 /* Now apply the change */
133 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
137 /* Note the D3DRS value applies to all textures, but GL has one
138 * per texture, so apply it now ready to be used!
140 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
141 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
142 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
144 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
147 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
148 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
151 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
152 ICOM_THIS(IDirect3DDevice8Impl,iface);
154 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
155 glMatrixMode(GL_MODELVIEW);
157 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
160 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
161 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
162 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
163 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
164 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
165 checkGLcall("glLightfv");
168 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
169 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
170 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
171 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
172 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
173 checkGLcall("glLightfv");
176 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
177 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
178 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
179 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
180 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
181 checkGLcall("glLightfv");
183 /* Attenuation - Are these right? guessing... */
184 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
185 checkGLcall("glLightf");
186 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
187 checkGLcall("glLightf");
189 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
190 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
191 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
192 checkGLcall("glLightf");
194 switch (lightInfo->OriginalParms.Type) {
197 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
198 checkGLcall("glLightfv");
199 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
200 checkGLcall("glLightf");
206 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
207 checkGLcall("glLightfv");
209 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214 checkGLcall("glLightf");
218 case D3DLIGHT_DIRECTIONAL:
220 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
221 checkGLcall("glLightfv");
222 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
223 checkGLcall("glLightf");
224 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
225 checkGLcall("glLightf");
229 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
232 /* Restore the modelview matrix */
236 /* Setup this textures matrix */
237 static void set_texture_matrix(float *smat, DWORD flags)
241 glMatrixMode(GL_TEXTURE);
243 if (flags == D3DTTFF_DISABLE) {
245 checkGLcall("glLoadIdentity()");
249 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
250 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
251 checkGLcall("glLoadIdentity()");
255 memcpy(mat, smat, 16*sizeof(float));
257 switch (flags & ~D3DTTFF_PROJECTED) {
258 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
259 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
260 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
263 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
265 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
266 mat[1] = mat[5] = mat[9] = mat[13] = 0;
269 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
270 mat[2] = mat[6] = mat[10] = mat[14] = 0;
274 checkGLcall("glLoadMatrixf(mat)");
277 /* IDirect3D IUnknown parts follow: */
278 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
280 ICOM_THIS(IDirect3DDevice8Impl,iface);
282 if (IsEqualGUID(riid, &IID_IUnknown)
283 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
284 IDirect3DDevice8Impl_AddRef(iface);
289 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
290 return E_NOINTERFACE;
293 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
294 ICOM_THIS(IDirect3DDevice8Impl,iface);
295 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
296 return ++(This->ref);
299 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
300 ICOM_THIS(IDirect3DDevice8Impl,iface);
301 ULONG ref = --This->ref;
302 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
304 IDirect3DDevice8Impl_CleanRender(iface);
305 HeapFree(GetProcessHeap(), 0, This);
310 /* IDirect3DDevice Interface follow: */
311 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
312 ICOM_THIS(IDirect3DDevice8Impl,iface);
313 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
317 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
318 ICOM_THIS(IDirect3DDevice8Impl,iface);
319 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
321 * pretend we have 32MB of any type of memory queried.
323 return (1024*1024*32);
326 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
327 ICOM_THIS(IDirect3DDevice8Impl,iface);
328 FIXME("(%p) : stub\n", This); return D3D_OK;
330 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
331 ICOM_THIS(IDirect3DDevice8Impl,iface);
332 TRACE("(%p) : returning %p\n", This, This->direct3d8);
335 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
337 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
340 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
341 ICOM_THIS(IDirect3DDevice8Impl,iface);
342 FIXME("(%p) : stub, calling idirect3d for now\n", This);
343 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
346 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
351 ICOM_THIS(IDirect3DDevice8Impl,iface);
352 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
353 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
354 pMode->RefreshRate = 85; /*FIXME: How to identify? */
356 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
357 bpp = GetDeviceCaps(hdc, BITSPIXEL);
361 case 8: pMode->Format = D3DFMT_R8G8B8; break;
362 case 16: pMode->Format = D3DFMT_R5G6B5; break;
363 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
364 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
366 FIXME("Unrecognized display mode format\n");
367 pMode->Format = D3DFMT_UNKNOWN;
370 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
371 pMode->Format, debug_d3dformat(pMode->Format));
374 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
375 ICOM_THIS(IDirect3DDevice8Impl,iface);
376 TRACE("(%p) copying to %p\n", This, pParameters);
377 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
380 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
381 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
382 ICOM_THIS(IDirect3DDevice8Impl,iface);
383 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
385 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
386 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
387 return D3DERR_INVALIDCALL;
389 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
390 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
391 return D3DERR_INVALIDCALL;
394 This->xHotSpot = XHotSpot;
395 This->yHotSpot = YHotSpot;
398 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
399 ICOM_THIS(IDirect3DDevice8Impl,iface);
400 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
401 This->xScreenSpace = XScreenSpace;
402 This->yScreenSpace = YScreenSpace;
405 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
406 ICOM_THIS(IDirect3DDevice8Impl,iface);
407 TRACE("(%p) : visible(%d)\n", This, bShow);
408 This->bCursorVisible = bShow;
411 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
412 IDirect3DSwapChain8Impl* object;
413 ICOM_THIS(IDirect3DDevice8Impl,iface);
414 FIXME("(%p) : stub\n", This);
416 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
417 if (NULL == object) {
418 return D3DERR_OUTOFVIDEOMEMORY;
420 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
423 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
424 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
425 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
427 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
428 (pPresentationParameters->BackBufferHeight == 0))) {
431 GetClientRect(This->win_handle, &Rect);
433 if (pPresentationParameters->BackBufferWidth == 0) {
434 pPresentationParameters->BackBufferWidth = Rect.right;
435 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
437 if (pPresentationParameters->BackBufferHeight == 0) {
438 pPresentationParameters->BackBufferHeight = Rect.bottom;
439 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
443 /* Save the presentation parms now filled in correctly */
444 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
446 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
447 pPresentationParameters->BackBufferWidth,
448 pPresentationParameters->BackBufferHeight,
449 pPresentationParameters->BackBufferFormat,
450 pPresentationParameters->MultiSampleType,
452 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
454 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
455 pPresentationParameters->BackBufferWidth,
456 pPresentationParameters->BackBufferHeight,
457 pPresentationParameters->BackBufferFormat,
458 pPresentationParameters->MultiSampleType,
460 (LPDIRECT3DSURFACE8*) &object->backBuffer);
462 if (pPresentationParameters->EnableAutoDepthStencil) {
463 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
464 pPresentationParameters->BackBufferWidth,
465 pPresentationParameters->BackBufferHeight,
466 pPresentationParameters->AutoDepthStencilFormat,
468 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
470 object->depthStencilBuffer = NULL;
473 *pSwapChain = (IDirect3DSwapChain8*) object;
476 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
477 ICOM_THIS(IDirect3DDevice8Impl,iface);
478 FIXME("(%p) : stub\n", This); return D3D_OK;
480 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
481 ICOM_THIS(IDirect3DDevice8Impl,iface);
482 TRACE("(%p) : complete stub!\n", This);
486 glXSwapBuffers(This->display, This->drawable);
487 /* Dont call checkGLcall, as glGetError is not applicable here */
488 TRACE("glXSwapBuffers called, Starting new frame\n");
493 static long prev_time, frames;
495 DWORD time = GetTickCount();
497 /* every 1.5 seconds */
498 if (time - prev_time > 1500) {
499 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
505 #if defined(FRAME_DEBUGGING)
507 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
510 FIXME("Enabling D3D Trace\n");
511 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
512 #if defined(SHOW_FRAME_MAKEUP)
513 FIXME("Singe Frame snapshots Starting\n");
514 isDumpingFrames = TRUE;
515 glClear(GL_COLOR_BUFFER_BIT);
518 #if defined(SINGLE_FRAME_DEBUGGING)
520 #if defined(SHOW_FRAME_MAKEUP)
521 FIXME("Singe Frame snapshots Finishing\n");
522 isDumpingFrames = FALSE;
524 FIXME("Singe Frame trace complete\n");
525 DeleteFileA("C:\\D3DTRACE");
526 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
532 #if defined(SHOW_FRAME_MAKEUP)
533 FIXME("Singe Frame snapshots Finishing\n");
534 isDumpingFrames = FALSE;
536 FIXME("Disabling D3D Trace\n");
537 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
547 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
548 ICOM_THIS(IDirect3DDevice8Impl,iface);
549 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
550 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
552 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
553 FIXME("Only one backBuffer currently supported\n");
554 return D3DERR_INVALIDCALL;
557 /* Note inc ref on returned surface */
558 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
562 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
563 ICOM_THIS(IDirect3DDevice8Impl,iface);
564 FIXME("(%p) : stub\n", This);
567 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
569 ICOM_THIS(IDirect3DDevice8Impl,iface);
571 FIXME("(%p) : pRamp@%p\n", This, pRamp);
572 hDC = GetDC(This->win_handle);
573 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
574 ReleaseDC(This->win_handle, hDC);
577 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
579 ICOM_THIS(IDirect3DDevice8Impl,iface);
581 FIXME("(%p) : pRamp@%p\n", This, pRamp);
582 hDC = GetDC(This->win_handle);
583 GetDeviceGammaRamp(hDC, pRamp);
584 ReleaseDC(This->win_handle, hDC);
587 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
588 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
589 IDirect3DTexture8Impl *object;
594 ICOM_THIS(IDirect3DDevice8Impl,iface);
596 /* Allocate the storage for the device */
597 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);
598 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
599 object->lpVtbl = &Direct3DTexture8_Vtbl;
600 object->Device = This;
601 object->ResourceType = D3DRTYPE_TEXTURE;
603 object->width = Width;
604 object->height = Height;
605 object->levels = Levels;
606 object->usage = Usage;
607 object->format = Format;
609 /* Calculate levels for mip mapping */
614 while (tmpW > 1 && tmpH > 1) {
615 tmpW = max(1, tmpW / 2);
616 tmpH = max(1, tmpH / 2);
619 TRACE("Calculated levels = %d\n", object->levels);
622 /* Generate all the surfaces */
625 for (i = 0; i < object->levels; i++)
627 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
628 object->surfaces[i]->Container = (IUnknown*) object;
629 object->surfaces[i]->myDesc.Usage = Usage;
630 object->surfaces[i]->myDesc.Pool = Pool;
632 * As written in msdn in IDirect3DTexture8::LockRect
633 * Textures created in D3DPOOL_DEFAULT are not lockable.
635 if (D3DPOOL_DEFAULT == Pool) {
636 object->surfaces[i]->lockable = FALSE;
639 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
640 tmpW = max(1, tmpW / 2);
641 tmpH = max(1, tmpH / 2);
644 *ppTexture = (LPDIRECT3DTEXTURE8) object;
645 TRACE("(%p) : Created texture %p\n", This, object);
648 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
649 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
650 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
652 IDirect3DVolumeTexture8Impl *object;
658 ICOM_THIS(IDirect3DDevice8Impl,iface);
660 /* Allocate the storage for it */
661 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));
662 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
663 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
664 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
665 object->Device = This;
668 object->width = Width;
669 object->height = Height;
670 object->depth = Depth;
671 object->levels = Levels;
672 object->usage = Usage;
673 object->format = Format;
675 /* Calculate levels for mip mapping */
681 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
682 tmpW = max(1, tmpW / 2);
683 tmpH = max(1, tmpH / 2);
684 tmpD = max(1, tmpD / 2);
687 TRACE("Calculated levels = %d\n", object->levels);
690 /* Generate all the surfaces */
695 for (i = 0; i < object->levels; i++)
697 IDirect3DVolume8Impl* volume;
699 /* Create the volume - No entry point for this seperately?? */
700 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
701 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
703 volume->lpVtbl = &Direct3DVolume8_Vtbl;
704 volume->Device = This;
705 volume->ResourceType = D3DRTYPE_VOLUME;
706 volume->Container = (IUnknown*) object;
709 volume->myDesc.Width = Width;
710 volume->myDesc.Height = Height;
711 volume->myDesc.Depth = Depth;
712 volume->myDesc.Format = Format;
713 volume->myDesc.Type = D3DRTYPE_VOLUME;
714 volume->myDesc.Pool = Pool;
715 volume->myDesc.Usage = Usage;
716 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
717 /* Note: Volume textures cannot be dxtn, hence no need to check here */
718 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
719 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
721 volume->lockable = TRUE;
722 volume->locked = FALSE;
723 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
724 volume->Dirty = FALSE;
725 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
727 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
728 This, Width, Height, Depth, Format, debug_d3dformat(Format),
729 volume, volume->allocatedMemory, volume->myDesc.Size);
731 tmpW = max(1, tmpW / 2);
732 tmpH = max(1, tmpH / 2);
733 tmpD = max(1, tmpD / 2);
736 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
737 TRACE("(%p) : Created volume texture %p\n", This, object);
740 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
741 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
743 IDirect3DCubeTexture8Impl *object;
744 ICOM_THIS(IDirect3DDevice8Impl,iface);
748 /* Allocate the storage for it */
749 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));
750 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
751 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
753 object->Device = This;
754 object->ResourceType = D3DRTYPE_CUBETEXTURE;
756 object->edgeLength = EdgeLength;
757 object->levels = Levels;
758 object->usage = Usage;
759 object->format = Format;
761 /* Calculate levels for mip mapping */
766 tmpW = max(1, tmpW / 2);
769 TRACE("Calculated levels = %d\n", object->levels);
772 /* Generate all the surfaces */
774 for (i = 0; i < object->levels; i++) {
775 /* Create the 6 faces */
776 for (j = 0; j < 6; j++) {
777 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
778 object->surfaces[j][i]->Container = (IUnknown*) object;
779 object->surfaces[j][i]->myDesc.Usage = Usage;
780 object->surfaces[j][i]->myDesc.Pool = Pool;
782 * As written in msdn in IDirect3DCubeTexture8::LockRect
783 * Textures created in D3DPOOL_DEFAULT are not lockable.
785 if (D3DPOOL_DEFAULT == Pool) {
786 object->surfaces[j][i]->lockable = FALSE;
789 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
791 tmpW = max(1, tmpW / 2);
794 TRACE("(%p) : Iface@%p\n", This, object);
795 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
798 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
799 IDirect3DVertexBuffer8Impl *object;
801 ICOM_THIS(IDirect3DDevice8Impl,iface);
803 /* Allocate the storage for the device */
804 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
805 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
806 object->Device = This;
807 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
809 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
810 object->currentDesc.Usage = Usage;
811 object->currentDesc.Pool = Pool;
812 object->currentDesc.FVF = FVF;
813 object->currentDesc.Size = Size;
815 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
817 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
821 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
822 IDirect3DIndexBuffer8Impl *object;
824 ICOM_THIS(IDirect3DDevice8Impl,iface);
825 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
827 /* Allocate the storage for the device */
828 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
829 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
830 object->Device = This;
832 object->ResourceType = D3DRTYPE_INDEXBUFFER;
834 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
835 object->currentDesc.Usage = Usage;
836 object->currentDesc.Pool = Pool;
837 object->currentDesc.Format = Format;
838 object->currentDesc.Size = Length;
840 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
842 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
844 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
848 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
849 IDirect3DSurface8Impl *object;
850 ICOM_THIS(IDirect3DDevice8Impl,iface);
852 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
853 if (NULL == object) {
855 return D3DERR_OUTOFVIDEOMEMORY;
857 *ppSurface = (LPDIRECT3DSURFACE8) object;
858 object->lpVtbl = &Direct3DSurface8_Vtbl;
859 object->Device = This;
860 object->ResourceType = D3DRTYPE_SURFACE;
861 object->Container = (IUnknown*) This;
864 object->myDesc.Width = Width;
865 object->myDesc.Height = Height;
866 object->myDesc.Format = Format;
867 object->myDesc.Type = D3DRTYPE_SURFACE;
868 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
869 object->myDesc.Pool = D3DPOOL_DEFAULT;
870 object->myDesc.MultiSampleType = MultiSample;
871 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
872 if (Format == D3DFMT_DXT1) {
873 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
875 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
877 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
878 object->lockable = Lockable;
879 object->locked = FALSE;
880 memset(&object->lockedRect, 0, sizeof(RECT));
881 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
883 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);
886 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
887 IDirect3DSurface8Impl *object;
889 ICOM_THIS(IDirect3DDevice8Impl,iface);
891 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
892 if (NULL == object) {
894 return D3DERR_OUTOFVIDEOMEMORY;
896 *ppSurface = (LPDIRECT3DSURFACE8) object;
897 object->lpVtbl = &Direct3DSurface8_Vtbl;
898 object->Device = This;
899 object->ResourceType = D3DRTYPE_SURFACE;
900 object->Container = (IUnknown*) This;
903 object->myDesc.Width = Width;
904 object->myDesc.Height = Height;
905 object->myDesc.Format = Format;
906 object->myDesc.Type = D3DRTYPE_SURFACE;
907 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
908 object->myDesc.Pool = D3DPOOL_DEFAULT;
909 object->myDesc.MultiSampleType = MultiSample;
910 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
911 if (Format == D3DFMT_DXT1) {
912 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
914 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
916 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
917 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
918 object->locked = FALSE;
919 memset(&object->lockedRect, 0, sizeof(RECT));
920 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
922 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);
925 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
926 IDirect3DSurface8Impl *object;
928 ICOM_THIS(IDirect3DDevice8Impl,iface);
930 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
931 *ppSurface = (LPDIRECT3DSURFACE8) object;
932 object->lpVtbl = &Direct3DSurface8_Vtbl;
933 object->Device = This;
934 object->ResourceType = D3DRTYPE_SURFACE;
935 object->Container = (IUnknown*) This;
938 object->myDesc.Width = Width;
939 object->myDesc.Height = Height;
940 object->myDesc.Format = Format;
941 object->myDesc.Type = D3DRTYPE_SURFACE;
942 object->myDesc.Usage = 0;
943 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
944 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
945 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
946 it is based around 4x4 pixel blocks it requires padding, so allocate enough
948 if (Format == D3DFMT_DXT1) {
949 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
950 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
951 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
952 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
954 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
956 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
957 object->lockable = TRUE;
958 object->locked = FALSE;
959 memset(&object->lockedRect, 0, sizeof(RECT));
960 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
962 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);
965 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
966 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
967 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
970 IDirect3DBaseTexture8* texture = NULL;
973 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
974 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
976 ICOM_THIS(IDirect3DDevice8Impl,iface);
977 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
978 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
980 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
981 a sample and doesnt seem to break anything as far as I can tell */
982 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
983 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
984 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
985 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
986 rc = D3DERR_INVALIDCALL;
988 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
989 TRACE("Converting dest to same format as source, since dest was unknown\n");
990 dst->myDesc.Format = src->myDesc.Format;
992 /* Convert container as well */
993 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
994 if (texture != NULL) {
995 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
996 /** Releasing texture after GetContainer */
997 IDirect3DBaseTexture8_Release(texture);
1002 /* Quick if complete copy ... */
1003 if (rc == D3D_OK && cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1005 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1007 D3DLOCKED_RECT lrSrc;
1008 D3DLOCKED_RECT lrDst;
1009 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1010 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1011 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1013 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1015 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1016 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1017 TRACE("Unlocked src and dst\n");
1021 FIXME("Wanted to copy all surfaces but size not compatible\n");
1022 rc = D3DERR_INVALIDCALL;
1028 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1030 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1033 /* Copy rect by rect */
1034 for (i = 0; i < cRects; i++) {
1035 CONST RECT* r = &pSourceRectsArray[i];
1036 CONST POINT* p = &pDestPointsArray[i];
1039 D3DLOCKED_RECT lrSrc;
1040 D3DLOCKED_RECT lrDst;
1044 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1045 if (src->myDesc.Format == D3DFMT_DXT1) {
1046 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1048 copyperline = ((r->right - r->left) * bytesPerPixel);
1050 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1051 dest_rect.left = p->x;
1052 dest_rect.top = p->y;
1053 dest_rect.right = p->x + (r->right - r->left);
1054 dest_rect.left = p->y + (r->bottom - r->top);
1055 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1056 TRACE("Locked src and dst\n");
1058 /* Find where to start */
1059 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1060 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1063 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1064 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1065 TRACE("Unlocked src and dst\n");
1070 FIXME("Wanted to copy partial surfaces not implemented\n");
1071 rc = D3DERR_INVALIDCALL;
1078 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1079 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1080 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1081 D3DRESOURCETYPE srcType;
1082 D3DRESOURCETYPE dstType;
1084 ICOM_THIS(IDirect3DDevice8Impl,iface);
1085 TRACE("(%p) : first try\n", This);
1087 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1088 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1090 if (srcType != dstType) {
1091 return D3DERR_INVALIDCALL;
1093 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1094 return D3DERR_INVALIDCALL;
1096 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1097 return D3DERR_INVALIDCALL;
1099 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1100 /** Only copy Dirty textures */
1101 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1102 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1103 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1106 for (i = skipLevels; i < srcLevelCnt; ++i) {
1110 case D3DRTYPE_TEXTURE:
1112 IDirect3DSurface8* srcSur = NULL;
1113 IDirect3DSurface8* dstSur = NULL;
1114 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1115 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1117 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1118 about dst with less levels than the source?) */
1119 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1121 IDirect3DSurface8Impl_Release(srcSur);
1122 IDirect3DSurface8Impl_Release(dstSur);
1125 case D3DRTYPE_VOLUMETEXTURE:
1127 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1130 case D3DRTYPE_CUBETEXTURE:
1132 IDirect3DSurface8* srcSur = NULL;
1133 IDirect3DSurface8* dstSur = NULL;
1134 for (j = 0; j < 5; ++j) {
1135 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1136 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1137 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1138 IDirect3DSurface8Impl_Release(srcSur);
1139 IDirect3DSurface8Impl_Release(dstSur);
1147 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1152 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1154 D3DLOCKED_RECT lockedRect;
1159 ICOM_THIS(IDirect3DDevice8Impl,iface);
1161 FIXME("(%p) : see if behavior correct\n", This);
1163 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1164 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1165 return D3DERR_INVALIDCALL;
1168 wantedRect.left = 0;
1170 wantedRect.right = This->PresentParms.BackBufferWidth;
1171 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1173 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1175 ERR("(%p) : cannot lock surface\n", This);
1176 return D3DERR_INVALIDCALL;
1182 vcheckGLcall("glFlush");
1183 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1184 vcheckGLcall("glIntegerv");
1185 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1186 vcheckGLcall("glIntegerv");
1188 glReadBuffer(GL_FRONT);
1189 vcheckGLcall("glReadBuffer");
1190 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1191 vcheckGLcall("glPixelStorei");
1195 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1196 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1197 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1198 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1199 vcheckGLcall("glReadPixels");
1202 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1203 vcheckGLcall("glPixelStorei");
1204 glReadBuffer(prev_read);
1205 vcheckGLcall("glReadBuffer");
1209 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1212 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1215 ICOM_THIS(IDirect3DDevice8Impl,iface);
1217 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1218 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1222 IDirect3DDevice8Impl_CleanRender(iface);
1224 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1225 IDirect3DSurface8Impl* tmp;
1227 TRACE("retoring SetRenderTarget defaults\n");
1229 tmp = This->renderTarget;
1230 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1231 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1232 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1234 tmp = This->stencilBufferTarget;
1235 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1236 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1237 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1242 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1244 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1249 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1250 ICOM_THIS(IDirect3DDevice8Impl,iface);
1252 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1254 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1255 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1260 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1261 ICOM_THIS(IDirect3DDevice8Impl,iface);
1263 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1265 /* Note inc ref on returned surface */
1266 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1267 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1272 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1273 ICOM_THIS(IDirect3DDevice8Impl,iface);
1274 TRACE("(%p) : stub\n", This);
1277 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1278 IDirect3DBaseTexture8* cont = NULL;
1280 ICOM_THIS(IDirect3DDevice8Impl,iface);
1281 TRACE("(%p)\n", This);
1286 checkGLcall("glFlush");
1288 /* Useful for debugging sometimes!
1289 printf("Hit Enter ...\n");
1292 if (This->frontBuffer != This->renderTarget) {
1295 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1296 vcheckGLcall("glIntegerv");
1297 glReadBuffer(GL_BACK);
1298 vcheckGLcall("glReadBuffer");
1301 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1303 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1306 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1308 This->renderTarget->myDesc.Height - j - 1,
1309 This->renderTarget->myDesc.Width,
1311 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1312 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1313 This->renderTarget->allocatedMemory + j * pitch);
1314 vcheckGLcall("glReadPixels");
1317 glReadBuffer(prev_read);
1318 vcheckGLcall("glReadBuffer");
1321 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1322 if (SUCCEEDED(hr) && NULL != cont) {
1323 /** always dirtify for now. we must find a better way to see that surface have been modified */
1324 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1325 IDirect3DBaseTexture8_PreLoad(cont);
1326 IDirect3DBaseTexture8Impl_Release(cont);
1334 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1335 ICOM_THIS(IDirect3DDevice8Impl,iface);
1337 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1338 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1339 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1340 GLbitfield glMask = 0;
1341 GLboolean old_ztest;
1342 GLfloat old_z_clear_value;
1343 GLint old_stencil_clear_value;
1344 GLfloat old_color_clear_value[4];
1346 CONST D3DRECT* curRect;
1348 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1349 Count, pRects, Flags, Z, Stencil);
1352 glEnable(GL_SCISSOR_TEST);
1353 checkGLcall("glEnable GL_SCISSOR_TEST");
1354 if (Count > 0 && pRects) {
1360 /* Only set the values up once, as they are not changing */
1361 if (Flags & D3DCLEAR_STENCIL) {
1362 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1363 glClearStencil(Stencil);
1364 checkGLcall("glClearStencil");
1365 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1368 if (Flags & D3DCLEAR_ZBUFFER) {
1369 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1370 glDepthMask(GL_TRUE);
1371 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1373 checkGLcall("glClearDepth");
1374 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1377 if (Flags & D3DCLEAR_TARGET) {
1378 TRACE("Clearing screen with glClear to color %lx\n", Color);
1379 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1380 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1381 ((Color >> 8) & 0xFF) / 255.0f,
1382 ((Color >> 0) & 0xFF) / 255.0f,
1383 ((Color >> 24) & 0xFF) / 255.0f);
1384 checkGLcall("glClearColor");
1385 glMask = glMask | GL_COLOR_BUFFER_BIT;
1388 /* Now process each rect in turn */
1389 for (i = 0; i < Count || i == 0; i++) {
1392 /* Note gl uses lower left, width/height */
1393 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1394 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1395 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1396 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1397 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1398 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1399 checkGLcall("glScissor");
1401 glScissor(This->StateBlock->viewport.X,
1402 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1403 This->StateBlock->viewport.Width,
1404 This->StateBlock->viewport.Height);
1405 checkGLcall("glScissor");
1408 /* Clear the selected rectangle (or full screen) */
1410 checkGLcall("glClear");
1412 /* Step to the next rectangle */
1413 if (curRect) curRect = curRect + sizeof(D3DRECT);
1416 /* Restore the old values (why..?) */
1417 if (Flags & D3DCLEAR_STENCIL) {
1418 glClearStencil(old_stencil_clear_value);
1420 if (Flags & D3DCLEAR_ZBUFFER) {
1421 glDepthMask(old_ztest);
1422 glClearDepth(old_z_clear_value);
1424 if (Flags & D3DCLEAR_TARGET) {
1425 glClearColor(old_color_clear_value[0],
1426 old_color_clear_value[1],
1427 old_color_clear_value[2],
1428 old_color_clear_value[3]);
1431 glDisable(GL_SCISSOR_TEST);
1432 checkGLcall("glDisable");
1437 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1438 ICOM_THIS(IDirect3DDevice8Impl,iface);
1441 /* Most of this routine, comments included copied from ddraw tree initially: */
1442 TRACE("(%p) : State=%d\n", This, d3dts);
1444 /* Handle recording of state blocks */
1445 if (This->isRecordingState) {
1446 TRACE("Recording... not performing anything\n");
1447 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1448 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1449 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1454 * if the new matrix is the same as the current one,
1455 * we cut off any further processing. this seems to be a reasonable
1456 * optimization because as was noticed, some apps (warcraft3 for example)
1457 * tend towards setting the same matrix repeatedly for some dumb reason.
1459 * From here on we assume that the new matrix is different, wherever it matters
1462 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1463 TRACE("The app is setting the same matrix over again\n");
1466 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1470 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1471 where ViewMat = Camera space, WorldMat = world space.
1473 In OpenGL, camera and world space is combined into GL_MODELVIEW
1474 matrix. The Projection matrix stay projection matrix.
1477 /* Capture the times we can just ignore the change */
1478 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1479 This->modelview_valid = FALSE;
1482 } else if (d3dts == D3DTS_PROJECTION) {
1483 This->proj_valid = FALSE;
1486 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1487 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1488 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1492 /* Chances are we really are going to have to change a matrix */
1495 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1496 if (d3dts < GL_LIMITS(textures)) {
1497 int tex = d3dts - D3DTS_TEXTURE0;
1498 #if defined(GL_VERSION_1_3)
1499 glActiveTexture(GL_TEXTURE0 + tex);
1501 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1503 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1506 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1508 PLIGHTINFOEL *lightChain = NULL;
1509 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1510 This->modelview_valid = FALSE;
1511 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1512 glMatrixMode(GL_MODELVIEW);
1513 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1515 glLoadMatrixf((float *)lpmatrix);
1516 checkGLcall("glLoadMatrixf(...)");
1518 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1519 * NOTE: We have to reset the positions even if the light/plane is not currently
1520 * enabled, since the call to enable it will not reset the position.
1521 * NOTE2: Apparently texture transforms do NOT need reapplying
1525 lightChain = This->StateBlock->lights;
1526 while (lightChain && lightChain->glIndex != -1) {
1527 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1528 checkGLcall("glLightfv posn");
1529 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1530 checkGLcall("glLightfv dirn");
1531 lightChain = lightChain->next;
1533 /* Reset Clipping Planes if clipping is enabled */
1534 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1535 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1536 checkGLcall("glClipPlane");
1540 } else { /* What was requested!?? */
1541 WARN("invalid matrix specified: %i\n", d3dts);
1545 /* Release lock, all done */
1550 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1551 ICOM_THIS(IDirect3DDevice8Impl,iface);
1552 TRACE("(%p) : for State %d\n", This, State);
1553 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1557 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1558 D3DMATRIX *mat = NULL;
1561 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1562 but works regardless of recording being on.
1563 If this is found to be wrong, change to StateBlock. */
1564 ICOM_THIS(IDirect3DDevice8Impl,iface);
1565 TRACE("(%p) : For state %u\n", This, State);
1567 if (State < HIGHEST_TRANSFORMSTATE)
1569 mat = &This->UpdateStateBlock->transforms[State];
1571 FIXME("Unhandled transform state!!\n");
1574 /* Copied from ddraw code: */
1575 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);
1576 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);
1577 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);
1578 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);
1580 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);
1581 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);
1582 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);
1583 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);
1585 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);
1586 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);
1587 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);
1588 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);
1590 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);
1591 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);
1592 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);
1593 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);
1595 /* Apply change via set transform - will reapply to eg. lights this way */
1596 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1599 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1600 ICOM_THIS(IDirect3DDevice8Impl,iface);
1602 TRACE("(%p)\n", This);
1603 This->UpdateStateBlock->Changed.viewport = TRUE;
1604 This->UpdateStateBlock->Set.viewport = TRUE;
1605 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1607 /* Handle recording of state blocks */
1608 if (This->isRecordingState) {
1609 TRACE("Recording... not performing anything\n");
1615 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1616 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1618 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1619 checkGLcall("glDepthRange");
1620 /* Note: GL requires lower left, DirectX supplies upper left */
1621 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1622 pViewport->Width, pViewport->Height);
1623 checkGLcall("glViewport");
1630 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1631 ICOM_THIS(IDirect3DDevice8Impl,iface);
1632 TRACE("(%p)\n", This);
1633 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1637 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1638 ICOM_THIS(IDirect3DDevice8Impl,iface);
1640 This->UpdateStateBlock->Changed.material = TRUE;
1641 This->UpdateStateBlock->Set.material = TRUE;
1642 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1644 /* Handle recording of state blocks */
1645 if (This->isRecordingState) {
1646 TRACE("Recording... not performing anything\n");
1651 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1652 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1653 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1654 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1655 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1657 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1658 checkGLcall("glMaterialfv");
1659 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1660 checkGLcall("glMaterialfv");
1662 /* Only change material color if specular is enabled, otherwise it is set to black */
1663 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1664 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1665 checkGLcall("glMaterialfv");
1667 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1668 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1669 checkGLcall("glMaterialfv");
1671 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1672 checkGLcall("glMaterialfv");
1673 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1674 checkGLcall("glMaterialf");
1679 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1680 ICOM_THIS(IDirect3DDevice8Impl,iface);
1681 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1682 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1683 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1684 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1685 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1686 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1690 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1691 you can reference any indexes you want as long as that number max are enabled are any
1692 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1693 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1694 but when recording, just build a chain pretty much of commands to be replayed. */
1696 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1698 PLIGHTINFOEL *object, *temp;
1700 ICOM_THIS(IDirect3DDevice8Impl,iface);
1701 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1703 /* If recording state block, just add to end of lights chain */
1704 if (This->isRecordingState) {
1705 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1706 if (NULL == object) {
1707 return D3DERR_OUTOFVIDEOMEMORY;
1709 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1710 object->OriginalIndex = Index;
1711 object->glIndex = -1;
1712 object->changed = TRUE;
1714 /* Add to the END of the chain of lights changes to be replayed */
1715 if (This->UpdateStateBlock->lights == NULL) {
1716 This->UpdateStateBlock->lights = object;
1718 temp = This->UpdateStateBlock->lights;
1719 while (temp->next != NULL) temp=temp->next;
1720 temp->next = object;
1722 TRACE("Recording... not performing anything more\n");
1726 /* Ok, not recording any longer so do real work */
1727 object = This->StateBlock->lights;
1728 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1730 /* If we didnt find it in the list of lights, time to add it */
1731 if (object == NULL) {
1732 PLIGHTINFOEL *insertAt,*prevPos;
1734 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1735 if (NULL == object) {
1736 return D3DERR_OUTOFVIDEOMEMORY;
1738 object->OriginalIndex = Index;
1739 object->glIndex = -1;
1741 /* Add it to the front of list with the idea that lights will be changed as needed
1742 BUT after any lights currently assigned GL indexes */
1743 insertAt = This->StateBlock->lights;
1745 while (insertAt != NULL && insertAt->glIndex != -1) {
1747 insertAt = insertAt->next;
1750 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1751 This->StateBlock->lights = object;
1752 } else if (insertAt == NULL) { /* End of list */
1753 prevPos->next = object;
1754 object->prev = prevPos;
1755 } else { /* Middle of chain */
1756 if (prevPos == NULL) {
1757 This->StateBlock->lights = object;
1759 prevPos->next = object;
1761 object->prev = prevPos;
1762 object->next = insertAt;
1763 insertAt->prev = object;
1767 /* Initialze the object */
1768 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,
1769 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1770 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1771 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1772 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1773 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1774 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1776 /* Save away the information */
1777 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1779 switch (pLight->Type) {
1780 case D3DLIGHT_POINT:
1782 object->lightPosn[0] = pLight->Position.x;
1783 object->lightPosn[1] = pLight->Position.y;
1784 object->lightPosn[2] = pLight->Position.z;
1785 object->lightPosn[3] = 1.0f;
1786 object->cutoff = 180.0f;
1792 object->lightPosn[0] = pLight->Position.x;
1793 object->lightPosn[1] = pLight->Position.y;
1794 object->lightPosn[2] = pLight->Position.z;
1795 object->lightPosn[3] = 1.0;
1798 object->lightDirn[0] = pLight->Direction.x;
1799 object->lightDirn[1] = pLight->Direction.y;
1800 object->lightDirn[2] = pLight->Direction.z;
1801 object->lightDirn[3] = 1.0;
1804 * opengl-ish and d3d-ish spot lights use too different models for the
1805 * light "intensity" as a function of the angle towards the main light direction,
1806 * so we only can approximate very roughly.
1807 * however spot lights are rather rarely used in games (if ever used at all).
1808 * furthermore if still used, probably nobody pays attention to such details.
1810 if (pLight->Falloff == 0) {
1813 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1815 if (rho < 0.0001) rho = 0.0001f;
1816 object->exponent = -0.3/log(cos(rho/2));
1817 object->cutoff = pLight->Phi*90/M_PI;
1822 case D3DLIGHT_DIRECTIONAL:
1824 object->lightPosn[0] = -pLight->Direction.x;
1825 object->lightPosn[1] = -pLight->Direction.y;
1826 object->lightPosn[2] = -pLight->Direction.z;
1827 object->lightPosn[3] = 0.0;
1828 object->exponent = 0.0f;
1829 object->cutoff = 180.0f;
1833 FIXME("Unrecognized light type %d\n", pLight->Type);
1836 /* Update the live definitions if the light is currently assigned a glIndex */
1837 if (object->glIndex != -1) {
1838 setup_light(iface, object->glIndex, object);
1842 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1843 PLIGHTINFOEL *lightInfo = NULL;
1844 ICOM_THIS(IDirect3DDevice8Impl,iface);
1845 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1847 /* Locate the light in the live lights */
1848 lightInfo = This->StateBlock->lights;
1849 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1851 if (lightInfo == NULL) {
1852 TRACE("Light information requested but light not defined\n");
1853 return D3DERR_INVALIDCALL;
1856 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1859 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1860 PLIGHTINFOEL *lightInfo = NULL;
1861 ICOM_THIS(IDirect3DDevice8Impl,iface);
1862 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1864 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1865 if (This->isRecordingState) {
1866 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1867 if (NULL == lightInfo) {
1868 return D3DERR_OUTOFVIDEOMEMORY;
1870 lightInfo->OriginalIndex = Index;
1871 lightInfo->glIndex = -1;
1872 lightInfo->enabledChanged = TRUE;
1874 /* Add to the END of the chain of lights changes to be replayed */
1875 if (This->UpdateStateBlock->lights == NULL) {
1876 This->UpdateStateBlock->lights = lightInfo;
1878 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1879 while (temp->next != NULL) temp=temp->next;
1880 temp->next = lightInfo;
1882 TRACE("Recording... not performing anything more\n");
1886 /* Not recording... So, locate the light in the live lights */
1887 lightInfo = This->StateBlock->lights;
1888 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1890 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1891 if (lightInfo == NULL) {
1892 D3DLIGHT8 lightParms;
1893 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1894 wait until someone confirms it seems to work! */
1895 TRACE("Light enabled requested but light not defined, so defining one!\n");
1896 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1897 lightParms.Diffuse.r = 1.0;
1898 lightParms.Diffuse.g = 1.0;
1899 lightParms.Diffuse.b = 1.0;
1900 lightParms.Diffuse.a = 0.0;
1901 lightParms.Specular.r = 0.0;
1902 lightParms.Specular.g = 0.0;
1903 lightParms.Specular.b = 0.0;
1904 lightParms.Specular.a = 0.0;
1905 lightParms.Ambient.r = 0.0;
1906 lightParms.Ambient.g = 0.0;
1907 lightParms.Ambient.b = 0.0;
1908 lightParms.Ambient.a = 0.0;
1909 lightParms.Position.x = 0.0;
1910 lightParms.Position.y = 0.0;
1911 lightParms.Position.z = 0.0;
1912 lightParms.Direction.x = 0.0;
1913 lightParms.Direction.y = 0.0;
1914 lightParms.Direction.z = 1.0;
1915 lightParms.Range = 0.0;
1916 lightParms.Falloff = 0.0;
1917 lightParms.Attenuation0 = 0.0;
1918 lightParms.Attenuation1 = 0.0;
1919 lightParms.Attenuation2 = 0.0;
1920 lightParms.Theta = 0.0;
1921 lightParms.Phi = 0.0;
1922 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1924 /* Search for it again! Should be fairly quick as near head of list */
1925 lightInfo = This->StateBlock->lights;
1926 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1927 if (lightInfo == NULL) {
1928 FIXME("Adding default lights has failed dismally\n");
1929 return D3DERR_INVALIDCALL;
1933 /* OK, we now have a light... */
1934 if (Enable == FALSE) {
1936 /* If we are disabling it, check it was enabled, and
1937 still only do something if it has assigned a glIndex (which it should have!) */
1938 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1939 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1941 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1942 checkGLcall("glDisable GL_LIGHT0+Index");
1945 TRACE("Nothing to do as light was not enabled\n");
1947 lightInfo->lightEnabled = FALSE;
1950 /* We are enabling it. If it is enabled, its really simple */
1951 if (lightInfo->lightEnabled == TRUE) {
1953 TRACE("Nothing to do as light was enabled\n");
1955 /* If it already has a glIndex, its still simple */
1956 } else if (lightInfo->glIndex != -1) {
1957 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1958 lightInfo->lightEnabled = TRUE;
1960 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1961 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1964 /* Otherwise got to find space - lights are ordered gl indexes first */
1966 PLIGHTINFOEL *bsf = NULL;
1967 PLIGHTINFOEL *pos = This->StateBlock->lights;
1968 PLIGHTINFOEL *prev = NULL;
1972 /* Try to minimize changes as much as possible */
1973 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1975 /* Try to remember which index can be replaced if necessary */
1976 if (bsf==NULL && pos->lightEnabled == FALSE) {
1977 /* Found a light we can replace, save as best replacement */
1981 /* Step to next space */
1987 /* If we have too many active lights, fail the call */
1988 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1989 FIXME("Program requests too many concurrent lights\n");
1990 return D3DERR_INVALIDCALL;
1992 /* If we have allocated all lights, but not all are enabled,
1993 reuse one which is not enabled */
1994 } else if (Index == This->maxConcurrentLights) {
1995 /* use bsf - Simply swap the new light and the BSF one */
1996 PLIGHTINFOEL *bsfNext = bsf->next;
1997 PLIGHTINFOEL *bsfPrev = bsf->prev;
2000 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2001 if (bsf->prev != NULL) {
2002 bsf->prev->next = lightInfo;
2004 This->StateBlock->lights = lightInfo;
2007 /* If not side by side, lots of chains to update */
2008 if (bsf->next != lightInfo) {
2009 lightInfo->prev->next = bsf;
2010 bsf->next->prev = lightInfo;
2011 bsf->next = lightInfo->next;
2012 bsf->prev = lightInfo->prev;
2013 lightInfo->next = bsfNext;
2014 lightInfo->prev = bsfPrev;
2018 bsf->prev = lightInfo;
2019 bsf->next = lightInfo->next;
2020 lightInfo->next = bsf;
2021 lightInfo->prev = bsfPrev;
2026 glIndex = bsf->glIndex;
2028 lightInfo->glIndex = glIndex;
2029 lightInfo->lightEnabled = TRUE;
2031 /* Finally set up the light in gl itself */
2032 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2034 setup_light(iface, glIndex, lightInfo);
2035 glEnable(GL_LIGHT0 + glIndex);
2036 checkGLcall("glEnable GL_LIGHT0 new setup");
2039 /* If we reached the end of the allocated lights, with space in the
2040 gl lights, setup a new light */
2041 } else if (pos->glIndex == -1) {
2043 /* We reached the end of the allocated gl lights, so already
2044 know the index of the next one! */
2046 lightInfo->glIndex = glIndex;
2047 lightInfo->lightEnabled = TRUE;
2049 /* In an ideal world, its already in the right place */
2050 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2051 /* No need to move it */
2053 /* Remove this light from the list */
2054 lightInfo->prev->next = lightInfo->next;
2055 if (lightInfo->next != NULL) {
2056 lightInfo->next->prev = lightInfo->prev;
2059 /* Add in at appropriate place (inbetween prev and pos) */
2060 lightInfo->prev = prev;
2061 lightInfo->next = pos;
2063 This->StateBlock->lights = lightInfo;
2065 prev->next = lightInfo;
2068 pos->prev = lightInfo;
2072 /* Finally set up the light in gl itself */
2073 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2075 setup_light(iface, glIndex, lightInfo);
2076 glEnable(GL_LIGHT0 + glIndex);
2077 checkGLcall("glEnable GL_LIGHT0 new setup");
2085 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2087 PLIGHTINFOEL *lightInfo = NULL;
2088 ICOM_THIS(IDirect3DDevice8Impl,iface);
2089 TRACE("(%p) : for idx(%ld)\n", This, Index);
2091 /* Locate the light in the live lights */
2092 lightInfo = This->StateBlock->lights;
2093 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2095 if (lightInfo == NULL) {
2096 TRACE("Light enabled state requested but light not defined\n");
2097 return D3DERR_INVALIDCALL;
2099 *pEnable = lightInfo->lightEnabled;
2102 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2103 ICOM_THIS(IDirect3DDevice8Impl,iface);
2104 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2106 /* Validate Index */
2107 if (Index >= GL_LIMITS(clipplanes)) {
2108 TRACE("Application has requested clipplane this device doesnt support\n");
2109 return D3DERR_INVALIDCALL;
2112 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2113 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2114 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2115 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2116 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2117 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2119 /* Handle recording of state blocks */
2120 if (This->isRecordingState) {
2121 TRACE("Recording... not performing anything\n");
2129 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2130 glMatrixMode(GL_MODELVIEW);
2132 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2134 TRACE("Clipplane [%f,%f,%f,%f]\n",
2135 This->UpdateStateBlock->clipplane[Index][0],
2136 This->UpdateStateBlock->clipplane[Index][1],
2137 This->UpdateStateBlock->clipplane[Index][2],
2138 This->UpdateStateBlock->clipplane[Index][3]);
2139 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2140 checkGLcall("glClipPlane");
2148 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2149 ICOM_THIS(IDirect3DDevice8Impl,iface);
2150 TRACE("(%p) : for idx %ld\n", This, Index);
2152 /* Validate Index */
2153 if (Index >= GL_LIMITS(clipplanes)) {
2154 TRACE("Application has requested clipplane this device doesnt support\n");
2155 return D3DERR_INVALIDCALL;
2158 pPlane[0] = This->StateBlock->clipplane[Index][0];
2159 pPlane[1] = This->StateBlock->clipplane[Index][1];
2160 pPlane[2] = This->StateBlock->clipplane[Index][2];
2161 pPlane[3] = This->StateBlock->clipplane[Index][3];
2164 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2165 ICOM_THIS(IDirect3DDevice8Impl,iface);
2166 DWORD OldValue = This->StateBlock->renderstate[State];
2168 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2169 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2170 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2171 This->UpdateStateBlock->renderstate[State] = Value;
2173 /* Handle recording of state blocks */
2174 if (This->isRecordingState) {
2175 TRACE("Recording... not performing anything\n");
2182 case D3DRS_FILLMODE :
2183 switch ((D3DFILLMODE) Value) {
2184 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2185 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2186 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2188 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2190 checkGLcall("glPolygonMode (fillmode)");
2193 case D3DRS_LIGHTING :
2195 glEnable(GL_LIGHTING);
2196 checkGLcall("glEnable GL_LIGHTING");
2198 glDisable(GL_LIGHTING);
2199 checkGLcall("glDisable GL_LIGHTING");
2203 case D3DRS_ZENABLE :
2204 switch ((D3DZBUFFERTYPE) Value) {
2206 glDisable(GL_DEPTH_TEST);
2207 checkGLcall("glDisable GL_DEPTH_TEST");
2210 glEnable(GL_DEPTH_TEST);
2211 checkGLcall("glEnable GL_DEPTH_TEST");
2216 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2220 case D3DRS_CULLMODE :
2222 /* If we are culling "back faces with clockwise vertices" then
2223 set front faces to be counter clockwise and enable culling
2225 switch ((D3DCULL) Value) {
2227 glDisable(GL_CULL_FACE);
2228 checkGLcall("glDisable GL_CULL_FACE");
2231 glEnable(GL_CULL_FACE);
2232 checkGLcall("glEnable GL_CULL_FACE");
2233 glFrontFace(GL_CCW);
2234 checkGLcall("glFrontFace GL_CCW");
2235 glCullFace(GL_BACK);
2238 glEnable(GL_CULL_FACE);
2239 checkGLcall("glEnable GL_CULL_FACE");
2241 checkGLcall("glFrontFace GL_CW");
2242 glCullFace(GL_BACK);
2245 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2249 case D3DRS_SHADEMODE :
2250 switch ((D3DSHADEMODE) Value) {
2252 glShadeModel(GL_FLAT);
2253 checkGLcall("glShadeModel");
2255 case D3DSHADE_GOURAUD:
2256 glShadeModel(GL_SMOOTH);
2257 checkGLcall("glShadeModel");
2259 case D3DSHADE_PHONG:
2260 FIXME("D3DSHADE_PHONG isnt supported?\n");
2263 return D3DERR_INVALIDCALL;
2265 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2269 case D3DRS_DITHERENABLE :
2271 glEnable(GL_DITHER);
2272 checkGLcall("glEnable GL_DITHER");
2274 glDisable(GL_DITHER);
2275 checkGLcall("glDisable GL_DITHER");
2279 case D3DRS_ZWRITEENABLE :
2282 checkGLcall("glDepthMask");
2285 checkGLcall("glDepthMask");
2291 int glParm = GL_LESS;
2293 switch ((D3DCMPFUNC) Value) {
2294 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2295 case D3DCMP_LESS: glParm=GL_LESS; break;
2296 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2297 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2298 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2299 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2300 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2301 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2303 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2305 glDepthFunc(glParm);
2306 checkGLcall("glDepthFunc");
2310 case D3DRS_AMBIENT :
2313 D3DCOLORTOGLFLOAT4(Value, col);
2314 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2315 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2316 checkGLcall("glLightModel for MODEL_AMBIENT");
2321 case D3DRS_ALPHABLENDENABLE :
2324 checkGLcall("glEnable GL_BLEND");
2326 glDisable(GL_BLEND);
2327 checkGLcall("glDisable GL_BLEND");
2331 case D3DRS_SRCBLEND :
2332 case D3DRS_DESTBLEND :
2334 int newVal = GL_ZERO;
2336 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2337 case D3DBLEND_ONE : newVal = GL_ONE; break;
2338 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2339 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2340 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2341 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2342 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2343 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2344 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2345 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2346 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2348 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2349 This->srcBlend = newVal;
2350 This->dstBlend = newVal;
2353 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2354 This->srcBlend = newVal;
2355 This->dstBlend = newVal;
2358 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2361 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2362 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2363 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2364 glBlendFunc(This->srcBlend, This->dstBlend);
2366 checkGLcall("glBlendFunc");
2370 case D3DRS_ALPHATESTENABLE :
2372 glEnable(GL_ALPHA_TEST);
2373 checkGLcall("glEnable GL_ALPHA_TEST");
2375 glDisable(GL_ALPHA_TEST);
2376 checkGLcall("glDisable GL_ALPHA_TEST");
2380 case D3DRS_ALPHAFUNC :
2382 int glParm = GL_LESS;
2383 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2385 switch ((D3DCMPFUNC) Value) {
2386 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2387 case D3DCMP_LESS: glParm = GL_LESS; break;
2388 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2389 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2390 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2391 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2392 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2393 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2395 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2397 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2398 glAlphaFunc(glParm, ref);
2399 This->alphafunc = glParm;
2400 checkGLcall("glAlphaFunc");
2404 case D3DRS_ALPHAREF :
2406 int glParm = This->alphafunc;
2409 ref = ((float) Value) / 255.0f;
2410 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2411 glAlphaFunc(glParm, ref);
2412 checkGLcall("glAlphaFunc");
2416 case D3DRS_CLIPPLANEENABLE :
2417 case D3DRS_CLIPPING :
2419 /* Ensure we only do the changed clip planes */
2420 DWORD enable = 0xFFFFFFFF;
2421 DWORD disable = 0x00000000;
2423 /* If enabling / disabling all */
2424 if (State == D3DRS_CLIPPING) {
2426 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2429 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2433 enable = Value & ~OldValue;
2434 disable = ~Value & OldValue;
2437 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2438 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2439 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2440 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2441 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2442 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2444 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2445 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2446 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2447 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2448 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2449 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2453 case D3DRS_BLENDOP :
2455 int glParm = GL_FUNC_ADD;
2457 switch ((D3DBLENDOP) Value) {
2458 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2459 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2460 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2461 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2462 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2464 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2466 TRACE("glBlendEquation(%x)\n", glParm);
2467 glBlendEquation(glParm);
2468 checkGLcall("glBlendEquation");
2472 case D3DRS_TEXTUREFACTOR :
2476 /* Note the texture color applies to all textures whereas
2477 GL_TEXTURE_ENV_COLOR applies to active only */
2479 D3DCOLORTOGLFLOAT4(Value, col);
2480 /* Set the default alpha blend color */
2481 glBlendColor(col[0], col[1], col[2], col[3]);
2482 checkGLcall("glBlendColor");
2484 /* And now the default texture color as well */
2485 for (i = 0; i < GL_LIMITS(textures); i++) {
2487 /* Note the D3DRS value applies to all textures, but GL has one
2488 per texture, so apply it now ready to be used! */
2489 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2490 #if defined(GL_VERSION_1_3)
2491 glActiveTexture(GL_TEXTURE0 + i);
2493 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2495 checkGLcall("Activate texture.. to update const color");
2497 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2500 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2501 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2506 case D3DRS_SPECULARENABLE :
2508 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2509 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2510 specular color. This is wrong:
2511 Separate specular color means the specular colour is maintained separately, whereas
2512 single color means it is merged in. However in both cases they are being used to
2514 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2515 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2519 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2520 checkGLcall("glMaterialfv");
2521 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2522 glEnable(GL_COLOR_SUM_EXT);
2524 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2526 checkGLcall("glEnable(GL_COLOR_SUM)");
2528 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2530 /* for the case of enabled lighting: */
2531 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2532 checkGLcall("glMaterialfv");
2534 /* for the case of disabled lighting: */
2535 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2536 glDisable(GL_COLOR_SUM_EXT);
2538 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2540 checkGLcall("glDisable(GL_COLOR_SUM)");
2545 case D3DRS_STENCILENABLE :
2547 glEnable(GL_STENCIL_TEST);
2548 checkGLcall("glEnable GL_STENCIL_TEST");
2550 glDisable(GL_STENCIL_TEST);
2551 checkGLcall("glDisable GL_STENCIL_TEST");
2555 case D3DRS_STENCILFUNC :
2557 int glParm = GL_ALWAYS;
2558 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2559 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2561 switch ((D3DCMPFUNC) Value) {
2562 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2563 case D3DCMP_LESS: glParm=GL_LESS; break;
2564 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2565 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2566 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2567 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2568 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2569 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2571 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2573 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2574 This->stencilfunc = glParm;
2575 glStencilFunc(glParm, ref, mask);
2576 checkGLcall("glStencilFunc");
2580 case D3DRS_STENCILREF :
2582 int glParm = This->stencilfunc;
2584 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2587 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2588 glStencilFunc(glParm, ref, mask);
2589 checkGLcall("glStencilFunc");
2593 case D3DRS_STENCILMASK :
2595 int glParm = This->stencilfunc;
2596 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2597 GLuint mask = Value;
2599 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2600 glStencilFunc(glParm, ref, mask);
2601 checkGLcall("glStencilFunc");
2605 case D3DRS_STENCILFAIL :
2611 fail = StencilOp(Value);
2612 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2613 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2614 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2615 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2617 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2618 glStencilOp(fail, zfail, zpass);
2619 checkGLcall("glStencilOp(fail, zfail, zpass);");
2622 case D3DRS_STENCILZFAIL :
2628 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2629 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2630 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2631 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2632 zfail = StencilOp(Value);
2634 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2635 glStencilOp(fail, zfail, zpass);
2636 checkGLcall("glStencilOp(fail, zfail, zpass);");
2639 case D3DRS_STENCILPASS :
2645 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2646 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2647 zpass = StencilOp(Value);
2648 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2649 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2651 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2652 glStencilOp(fail, zfail, zpass);
2653 checkGLcall("glStencilOp(fail, zfail, zpass);");
2657 case D3DRS_STENCILWRITEMASK :
2659 glStencilMask(Value);
2660 TRACE("glStencilMask(%lu)\n", Value);
2661 checkGLcall("glStencilMask");
2665 case D3DRS_FOGENABLE :
2667 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2669 checkGLcall("glEnable GL_FOG");
2672 checkGLcall("glDisable GL_FOG");
2677 case D3DRS_FOGCOLOR :
2680 D3DCOLORTOGLFLOAT4(Value, col);
2681 /* Set the default alpha blend color */
2682 glFogfv(GL_FOG_COLOR, &col[0]);
2683 checkGLcall("glFog GL_FOG_COLOR");
2687 case D3DRS_FOGTABLEMODE :
2690 case D3DFOG_NONE: /* I don't know what to do here */ break;
2691 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2692 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2693 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2695 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2700 case D3DRS_FOGSTART :
2702 float *f = (float*) &Value;
2703 glFogfv(GL_FOG_START, f);
2704 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2705 TRACE("Fog Start == %f\n", *f);
2711 float *f = (float*) &Value;
2712 glFogfv(GL_FOG_END, f);
2713 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2714 TRACE("Fog End == %f\n", *f);
2718 case D3DRS_FOGDENSITY :
2720 float *f = (float*) &Value;
2721 glFogfv(GL_FOG_DENSITY, f);
2722 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2726 case D3DRS_VERTEXBLEND :
2728 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2729 TRACE("Vertex Blending state to %ld\n", Value);
2733 case D3DRS_TWEENFACTOR :
2735 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2736 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2740 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2742 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2746 case D3DRS_COLORVERTEX :
2747 case D3DRS_DIFFUSEMATERIALSOURCE :
2748 case D3DRS_SPECULARMATERIALSOURCE :
2749 case D3DRS_AMBIENTMATERIALSOURCE :
2750 case D3DRS_EMISSIVEMATERIALSOURCE :
2752 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2754 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2755 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2756 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2757 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2758 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2759 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2761 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2762 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2763 Parm = GL_AMBIENT_AND_DIFFUSE;
2767 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2769 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2771 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2778 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2780 This->tracking_color = NEEDS_TRACKING;
2781 This->tracking_parm = Parm;
2785 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2790 case D3DRS_LINEPATTERN :
2792 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2793 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2795 if (pattern->wRepeatFactor) {
2796 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2797 checkGLcall("glLineStipple(repeat, linepattern)");
2798 glEnable(GL_LINE_STIPPLE);
2799 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2801 glDisable(GL_LINE_STIPPLE);
2802 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2810 TRACE("ZBias value %f\n", *((float*)&Value));
2811 glPolygonOffset(0, -*((float*)&Value));
2812 checkGLcall("glPolygonOffset(0, -Value)");
2813 glEnable(GL_POLYGON_OFFSET_FILL);
2814 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2815 glEnable(GL_POLYGON_OFFSET_LINE);
2816 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2817 glEnable(GL_POLYGON_OFFSET_POINT);
2818 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2820 glDisable(GL_POLYGON_OFFSET_FILL);
2821 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2822 glDisable(GL_POLYGON_OFFSET_LINE);
2823 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2824 glDisable(GL_POLYGON_OFFSET_POINT);
2825 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2830 case D3DRS_NORMALIZENORMALS :
2832 glEnable(GL_NORMALIZE);
2833 checkGLcall("glEnable(GL_NORMALIZE);");
2835 glDisable(GL_NORMALIZE);
2836 checkGLcall("glDisable(GL_NORMALIZE);");
2840 case D3DRS_POINTSIZE :
2841 TRACE("Set point size to %f\n", *((float*)&Value));
2842 glPointSize(*((float*)&Value));
2843 checkGLcall("glPointSize(...);");
2846 case D3DRS_POINTSIZE_MIN :
2847 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2848 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2849 checkGLcall("glPointParameterfEXT(...);");
2851 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2855 case D3DRS_POINTSIZE_MAX :
2856 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2857 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2858 checkGLcall("glPointParameterfEXT(...);");
2860 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2864 case D3DRS_POINTSCALE_A :
2865 case D3DRS_POINTSCALE_B :
2866 case D3DRS_POINTSCALE_C :
2867 case D3DRS_POINTSCALEENABLE :
2869 /* If enabled, supply the parameters, otherwise fall back to defaults */
2870 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2871 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2872 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2873 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2874 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2876 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2877 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2878 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2880 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2883 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2884 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2885 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2886 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2888 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2894 case D3DRS_COLORWRITEENABLE :
2895 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2896 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2897 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2898 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2899 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2900 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
2901 Value & D3DCOLORWRITEENABLE_GREEN,
2902 Value & D3DCOLORWRITEENABLE_BLUE,
2903 Value & D3DCOLORWRITEENABLE_ALPHA);
2904 checkGLcall("glColorMask(...)");
2907 /* Unhandled yet...! */
2908 case D3DRS_LASTPIXEL :
2909 case D3DRS_ZVISIBLE :
2910 case D3DRS_EDGEANTIALIAS :
2911 case D3DRS_RANGEFOGENABLE :
2920 case D3DRS_FOGVERTEXMODE :
2921 case D3DRS_LOCALVIEWER :
2922 case D3DRS_SOFTWAREVERTEXPROCESSING :
2923 case D3DRS_POINTSPRITEENABLE :
2924 case D3DRS_MULTISAMPLEANTIALIAS :
2925 case D3DRS_MULTISAMPLEMASK :
2926 case D3DRS_PATCHEDGESTYLE :
2927 case D3DRS_PATCHSEGMENTS :
2928 case D3DRS_DEBUGMONITORTOKEN :
2929 case D3DRS_POSITIONORDER :
2930 case D3DRS_NORMALORDER :
2931 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2932 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2935 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2942 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2943 ICOM_THIS(IDirect3DDevice8Impl,iface);
2944 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2945 *pValue = This->StateBlock->renderstate[State];
2948 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2949 ICOM_THIS(IDirect3DDevice8Impl,iface);
2951 TRACE("(%p)\n", This);
2953 return IDirect3DDeviceImpl_BeginStateBlock(This);
2955 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2956 IDirect3DStateBlockImpl* pSB;
2957 ICOM_THIS(IDirect3DDevice8Impl,iface);
2960 TRACE("(%p)\n", This);
2962 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2963 *pToken = (DWORD) pSB;
2967 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2968 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2969 ICOM_THIS(IDirect3DDevice8Impl,iface);
2971 TRACE("(%p)\n", This);
2973 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2976 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2977 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2978 ICOM_THIS(IDirect3DDevice8Impl,iface);
2980 TRACE("(%p)\n", This);
2982 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2984 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2985 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2986 ICOM_THIS(IDirect3DDevice8Impl,iface);
2988 TRACE("(%p)\n", This);
2990 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2993 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2994 IDirect3DStateBlockImpl* pSB;
2995 ICOM_THIS(IDirect3DDevice8Impl,iface);
2998 TRACE("(%p) : for type %d\n", This, Type);
3000 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3001 *pToken = (DWORD) pSB;
3005 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3006 ICOM_THIS(IDirect3DDevice8Impl,iface);
3007 FIXME("(%p) : stub\n", This); return D3D_OK;
3009 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3010 ICOM_THIS(IDirect3DDevice8Impl,iface);
3011 FIXME("(%p) : stub\n", This); return D3D_OK;
3013 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3014 ICOM_THIS(IDirect3DDevice8Impl,iface);
3015 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3016 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3017 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3020 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3022 IDirect3DBaseTexture8 *oldTxt;
3023 BOOL reapplyStates = TRUE;
3024 DWORD oldTextureDimensions = -1;
3025 DWORD reapplyFlags = 0;
3027 ICOM_THIS(IDirect3DDevice8Impl,iface);
3028 D3DRESOURCETYPE textureType;
3030 oldTxt = This->UpdateStateBlock->textures[Stage];
3031 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3033 /* Reject invalid texture units */
3034 if (Stage >= GL_LIMITS(textures)) {
3035 TRACE("Attempt to access invalid texture rejected\n");
3036 return D3DERR_INVALIDCALL;
3039 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3040 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3041 This->UpdateStateBlock->textures[Stage] = pTexture;
3043 /* Handle recording of state blocks */
3044 if (This->isRecordingState) {
3045 TRACE("Recording... not performing anything\n");
3049 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3052 /* Make appropriate texture active */
3053 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3054 #if defined(GL_VERSION_1_3)
3055 glActiveTexture(GL_TEXTURE0 + Stage);
3057 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3059 checkGLcall("glActiveTextureARB");
3060 } else if (Stage>0) {
3061 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3064 /* Decrement the count of the previous texture */
3065 if (NULL != oldTxt) {
3066 IDirect3DBaseTexture8Impl_Release(oldTxt);
3069 if (NULL != pTexture) {
3070 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3072 /* Now setup the texture appropraitly */
3073 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3075 if (textureType == D3DRTYPE_TEXTURE) {
3076 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3077 TRACE("Skipping setting texture as old == new\n");
3078 reapplyStates = FALSE;
3080 /* Standard 2D texture */
3081 TRACE("Standard 2d texture\n");
3082 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3084 /* Load up the texture now */
3085 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3087 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3088 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3089 TRACE("Skipping setting texture as old == new\n");
3090 reapplyStates = FALSE;
3092 /* Standard 3D (volume) texture */
3093 TRACE("Standard 3d texture\n");
3094 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3096 /* Load up the texture now */
3097 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3099 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3100 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3101 TRACE("Skipping setting texture as old == new\n");
3102 reapplyStates = FALSE;
3104 /* Standard Cube texture */
3105 TRACE("Standard Cube texture\n");
3106 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3108 /* Load up the texture now */
3109 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3112 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3115 TRACE("Setting to no texture (ie default texture)\n");
3116 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3117 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3118 checkGLcall("glBindTexture");
3119 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3122 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3123 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3124 glDisable(oldTextureDimensions);
3125 checkGLcall("Disable oldTextureDimensions");
3126 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3127 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3128 checkGLcall("glEnable new texture dimensions");
3131 /* If Alpha arg1 is texture then handle the special case when there changes between a
3132 texture and no texture - See comments in set_tex_op */
3133 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3134 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3136 reapplyFlags |= REAPPLY_ALPHAOP;
3141 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3142 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3143 if (reapplyStates) {
3144 setupTextureStates(iface, Stage, reapplyFlags);
3152 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3153 ICOM_THIS(IDirect3DDevice8Impl,iface);
3154 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3155 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3159 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3160 ICOM_THIS(IDirect3DDevice8Impl,iface);
3162 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3164 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3166 /* Reject invalid texture units */
3167 if (Stage >= GL_LIMITS(textures)) {
3168 TRACE("Attempt to access invalid texture rejected\n");
3169 return D3DERR_INVALIDCALL;
3172 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3173 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3174 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3176 /* Handle recording of state blocks */
3177 if (This->isRecordingState) {
3178 TRACE("Recording... not performing anything\n");
3184 /* Make appropriate texture active */
3185 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3186 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3187 #if defined(GL_VERSION_1_3)
3188 glActiveTexture(GL_TEXTURE0 + Stage);
3189 vcheckGLcall("glActiveTexture");
3191 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3192 vcheckGLcall("glActiveTextureARB");
3194 } else if (Stage > 0) {
3195 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3200 case D3DTSS_MINFILTER :
3201 case D3DTSS_MIPFILTER :
3203 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3204 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3205 GLint realVal = GL_LINEAR;
3207 if (ValueMIN == D3DTEXF_POINT) {
3209 if (ValueMIP == D3DTEXF_POINT) {
3210 realVal = GL_NEAREST_MIPMAP_NEAREST;
3211 } else if (ValueMIP == D3DTEXF_LINEAR) {
3212 realVal = GL_NEAREST_MIPMAP_LINEAR;
3213 } else if (ValueMIP == D3DTEXF_NONE) {
3214 realVal = GL_NEAREST;
3216 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3217 realVal = GL_NEAREST_MIPMAP_LINEAR;
3219 } else if (ValueMIN == D3DTEXF_LINEAR) {
3221 if (ValueMIP == D3DTEXF_POINT) {
3222 realVal = GL_LINEAR_MIPMAP_NEAREST;
3223 } else if (ValueMIP == D3DTEXF_LINEAR) {
3224 realVal = GL_LINEAR_MIPMAP_LINEAR;
3225 } else if (ValueMIP == D3DTEXF_NONE) {
3226 realVal = GL_LINEAR;
3228 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3229 realVal = GL_LINEAR_MIPMAP_LINEAR;
3231 } else if (ValueMIN == D3DTEXF_NONE) {
3232 /* Doesnt really make sense - Windows just seems to disable
3233 mipmapping when this occurs */
3234 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3235 realVal = GL_LINEAR;
3238 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3239 realVal = GL_LINEAR_MIPMAP_LINEAR;
3242 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3243 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3244 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3248 case D3DTSS_MAXANISOTROPY :
3250 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3251 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3252 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3257 case D3DTSS_MAGFILTER :
3258 if (Value == D3DTEXF_POINT) {
3259 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3260 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3261 } else if (Value == D3DTEXF_LINEAR) {
3262 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3263 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3265 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3269 case D3DTSS_ALPHAOP :
3270 case D3DTSS_COLOROP :
3273 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3274 /* TODO: Disable by making this and all later levels disabled */
3275 glDisable(GL_TEXTURE_1D);
3276 checkGLcall("Disable GL_TEXTURE_1D");
3277 glDisable(GL_TEXTURE_2D);
3278 checkGLcall("Disable GL_TEXTURE_2D");
3279 glDisable(GL_TEXTURE_3D);
3280 checkGLcall("Disable GL_TEXTURE_3D");
3281 break; /* Dont bother setting the texture operations */
3283 /* Enable only the appropriate texture dimension */
3284 if (Type == D3DTSS_COLOROP) {
3285 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3286 glEnable(GL_TEXTURE_1D);
3287 checkGLcall("Enable GL_TEXTURE_1D");
3289 glDisable(GL_TEXTURE_1D);
3290 checkGLcall("Disable GL_TEXTURE_1D");
3292 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3293 glEnable(GL_TEXTURE_2D);
3294 checkGLcall("Enable GL_TEXTURE_2D");
3296 glDisable(GL_TEXTURE_2D);
3297 checkGLcall("Disable GL_TEXTURE_2D");
3299 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3300 glEnable(GL_TEXTURE_3D);
3301 checkGLcall("Enable GL_TEXTURE_3D");
3303 glDisable(GL_TEXTURE_3D);
3304 checkGLcall("Disable GL_TEXTURE_3D");
3306 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3307 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3308 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3310 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3311 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3315 /* Drop through... (Except disable case) */
3316 case D3DTSS_COLORARG0 :
3317 case D3DTSS_COLORARG1 :
3318 case D3DTSS_COLORARG2 :
3319 case D3DTSS_ALPHAARG0 :
3320 case D3DTSS_ALPHAARG1 :
3321 case D3DTSS_ALPHAARG2 :
3323 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3324 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3326 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3327 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3328 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3329 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3331 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3332 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3333 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3334 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3340 case D3DTSS_ADDRESSU :
3341 case D3DTSS_ADDRESSV :
3342 case D3DTSS_ADDRESSW :
3344 GLint wrapParm = GL_REPEAT;
3346 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3347 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3348 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3349 #if defined(GL_VERSION_1_4)
3350 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3351 #elif defined(GL_ARB_texture_mirrored_repeat)
3352 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3354 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3356 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3358 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3359 wrapParm = GL_REPEAT;
3363 case D3DTSS_ADDRESSU:
3364 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3365 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3366 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3368 case D3DTSS_ADDRESSV:
3369 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3370 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3371 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3373 case D3DTSS_ADDRESSW:
3374 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3375 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3376 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3379 break; /** stupic compilator */
3384 case D3DTSS_BORDERCOLOR :
3387 D3DCOLORTOGLFLOAT4(Value, col);
3388 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3389 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3390 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3394 case D3DTSS_TEXCOORDINDEX :
3396 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3398 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3399 one flag, you can still specify an index value, which the system uses to
3400 determine the texture wrapping mode.
3401 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3402 means use the vertex position (camera-space) as the input texture coordinates
3403 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3404 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3405 to the TEXCOORDINDEX value */
3408 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3410 switch (Value & 0xFFFF0000) {
3411 case D3DTSS_TCI_PASSTHRU:
3412 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3413 glDisable(GL_TEXTURE_GEN_S);
3414 glDisable(GL_TEXTURE_GEN_T);
3415 glDisable(GL_TEXTURE_GEN_R);
3416 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3419 case D3DTSS_TCI_CAMERASPACEPOSITION:
3420 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3421 as the input texture coordinates for this stage's texture transformation. This
3422 equates roughly to EYE_LINEAR */
3424 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3425 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3426 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3427 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3428 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3430 glMatrixMode(GL_MODELVIEW);
3433 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3434 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3435 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3436 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3439 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3440 glEnable(GL_TEXTURE_GEN_S);
3441 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3442 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3443 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3444 glEnable(GL_TEXTURE_GEN_T);
3445 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3446 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3447 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3448 glEnable(GL_TEXTURE_GEN_R);
3449 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3450 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3451 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3455 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3456 case D3DTSS_TCI_CAMERASPACENORMAL:
3458 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3459 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3460 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3461 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3462 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3464 glMatrixMode(GL_MODELVIEW);
3467 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3468 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3469 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3470 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3473 glEnable(GL_TEXTURE_GEN_S);
3474 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3475 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3476 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3477 glEnable(GL_TEXTURE_GEN_T);
3478 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3479 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3480 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3481 glEnable(GL_TEXTURE_GEN_R);
3482 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3483 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3484 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3489 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3490 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3493 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3494 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3495 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3496 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3497 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3499 glMatrixMode(GL_MODELVIEW);
3502 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3503 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3504 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3505 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3508 glEnable(GL_TEXTURE_GEN_S);
3509 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3510 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3511 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3512 glEnable(GL_TEXTURE_GEN_T);
3513 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3514 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3515 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3516 glEnable(GL_TEXTURE_GEN_R);
3517 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3518 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3519 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3524 /* Unhandled types: */
3527 /* ? disable GL_TEXTURE_GEN_n ? */
3528 glDisable(GL_TEXTURE_GEN_S);
3529 glDisable(GL_TEXTURE_GEN_T);
3530 glDisable(GL_TEXTURE_GEN_R);
3531 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3538 case D3DTSS_BUMPENVMAT00 :
3539 case D3DTSS_BUMPENVMAT01 :
3540 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3542 case D3DTSS_BUMPENVMAT10 :
3543 case D3DTSS_BUMPENVMAT11 :
3544 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3547 case D3DTSS_TEXTURETRANSFORMFLAGS :
3548 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3551 case D3DTSS_MIPMAPLODBIAS :
3552 case D3DTSS_MAXMIPLEVEL :
3553 case D3DTSS_BUMPENVLSCALE :
3554 case D3DTSS_BUMPENVLOFFSET :
3555 case D3DTSS_RESULTARG :
3557 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3558 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3565 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3566 ICOM_THIS(IDirect3DDevice8Impl,iface);
3567 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3570 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3571 ICOM_THIS(IDirect3DDevice8Impl,iface);
3572 FIXME("(%p) : stub\n", This);
3575 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3576 ICOM_THIS(IDirect3DDevice8Impl,iface);
3577 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3578 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3579 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3582 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3583 ICOM_THIS(IDirect3DDevice8Impl,iface);
3584 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3585 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3586 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3589 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3590 ICOM_THIS(IDirect3DDevice8Impl,iface);
3591 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3592 This->currentPalette = PaletteNumber;
3594 #if defined(GL_EXT_paletted_texture)
3595 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3599 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3600 GL_RGBA, /* internal format */
3601 256, /* table size */
3602 GL_RGBA, /* table format */
3603 GL_UNSIGNED_BYTE, /* table type */
3604 This->palettes[PaletteNumber]);
3605 checkGLcall("glColorTableEXT");
3610 /* Delayed palette handling ... waiting for software emulation into preload code */
3615 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3616 ICOM_THIS(IDirect3DDevice8Impl,iface);
3617 *PaletteNumber = This->currentPalette;
3618 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3621 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3623 ICOM_THIS(IDirect3DDevice8Impl,iface);
3624 This->StateBlock->streamIsUP = FALSE;
3626 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3627 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3631 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3632 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3634 IDirect3DIndexBuffer8 *pIB;
3635 D3DINDEXBUFFER_DESC IdxBufDsc;
3637 ICOM_THIS(IDirect3DDevice8Impl,iface);
3638 pIB = This->StateBlock->pIndexData;
3639 This->StateBlock->streamIsUP = FALSE;
3641 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3642 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3643 minIndex, NumVertices, startIndex, primCount);
3645 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3646 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3652 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3657 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3658 ICOM_THIS(IDirect3DDevice8Impl,iface);
3660 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3661 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3663 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3665 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3666 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3667 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3668 This->StateBlock->streamIsUP = TRUE;
3669 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3670 This->StateBlock->stream_stride[0] = 0;
3671 This->StateBlock->stream_source[0] = NULL;
3673 /*stream zero settings set to null at end */
3676 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3677 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3678 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3679 UINT VertexStreamZeroStride) {
3681 ICOM_THIS(IDirect3DDevice8Impl,iface);
3682 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),
3683 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3685 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3686 if (IndexDataFormat == D3DFMT_INDEX16) {
3692 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3693 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3694 This->StateBlock->streamIsUP = TRUE;
3695 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3696 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3698 /*stream zero settings set to null at end */
3699 This->StateBlock->stream_source[0] = NULL;
3700 This->StateBlock->stream_stride[0] = 0;
3701 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3705 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3706 ICOM_THIS(IDirect3DDevice8Impl,iface);
3707 FIXME("(%p) : stub\n", This); return D3D_OK;
3709 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3710 ICOM_THIS(IDirect3DDevice8Impl,iface);
3711 IDirect3DVertexShaderImpl* object;
3712 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3716 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3717 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3718 return D3DERR_INVALIDCALL;
3720 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3721 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3722 return D3DERR_OUTOFVIDEOMEMORY;
3725 /** Create the Vertex Shader */
3726 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3727 /** TODO: check FAILED(res) */
3729 /** Create and Bind the Vertex Shader Declaration */
3730 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3731 /** TODO: check FAILED(res) */
3733 VertexShaders[i] = object;
3734 VertexShaderDeclarations[i] = attached_decl;
3735 *pHandle = VS_HIGHESTFIXEDFXF + i;
3736 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3740 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3741 ICOM_THIS(IDirect3DDevice8Impl,iface);
3743 This->UpdateStateBlock->VertexShader = Handle;
3744 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3745 This->UpdateStateBlock->Set.vertexShader = TRUE;
3747 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3748 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3749 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3750 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3751 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3752 } else { /* use a fvf, so desactivate the vshader decl */
3753 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3754 This->UpdateStateBlock->vertexShaderDecl = NULL;
3755 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3756 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3758 /* Handle recording of state blocks */
3759 if (This->isRecordingState) {
3760 TRACE("Recording... not performing anything\n");
3764 * TODO: merge HAL shaders context switching from prototype
3768 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3769 ICOM_THIS(IDirect3DDevice8Impl,iface);
3770 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3771 *pHandle = This->StateBlock->VertexShader;
3775 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3776 ICOM_THIS(IDirect3DDevice8Impl,iface);
3777 IDirect3DVertexShaderImpl* object;
3778 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3780 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3781 return D3DERR_INVALIDCALL;
3785 * Delete Vertex Shader
3787 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3788 if (NULL == object) {
3789 return D3DERR_INVALIDCALL;
3791 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3792 /* TODO: check validity of object */
3793 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3794 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3795 HeapFree(GetProcessHeap(), 0, (void *)object);
3796 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3799 * Delete Vertex Shader Declaration
3801 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3802 if (NULL == attached_decl) {
3803 return D3DERR_INVALIDCALL;
3805 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3806 /* TODO: check validity of object */
3807 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3808 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3809 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3814 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3815 ICOM_THIS(IDirect3DDevice8Impl,iface);
3817 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3818 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3819 return D3DERR_INVALIDCALL;
3821 if (NULL == pConstantData) {
3822 return D3DERR_INVALIDCALL;
3824 if (ConstantCount > 1) {
3825 FLOAT* f = (FLOAT*)pConstantData;
3827 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3828 for (i = 0; i < ConstantCount; ++i) {
3829 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3833 FLOAT* f = (FLOAT*) pConstantData;
3834 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3836 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3837 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3840 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3841 ICOM_THIS(IDirect3DDevice8Impl,iface);
3843 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3844 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3845 return D3DERR_INVALIDCALL;
3847 if (NULL == pConstantData) {
3848 return D3DERR_INVALIDCALL;
3850 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3853 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3854 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3855 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3857 attached_decl = VERTEX_SHADER_DECL(Handle);
3858 if (NULL == attached_decl) {
3859 return D3DERR_INVALIDCALL;
3861 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3863 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3864 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3865 IDirect3DVertexShaderImpl* object;
3867 object = VERTEX_SHADER(Handle);
3868 if (NULL == object) {
3869 return D3DERR_INVALIDCALL;
3871 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3874 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3875 ICOM_THIS(IDirect3DDevice8Impl,iface);
3876 IDirect3DIndexBuffer8 *oldIdxs;
3878 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3879 oldIdxs = This->StateBlock->pIndexData;
3881 This->UpdateStateBlock->Changed.Indices = TRUE;
3882 This->UpdateStateBlock->Set.Indices = TRUE;
3883 This->UpdateStateBlock->pIndexData = pIndexData;
3884 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3886 /* Handle recording of state blocks */
3887 if (This->isRecordingState) {
3888 TRACE("Recording... not performing anything\n");
3892 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3893 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3896 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3897 ICOM_THIS(IDirect3DDevice8Impl,iface);
3898 FIXME("(%p) : stub\n", This);
3900 *ppIndexData = This->StateBlock->pIndexData;
3901 /* up ref count on ppindexdata */
3902 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3903 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3907 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3908 ICOM_THIS(IDirect3DDevice8Impl,iface);
3909 IDirect3DPixelShaderImpl* object;
3913 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3914 if (NULL == pFunction || NULL == pHandle) {
3915 return D3DERR_INVALIDCALL;
3917 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3918 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3919 return D3DERR_OUTOFVIDEOMEMORY;
3922 /** Create the Pixel Shader */
3923 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3924 if (SUCCEEDED(res)) {
3925 PixelShaders[i] = object;
3926 *pHandle = VS_HIGHESTFIXEDFXF + i;
3929 *pHandle = 0xFFFFFFFF;
3932 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3933 ICOM_THIS(IDirect3DDevice8Impl,iface);
3935 This->UpdateStateBlock->PixelShader = Handle;
3936 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3937 This->UpdateStateBlock->Set.pixelShader = TRUE;
3939 /* Handle recording of state blocks */
3940 if (This->isRecordingState) {
3941 TRACE_(d3d_shader)("Recording... not performing anything\n");
3945 /* FIXME: Quieten when not being used */
3947 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3949 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3954 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3955 ICOM_THIS(IDirect3DDevice8Impl,iface);
3956 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3957 *pHandle = This->StateBlock->PixelShader;
3961 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3962 ICOM_THIS(IDirect3DDevice8Impl,iface);
3963 IDirect3DPixelShaderImpl* object;
3965 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3966 return D3DERR_INVALIDCALL;
3968 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3969 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3970 /* TODO: check validity of object before free */
3971 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3972 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3973 HeapFree(GetProcessHeap(), 0, (void *)object);
3974 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3979 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3980 ICOM_THIS(IDirect3DDevice8Impl,iface);
3982 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3983 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3984 return D3DERR_INVALIDCALL;
3986 if (NULL == pConstantData) {
3987 return D3DERR_INVALIDCALL;
3989 if (ConstantCount > 1) {
3990 FLOAT* f = (FLOAT*)pConstantData;
3992 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3993 for (i = 0; i < ConstantCount; ++i) {
3994 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3998 FLOAT* f = (FLOAT*) pConstantData;
3999 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4001 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4002 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4005 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4006 ICOM_THIS(IDirect3DDevice8Impl,iface);
4008 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4009 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4010 return D3DERR_INVALIDCALL;
4012 if (NULL == pConstantData) {
4013 return D3DERR_INVALIDCALL;
4015 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4018 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4019 IDirect3DPixelShaderImpl* object;
4021 object = PIXEL_SHADER(Handle);
4022 if (NULL == object) {
4023 return D3DERR_INVALIDCALL;
4025 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4027 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4028 ICOM_THIS(IDirect3DDevice8Impl,iface);
4029 FIXME("(%p) : stub\n", This); return D3D_OK;
4031 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4032 ICOM_THIS(IDirect3DDevice8Impl,iface);
4033 FIXME("(%p) : stub\n", This); return D3D_OK;
4035 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4036 ICOM_THIS(IDirect3DDevice8Impl,iface);
4037 FIXME("(%p) : stub\n", This); return D3D_OK;
4040 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4041 IDirect3DVertexBuffer8 *oldSrc;
4042 ICOM_THIS(IDirect3DDevice8Impl,iface);
4044 oldSrc = This->StateBlock->stream_source[StreamNumber];
4045 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4047 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4048 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4049 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4050 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4052 /* Handle recording of state blocks */
4053 if (This->isRecordingState) {
4054 TRACE("Recording... not performing anything\n");
4058 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4059 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4062 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4063 ICOM_THIS(IDirect3DDevice8Impl,iface);
4064 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4065 *pStream = This->StateBlock->stream_source[StreamNumber];
4066 *pStride = This->StateBlock->stream_stride[StreamNumber];
4067 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4072 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4074 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4075 IDirect3DDevice8Impl_QueryInterface,
4076 IDirect3DDevice8Impl_AddRef,
4077 IDirect3DDevice8Impl_Release,
4078 IDirect3DDevice8Impl_TestCooperativeLevel,
4079 IDirect3DDevice8Impl_GetAvailableTextureMem,
4080 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4081 IDirect3DDevice8Impl_GetDirect3D,
4082 IDirect3DDevice8Impl_GetDeviceCaps,
4083 IDirect3DDevice8Impl_GetDisplayMode,
4084 IDirect3DDevice8Impl_GetCreationParameters,
4085 IDirect3DDevice8Impl_SetCursorProperties,
4086 IDirect3DDevice8Impl_SetCursorPosition,
4087 IDirect3DDevice8Impl_ShowCursor,
4088 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4089 IDirect3DDevice8Impl_Reset,
4090 IDirect3DDevice8Impl_Present,
4091 IDirect3DDevice8Impl_GetBackBuffer,
4092 IDirect3DDevice8Impl_GetRasterStatus,
4093 IDirect3DDevice8Impl_SetGammaRamp,
4094 IDirect3DDevice8Impl_GetGammaRamp,
4095 IDirect3DDevice8Impl_CreateTexture,
4096 IDirect3DDevice8Impl_CreateVolumeTexture,
4097 IDirect3DDevice8Impl_CreateCubeTexture,
4098 IDirect3DDevice8Impl_CreateVertexBuffer,
4099 IDirect3DDevice8Impl_CreateIndexBuffer,
4100 IDirect3DDevice8Impl_CreateRenderTarget,
4101 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4102 IDirect3DDevice8Impl_CreateImageSurface,
4103 IDirect3DDevice8Impl_CopyRects,
4104 IDirect3DDevice8Impl_UpdateTexture,
4105 IDirect3DDevice8Impl_GetFrontBuffer,
4106 IDirect3DDevice8Impl_SetRenderTarget,
4107 IDirect3DDevice8Impl_GetRenderTarget,
4108 IDirect3DDevice8Impl_GetDepthStencilSurface,
4109 IDirect3DDevice8Impl_BeginScene,
4110 IDirect3DDevice8Impl_EndScene,
4111 IDirect3DDevice8Impl_Clear,
4112 IDirect3DDevice8Impl_SetTransform,
4113 IDirect3DDevice8Impl_GetTransform,
4114 IDirect3DDevice8Impl_MultiplyTransform,
4115 IDirect3DDevice8Impl_SetViewport,
4116 IDirect3DDevice8Impl_GetViewport,
4117 IDirect3DDevice8Impl_SetMaterial,
4118 IDirect3DDevice8Impl_GetMaterial,
4119 IDirect3DDevice8Impl_SetLight,
4120 IDirect3DDevice8Impl_GetLight,
4121 IDirect3DDevice8Impl_LightEnable,
4122 IDirect3DDevice8Impl_GetLightEnable,
4123 IDirect3DDevice8Impl_SetClipPlane,
4124 IDirect3DDevice8Impl_GetClipPlane,
4125 IDirect3DDevice8Impl_SetRenderState,
4126 IDirect3DDevice8Impl_GetRenderState,
4127 IDirect3DDevice8Impl_BeginStateBlock,
4128 IDirect3DDevice8Impl_EndStateBlock,
4129 IDirect3DDevice8Impl_ApplyStateBlock,
4130 IDirect3DDevice8Impl_CaptureStateBlock,
4131 IDirect3DDevice8Impl_DeleteStateBlock,
4132 IDirect3DDevice8Impl_CreateStateBlock,
4133 IDirect3DDevice8Impl_SetClipStatus,
4134 IDirect3DDevice8Impl_GetClipStatus,
4135 IDirect3DDevice8Impl_GetTexture,
4136 IDirect3DDevice8Impl_SetTexture,
4137 IDirect3DDevice8Impl_GetTextureStageState,
4138 IDirect3DDevice8Impl_SetTextureStageState,
4139 IDirect3DDevice8Impl_ValidateDevice,
4140 IDirect3DDevice8Impl_GetInfo,
4141 IDirect3DDevice8Impl_SetPaletteEntries,
4142 IDirect3DDevice8Impl_GetPaletteEntries,
4143 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4144 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4145 IDirect3DDevice8Impl_DrawPrimitive,
4146 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4147 IDirect3DDevice8Impl_DrawPrimitiveUP,
4148 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4149 IDirect3DDevice8Impl_ProcessVertices,
4150 IDirect3DDevice8Impl_CreateVertexShader,
4151 IDirect3DDevice8Impl_SetVertexShader,
4152 IDirect3DDevice8Impl_GetVertexShader,
4153 IDirect3DDevice8Impl_DeleteVertexShader,
4154 IDirect3DDevice8Impl_SetVertexShaderConstant,
4155 IDirect3DDevice8Impl_GetVertexShaderConstant,
4156 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4157 IDirect3DDevice8Impl_GetVertexShaderFunction,
4158 IDirect3DDevice8Impl_SetStreamSource,
4159 IDirect3DDevice8Impl_GetStreamSource,
4160 IDirect3DDevice8Impl_SetIndices,
4161 IDirect3DDevice8Impl_GetIndices,
4162 IDirect3DDevice8Impl_CreatePixelShader,
4163 IDirect3DDevice8Impl_SetPixelShader,
4164 IDirect3DDevice8Impl_GetPixelShader,
4165 IDirect3DDevice8Impl_DeletePixelShader,
4166 IDirect3DDevice8Impl_SetPixelShaderConstant,
4167 IDirect3DDevice8Impl_GetPixelShaderConstant,
4168 IDirect3DDevice8Impl_GetPixelShaderFunction,
4169 IDirect3DDevice8Impl_DrawRectPatch,
4170 IDirect3DDevice8Impl_DrawTriPatch,
4171 IDirect3DDevice8Impl_DeletePatch
4174 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4176 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4177 ICOM_THIS(IDirect3DDevice8Impl,iface);
4182 if (This->glCtx != This->render_ctx) {
4183 glXDestroyContext(This->display, This->render_ctx);
4184 This->render_ctx = This->glCtx;
4187 if (This->win != This->drawable) {
4188 glXDestroyPbuffer(This->display, This->drawable);
4189 This->drawable = This->win;
4198 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4199 IDirect3DSurface8* RenderSurface,
4200 IDirect3DSurface8* StencilSurface) {
4202 HRESULT ret = D3DERR_INVALIDCALL;
4204 * Currently only active for GLX >= 1.3
4205 * for others versions we'll have to use GLXPixmaps
4207 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4208 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4209 * so only check OpenGL version
4211 #if defined(GL_VERSION_1_3)
4212 GLXFBConfig* cfgs = NULL;
4216 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4217 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4218 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4219 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4220 IDirect3DSurface8Impl* tmp;
4222 ICOM_THIS(IDirect3DDevice8Impl,iface);
4224 #define PUSH1(att) attribs[nAttribs++] = (att);
4225 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4227 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4228 PUSH2(GLX_X_RENDERABLE, TRUE);
4229 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4231 switch (BackBufferFormat) {
4234 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4235 PUSH2(GLX_BUFFER_SIZE, 8);
4236 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4240 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4241 PUSH2(GLX_RED_SIZE, 3);
4242 PUSH2(GLX_GREEN_SIZE, 3);
4243 PUSH2(GLX_BLUE_SIZE, 2);
4246 case D3DFMT_A1R5G5B5:
4247 PUSH2(GLX_ALPHA_SIZE, 1);
4248 case D3DFMT_X1R5G5B5:
4249 PUSH2(GLX_RED_SIZE, 5);
4250 PUSH2(GLX_GREEN_SIZE, 5);
4251 PUSH2(GLX_BLUE_SIZE, 5);
4255 PUSH2(GLX_RED_SIZE, 5);
4256 PUSH2(GLX_GREEN_SIZE, 6);
4257 PUSH2(GLX_BLUE_SIZE, 5);
4260 case D3DFMT_A4R4G4B4:
4261 PUSH2(GLX_ALPHA_SIZE, 4);
4262 case D3DFMT_X4R4G4B4:
4263 PUSH2(GLX_RED_SIZE, 4);
4264 PUSH2(GLX_GREEN_SIZE, 4);
4265 PUSH2(GLX_BLUE_SIZE, 4);
4268 case D3DFMT_A8R8G8B8:
4269 PUSH2(GLX_ALPHA_SIZE, 8);
4271 case D3DFMT_X8R8G8B8:
4272 PUSH2(GLX_RED_SIZE, 8);
4273 PUSH2(GLX_GREEN_SIZE, 8);
4274 PUSH2(GLX_BLUE_SIZE, 8);
4281 switch (StencilBufferFormat) {
4282 case D3DFMT_D16_LOCKABLE:
4284 PUSH2(GLX_DEPTH_SIZE, 16);
4288 PUSH2(GLX_DEPTH_SIZE, 15);
4292 PUSH2(GLX_DEPTH_SIZE, 24);
4295 case D3DFMT_D24X4S4:
4296 PUSH2(GLX_DEPTH_SIZE, 24);
4297 PUSH2(GLX_STENCIL_SIZE, 4);
4301 PUSH2(GLX_DEPTH_SIZE, 24);
4302 PUSH2(GLX_STENCIL_SIZE, 8);
4306 PUSH2(GLX_DEPTH_SIZE, 32);
4317 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4321 for (i = 0; i < nCfgs; ++i) {
4322 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4326 if (NULL != This->renderTarget) {
4329 vcheckGLcall("glFlush");
4332 /** very very usefull debug code */
4333 glXSwapBuffers(This->display, This->drawable);
4334 printf("Hit Enter to get next frame ...\n");
4338 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4339 vcheckGLcall("glIntegerv");
4340 glReadBuffer(GL_BACK);
4341 vcheckGLcall("glReadBuffer");
4344 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4346 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4349 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4351 This->renderTarget->myDesc.Height - j - 1,
4352 This->renderTarget->myDesc.Width,
4354 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4355 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4356 This->renderTarget->allocatedMemory + j * pitch);
4357 vcheckGLcall("glReadPixels");
4360 glReadBuffer(prev_read);
4361 vcheckGLcall("glReadBuffer");
4364 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4365 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4367 PUSH2(GLX_PBUFFER_WIDTH, Width);
4368 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4370 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4372 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4373 if (NULL == This->render_ctx) {
4374 ERR("cannot create glxContext\n");
4378 glXSwapBuffers(This->display, This->drawable);
4379 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4380 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4382 checkGLcall("glXMakeContextCurrent");
4385 tmp = This->renderTarget;
4386 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4387 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4388 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4390 tmp = This->stencilBufferTarget;
4391 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4392 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4393 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4398 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));