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); 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) {
1355 glEnable(GL_SCISSOR_TEST);
1356 checkGLcall("glEnable GL_SCISSOR_TEST");
1362 /* Only set the values up once, as they are not changing */
1363 if (Flags & D3DCLEAR_STENCIL) {
1364 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1365 glClearStencil(Stencil);
1366 checkGLcall("glClearStencil");
1367 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1370 if (Flags & D3DCLEAR_ZBUFFER) {
1371 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1372 glDepthMask(GL_TRUE);
1373 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1375 checkGLcall("glClearDepth");
1376 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1379 if (Flags & D3DCLEAR_TARGET) {
1380 TRACE("Clearing screen with glClear to color %lx\n", Color);
1381 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1382 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1383 ((Color >> 8) & 0xFF) / 255.0f,
1384 ((Color >> 0) & 0xFF) / 255.0f,
1385 ((Color >> 24) & 0xFF) / 255.0f);
1386 checkGLcall("glClearColor");
1387 glMask = glMask | GL_COLOR_BUFFER_BIT;
1390 /* Now process each rect in turn */
1391 for (i = 0; i < Count || i == 0; i++) {
1394 /* Note gl uses lower left, width/height */
1395 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1396 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1397 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1398 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1399 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1400 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1401 checkGLcall("glScissor");
1403 glScissor(This->StateBlock->viewport.X,
1404 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1405 This->StateBlock->viewport.Width,
1406 This->StateBlock->viewport.Height);
1407 checkGLcall("glScissor");
1410 /* Clear the selected rectangle (or full screen) */
1412 checkGLcall("glClear");
1414 /* Step to the next rectangle */
1415 if (curRect) curRect = curRect + sizeof(D3DRECT);
1418 /* Restore the old values (why..?) */
1419 if (Flags & D3DCLEAR_STENCIL) {
1420 glClearStencil(old_stencil_clear_value);
1422 if (Flags & D3DCLEAR_ZBUFFER) {
1423 glDepthMask(old_ztest);
1424 glClearDepth(old_z_clear_value);
1426 if (Flags & D3DCLEAR_TARGET) {
1427 glClearColor(old_color_clear_value[0],
1428 old_color_clear_value[1],
1429 old_color_clear_value[2],
1430 old_color_clear_value[3]);
1433 if (Count > 0 && pRects) {
1434 glDisable(GL_SCISSOR_TEST);
1435 checkGLcall("glDisable");
1441 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1442 ICOM_THIS(IDirect3DDevice8Impl,iface);
1445 /* Most of this routine, comments included copied from ddraw tree initially: */
1446 TRACE("(%p) : State=%d\n", This, d3dts);
1448 /* Handle recording of state blocks */
1449 if (This->isRecordingState) {
1450 TRACE("Recording... not performing anything\n");
1451 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1452 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1453 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1458 * if the new matrix is the same as the current one,
1459 * we cut off any further processing. this seems to be a reasonable
1460 * optimization because as was noticed, some apps (warcraft3 for example)
1461 * tend towards setting the same matrix repeatedly for some dumb reason.
1463 * From here on we assume that the new matrix is different, wherever it matters
1466 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1467 TRACE("The app is setting the same matrix over again\n");
1470 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1474 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1475 where ViewMat = Camera space, WorldMat = world space.
1477 In OpenGL, camera and world space is combined into GL_MODELVIEW
1478 matrix. The Projection matrix stay projection matrix.
1481 /* Capture the times we can just ignore the change */
1482 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1483 This->modelview_valid = FALSE;
1486 } else if (d3dts == D3DTS_PROJECTION) {
1487 This->proj_valid = FALSE;
1490 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1491 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1492 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1496 /* Chances are we really are going to have to change a matrix */
1499 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1500 if (d3dts < GL_LIMITS(textures)) {
1501 int tex = d3dts - D3DTS_TEXTURE0;
1502 #if defined(GL_VERSION_1_3)
1503 glActiveTexture(GL_TEXTURE0 + tex);
1505 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1507 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1510 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1512 PLIGHTINFOEL *lightChain = NULL;
1513 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1514 This->modelview_valid = FALSE;
1515 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1516 glMatrixMode(GL_MODELVIEW);
1517 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1519 glLoadMatrixf((float *)lpmatrix);
1520 checkGLcall("glLoadMatrixf(...)");
1522 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1523 * NOTE: We have to reset the positions even if the light/plane is not currently
1524 * enabled, since the call to enable it will not reset the position.
1525 * NOTE2: Apparently texture transforms do NOT need reapplying
1529 lightChain = This->StateBlock->lights;
1530 while (lightChain && lightChain->glIndex != -1) {
1531 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1532 checkGLcall("glLightfv posn");
1533 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1534 checkGLcall("glLightfv dirn");
1535 lightChain = lightChain->next;
1537 /* Reset Clipping Planes if clipping is enabled */
1538 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1539 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1540 checkGLcall("glClipPlane");
1544 } else { /* What was requested!?? */
1545 WARN("invalid matrix specified: %i\n", d3dts);
1549 /* Release lock, all done */
1554 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1555 ICOM_THIS(IDirect3DDevice8Impl,iface);
1556 TRACE("(%p) : for State %d\n", This, State);
1557 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1561 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1562 D3DMATRIX *mat = NULL;
1565 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1566 but works regardless of recording being on.
1567 If this is found to be wrong, change to StateBlock. */
1568 ICOM_THIS(IDirect3DDevice8Impl,iface);
1569 TRACE("(%p) : For state %u\n", This, State);
1571 if (State < HIGHEST_TRANSFORMSTATE)
1573 mat = &This->UpdateStateBlock->transforms[State];
1575 FIXME("Unhandled transform state!!\n");
1578 /* Copied from ddraw code: */
1579 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);
1580 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);
1581 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);
1582 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);
1584 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);
1585 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);
1586 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);
1587 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);
1589 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);
1590 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);
1591 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);
1592 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);
1594 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);
1595 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);
1596 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);
1597 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);
1599 /* Apply change via set transform - will reapply to eg. lights this way */
1600 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1603 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1604 ICOM_THIS(IDirect3DDevice8Impl,iface);
1606 TRACE("(%p)\n", This);
1607 This->UpdateStateBlock->Changed.viewport = TRUE;
1608 This->UpdateStateBlock->Set.viewport = TRUE;
1609 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1611 /* Handle recording of state blocks */
1612 if (This->isRecordingState) {
1613 TRACE("Recording... not performing anything\n");
1619 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1620 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1622 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1623 checkGLcall("glDepthRange");
1624 /* Note: GL requires lower left, DirectX supplies upper left */
1625 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1626 pViewport->Width, pViewport->Height);
1627 checkGLcall("glViewport");
1634 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1635 ICOM_THIS(IDirect3DDevice8Impl,iface);
1636 TRACE("(%p)\n", This);
1637 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1641 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1642 ICOM_THIS(IDirect3DDevice8Impl,iface);
1644 This->UpdateStateBlock->Changed.material = TRUE;
1645 This->UpdateStateBlock->Set.material = TRUE;
1646 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1648 /* Handle recording of state blocks */
1649 if (This->isRecordingState) {
1650 TRACE("Recording... not performing anything\n");
1655 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1656 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1657 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1658 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1659 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1661 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1662 checkGLcall("glMaterialfv");
1663 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1664 checkGLcall("glMaterialfv");
1666 /* Only change material color if specular is enabled, otherwise it is set to black */
1667 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1668 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1669 checkGLcall("glMaterialfv");
1671 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1672 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1673 checkGLcall("glMaterialfv");
1675 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1676 checkGLcall("glMaterialfv");
1677 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1678 checkGLcall("glMaterialf");
1683 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1684 ICOM_THIS(IDirect3DDevice8Impl,iface);
1685 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1686 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1687 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1688 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1689 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1690 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1694 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1695 you can reference any indexes you want as long as that number max are enabled are any
1696 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1697 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1698 but when recording, just build a chain pretty much of commands to be replayed. */
1700 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1702 PLIGHTINFOEL *object, *temp;
1704 ICOM_THIS(IDirect3DDevice8Impl,iface);
1705 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1707 /* If recording state block, just add to end of lights chain */
1708 if (This->isRecordingState) {
1709 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1710 if (NULL == object) {
1711 return D3DERR_OUTOFVIDEOMEMORY;
1713 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1714 object->OriginalIndex = Index;
1715 object->glIndex = -1;
1716 object->changed = TRUE;
1718 /* Add to the END of the chain of lights changes to be replayed */
1719 if (This->UpdateStateBlock->lights == NULL) {
1720 This->UpdateStateBlock->lights = object;
1722 temp = This->UpdateStateBlock->lights;
1723 while (temp->next != NULL) temp=temp->next;
1724 temp->next = object;
1726 TRACE("Recording... not performing anything more\n");
1730 /* Ok, not recording any longer so do real work */
1731 object = This->StateBlock->lights;
1732 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1734 /* If we didnt find it in the list of lights, time to add it */
1735 if (object == NULL) {
1736 PLIGHTINFOEL *insertAt,*prevPos;
1738 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1739 if (NULL == object) {
1740 return D3DERR_OUTOFVIDEOMEMORY;
1742 object->OriginalIndex = Index;
1743 object->glIndex = -1;
1745 /* Add it to the front of list with the idea that lights will be changed as needed
1746 BUT after any lights currently assigned GL indexes */
1747 insertAt = This->StateBlock->lights;
1749 while (insertAt != NULL && insertAt->glIndex != -1) {
1751 insertAt = insertAt->next;
1754 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1755 This->StateBlock->lights = object;
1756 } else if (insertAt == NULL) { /* End of list */
1757 prevPos->next = object;
1758 object->prev = prevPos;
1759 } else { /* Middle of chain */
1760 if (prevPos == NULL) {
1761 This->StateBlock->lights = object;
1763 prevPos->next = object;
1765 object->prev = prevPos;
1766 object->next = insertAt;
1767 insertAt->prev = object;
1771 /* Initialze the object */
1772 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,
1773 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1774 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1775 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1776 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1777 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1778 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1780 /* Save away the information */
1781 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1783 switch (pLight->Type) {
1784 case D3DLIGHT_POINT:
1786 object->lightPosn[0] = pLight->Position.x;
1787 object->lightPosn[1] = pLight->Position.y;
1788 object->lightPosn[2] = pLight->Position.z;
1789 object->lightPosn[3] = 1.0f;
1790 object->cutoff = 180.0f;
1796 object->lightPosn[0] = pLight->Position.x;
1797 object->lightPosn[1] = pLight->Position.y;
1798 object->lightPosn[2] = pLight->Position.z;
1799 object->lightPosn[3] = 1.0;
1802 object->lightDirn[0] = pLight->Direction.x;
1803 object->lightDirn[1] = pLight->Direction.y;
1804 object->lightDirn[2] = pLight->Direction.z;
1805 object->lightDirn[3] = 1.0;
1808 * opengl-ish and d3d-ish spot lights use too different models for the
1809 * light "intensity" as a function of the angle towards the main light direction,
1810 * so we only can approximate very roughly.
1811 * however spot lights are rather rarely used in games (if ever used at all).
1812 * furthermore if still used, probably nobody pays attention to such details.
1814 if (pLight->Falloff == 0) {
1817 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1819 if (rho < 0.0001) rho = 0.0001f;
1820 object->exponent = -0.3/log(cos(rho/2));
1821 object->cutoff = pLight->Phi*90/M_PI;
1826 case D3DLIGHT_DIRECTIONAL:
1828 object->lightPosn[0] = -pLight->Direction.x;
1829 object->lightPosn[1] = -pLight->Direction.y;
1830 object->lightPosn[2] = -pLight->Direction.z;
1831 object->lightPosn[3] = 0.0;
1832 object->exponent = 0.0f;
1833 object->cutoff = 180.0f;
1837 FIXME("Unrecognized light type %d\n", pLight->Type);
1840 /* Update the live definitions if the light is currently assigned a glIndex */
1841 if (object->glIndex != -1) {
1842 setup_light(iface, object->glIndex, object);
1846 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1847 PLIGHTINFOEL *lightInfo = NULL;
1848 ICOM_THIS(IDirect3DDevice8Impl,iface);
1849 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1851 /* Locate the light in the live lights */
1852 lightInfo = This->StateBlock->lights;
1853 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1855 if (lightInfo == NULL) {
1856 TRACE("Light information requested but light not defined\n");
1857 return D3DERR_INVALIDCALL;
1860 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1863 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1864 PLIGHTINFOEL *lightInfo = NULL;
1865 ICOM_THIS(IDirect3DDevice8Impl,iface);
1866 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1868 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1869 if (This->isRecordingState) {
1870 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1871 if (NULL == lightInfo) {
1872 return D3DERR_OUTOFVIDEOMEMORY;
1874 lightInfo->OriginalIndex = Index;
1875 lightInfo->glIndex = -1;
1876 lightInfo->enabledChanged = TRUE;
1878 /* Add to the END of the chain of lights changes to be replayed */
1879 if (This->UpdateStateBlock->lights == NULL) {
1880 This->UpdateStateBlock->lights = lightInfo;
1882 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1883 while (temp->next != NULL) temp=temp->next;
1884 temp->next = lightInfo;
1886 TRACE("Recording... not performing anything more\n");
1890 /* Not recording... So, locate the light in the live lights */
1891 lightInfo = This->StateBlock->lights;
1892 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1894 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1895 if (lightInfo == NULL) {
1896 D3DLIGHT8 lightParms;
1897 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1898 wait until someone confirms it seems to work! */
1899 TRACE("Light enabled requested but light not defined, so defining one!\n");
1900 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1901 lightParms.Diffuse.r = 1.0;
1902 lightParms.Diffuse.g = 1.0;
1903 lightParms.Diffuse.b = 1.0;
1904 lightParms.Diffuse.a = 0.0;
1905 lightParms.Specular.r = 0.0;
1906 lightParms.Specular.g = 0.0;
1907 lightParms.Specular.b = 0.0;
1908 lightParms.Specular.a = 0.0;
1909 lightParms.Ambient.r = 0.0;
1910 lightParms.Ambient.g = 0.0;
1911 lightParms.Ambient.b = 0.0;
1912 lightParms.Ambient.a = 0.0;
1913 lightParms.Position.x = 0.0;
1914 lightParms.Position.y = 0.0;
1915 lightParms.Position.z = 0.0;
1916 lightParms.Direction.x = 0.0;
1917 lightParms.Direction.y = 0.0;
1918 lightParms.Direction.z = 1.0;
1919 lightParms.Range = 0.0;
1920 lightParms.Falloff = 0.0;
1921 lightParms.Attenuation0 = 0.0;
1922 lightParms.Attenuation1 = 0.0;
1923 lightParms.Attenuation2 = 0.0;
1924 lightParms.Theta = 0.0;
1925 lightParms.Phi = 0.0;
1926 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1928 /* Search for it again! Should be fairly quick as near head of list */
1929 lightInfo = This->StateBlock->lights;
1930 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1931 if (lightInfo == NULL) {
1932 FIXME("Adding default lights has failed dismally\n");
1933 return D3DERR_INVALIDCALL;
1937 /* OK, we now have a light... */
1938 if (Enable == FALSE) {
1940 /* If we are disabling it, check it was enabled, and
1941 still only do something if it has assigned a glIndex (which it should have!) */
1942 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1943 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1945 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1946 checkGLcall("glDisable GL_LIGHT0+Index");
1949 TRACE("Nothing to do as light was not enabled\n");
1951 lightInfo->lightEnabled = FALSE;
1954 /* We are enabling it. If it is enabled, its really simple */
1955 if (lightInfo->lightEnabled == TRUE) {
1957 TRACE("Nothing to do as light was enabled\n");
1959 /* If it already has a glIndex, its still simple */
1960 } else if (lightInfo->glIndex != -1) {
1961 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1962 lightInfo->lightEnabled = TRUE;
1964 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1965 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1968 /* Otherwise got to find space - lights are ordered gl indexes first */
1970 PLIGHTINFOEL *bsf = NULL;
1971 PLIGHTINFOEL *pos = This->StateBlock->lights;
1972 PLIGHTINFOEL *prev = NULL;
1976 /* Try to minimize changes as much as possible */
1977 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1979 /* Try to remember which index can be replaced if necessary */
1980 if (bsf==NULL && pos->lightEnabled == FALSE) {
1981 /* Found a light we can replace, save as best replacement */
1985 /* Step to next space */
1991 /* If we have too many active lights, fail the call */
1992 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1993 FIXME("Program requests too many concurrent lights\n");
1994 return D3DERR_INVALIDCALL;
1996 /* If we have allocated all lights, but not all are enabled,
1997 reuse one which is not enabled */
1998 } else if (Index == This->maxConcurrentLights) {
1999 /* use bsf - Simply swap the new light and the BSF one */
2000 PLIGHTINFOEL *bsfNext = bsf->next;
2001 PLIGHTINFOEL *bsfPrev = bsf->prev;
2004 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2005 if (bsf->prev != NULL) {
2006 bsf->prev->next = lightInfo;
2008 This->StateBlock->lights = lightInfo;
2011 /* If not side by side, lots of chains to update */
2012 if (bsf->next != lightInfo) {
2013 lightInfo->prev->next = bsf;
2014 bsf->next->prev = lightInfo;
2015 bsf->next = lightInfo->next;
2016 bsf->prev = lightInfo->prev;
2017 lightInfo->next = bsfNext;
2018 lightInfo->prev = bsfPrev;
2022 bsf->prev = lightInfo;
2023 bsf->next = lightInfo->next;
2024 lightInfo->next = bsf;
2025 lightInfo->prev = bsfPrev;
2030 glIndex = bsf->glIndex;
2032 lightInfo->glIndex = glIndex;
2033 lightInfo->lightEnabled = TRUE;
2035 /* Finally set up the light in gl itself */
2036 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2038 setup_light(iface, glIndex, lightInfo);
2039 glEnable(GL_LIGHT0 + glIndex);
2040 checkGLcall("glEnable GL_LIGHT0 new setup");
2043 /* If we reached the end of the allocated lights, with space in the
2044 gl lights, setup a new light */
2045 } else if (pos->glIndex == -1) {
2047 /* We reached the end of the allocated gl lights, so already
2048 know the index of the next one! */
2050 lightInfo->glIndex = glIndex;
2051 lightInfo->lightEnabled = TRUE;
2053 /* In an ideal world, its already in the right place */
2054 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2055 /* No need to move it */
2057 /* Remove this light from the list */
2058 lightInfo->prev->next = lightInfo->next;
2059 if (lightInfo->next != NULL) {
2060 lightInfo->next->prev = lightInfo->prev;
2063 /* Add in at appropriate place (inbetween prev and pos) */
2064 lightInfo->prev = prev;
2065 lightInfo->next = pos;
2067 This->StateBlock->lights = lightInfo;
2069 prev->next = lightInfo;
2072 pos->prev = lightInfo;
2076 /* Finally set up the light in gl itself */
2077 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2079 setup_light(iface, glIndex, lightInfo);
2080 glEnable(GL_LIGHT0 + glIndex);
2081 checkGLcall("glEnable GL_LIGHT0 new setup");
2089 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2091 PLIGHTINFOEL *lightInfo = NULL;
2092 ICOM_THIS(IDirect3DDevice8Impl,iface);
2093 TRACE("(%p) : for idx(%ld)\n", This, Index);
2095 /* Locate the light in the live lights */
2096 lightInfo = This->StateBlock->lights;
2097 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2099 if (lightInfo == NULL) {
2100 TRACE("Light enabled state requested but light not defined\n");
2101 return D3DERR_INVALIDCALL;
2103 *pEnable = lightInfo->lightEnabled;
2106 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2107 ICOM_THIS(IDirect3DDevice8Impl,iface);
2108 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2110 /* Validate Index */
2111 if (Index >= GL_LIMITS(clipplanes)) {
2112 TRACE("Application has requested clipplane this device doesnt support\n");
2113 return D3DERR_INVALIDCALL;
2116 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2117 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2118 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2119 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2120 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2121 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2123 /* Handle recording of state blocks */
2124 if (This->isRecordingState) {
2125 TRACE("Recording... not performing anything\n");
2133 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2134 glMatrixMode(GL_MODELVIEW);
2136 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2138 TRACE("Clipplane [%f,%f,%f,%f]\n",
2139 This->UpdateStateBlock->clipplane[Index][0],
2140 This->UpdateStateBlock->clipplane[Index][1],
2141 This->UpdateStateBlock->clipplane[Index][2],
2142 This->UpdateStateBlock->clipplane[Index][3]);
2143 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2144 checkGLcall("glClipPlane");
2152 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2153 ICOM_THIS(IDirect3DDevice8Impl,iface);
2154 TRACE("(%p) : for idx %ld\n", This, Index);
2156 /* Validate Index */
2157 if (Index >= GL_LIMITS(clipplanes)) {
2158 TRACE("Application has requested clipplane this device doesnt support\n");
2159 return D3DERR_INVALIDCALL;
2162 pPlane[0] = This->StateBlock->clipplane[Index][0];
2163 pPlane[1] = This->StateBlock->clipplane[Index][1];
2164 pPlane[2] = This->StateBlock->clipplane[Index][2];
2165 pPlane[3] = This->StateBlock->clipplane[Index][3];
2168 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2169 ICOM_THIS(IDirect3DDevice8Impl,iface);
2170 DWORD OldValue = This->StateBlock->renderstate[State];
2172 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2173 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2174 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2175 This->UpdateStateBlock->renderstate[State] = Value;
2177 /* Handle recording of state blocks */
2178 if (This->isRecordingState) {
2179 TRACE("Recording... not performing anything\n");
2186 case D3DRS_FILLMODE :
2187 switch ((D3DFILLMODE) Value) {
2188 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2189 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2190 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2192 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2194 checkGLcall("glPolygonMode (fillmode)");
2197 case D3DRS_LIGHTING :
2199 glEnable(GL_LIGHTING);
2200 checkGLcall("glEnable GL_LIGHTING");
2202 glDisable(GL_LIGHTING);
2203 checkGLcall("glDisable GL_LIGHTING");
2207 case D3DRS_ZENABLE :
2208 switch ((D3DZBUFFERTYPE) Value) {
2210 glDisable(GL_DEPTH_TEST);
2211 checkGLcall("glDisable GL_DEPTH_TEST");
2214 glEnable(GL_DEPTH_TEST);
2215 checkGLcall("glEnable GL_DEPTH_TEST");
2220 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2224 case D3DRS_CULLMODE :
2226 /* If we are culling "back faces with clockwise vertices" then
2227 set front faces to be counter clockwise and enable culling
2229 switch ((D3DCULL) Value) {
2231 glDisable(GL_CULL_FACE);
2232 checkGLcall("glDisable GL_CULL_FACE");
2235 glEnable(GL_CULL_FACE);
2236 checkGLcall("glEnable GL_CULL_FACE");
2237 glFrontFace(GL_CCW);
2238 checkGLcall("glFrontFace GL_CCW");
2239 glCullFace(GL_BACK);
2242 glEnable(GL_CULL_FACE);
2243 checkGLcall("glEnable GL_CULL_FACE");
2245 checkGLcall("glFrontFace GL_CW");
2246 glCullFace(GL_BACK);
2249 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2253 case D3DRS_SHADEMODE :
2254 switch ((D3DSHADEMODE) Value) {
2256 glShadeModel(GL_FLAT);
2257 checkGLcall("glShadeModel");
2259 case D3DSHADE_GOURAUD:
2260 glShadeModel(GL_SMOOTH);
2261 checkGLcall("glShadeModel");
2263 case D3DSHADE_PHONG:
2264 FIXME("D3DSHADE_PHONG isnt supported?\n");
2267 return D3DERR_INVALIDCALL;
2269 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2273 case D3DRS_DITHERENABLE :
2275 glEnable(GL_DITHER);
2276 checkGLcall("glEnable GL_DITHER");
2278 glDisable(GL_DITHER);
2279 checkGLcall("glDisable GL_DITHER");
2283 case D3DRS_ZWRITEENABLE :
2286 checkGLcall("glDepthMask");
2289 checkGLcall("glDepthMask");
2295 int glParm = GL_LESS;
2297 switch ((D3DCMPFUNC) Value) {
2298 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2299 case D3DCMP_LESS: glParm=GL_LESS; break;
2300 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2301 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2302 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2303 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2304 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2305 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2307 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2309 glDepthFunc(glParm);
2310 checkGLcall("glDepthFunc");
2314 case D3DRS_AMBIENT :
2317 D3DCOLORTOGLFLOAT4(Value, col);
2318 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2319 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2320 checkGLcall("glLightModel for MODEL_AMBIENT");
2325 case D3DRS_ALPHABLENDENABLE :
2328 checkGLcall("glEnable GL_BLEND");
2330 glDisable(GL_BLEND);
2331 checkGLcall("glDisable GL_BLEND");
2335 case D3DRS_SRCBLEND :
2336 case D3DRS_DESTBLEND :
2338 int newVal = GL_ZERO;
2340 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2341 case D3DBLEND_ONE : newVal = GL_ONE; break;
2342 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2343 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2344 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2345 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2346 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2347 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2348 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2349 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2350 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2352 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2353 This->srcBlend = newVal;
2354 This->dstBlend = newVal;
2357 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2358 This->srcBlend = newVal;
2359 This->dstBlend = newVal;
2362 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2365 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2366 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2367 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2368 glBlendFunc(This->srcBlend, This->dstBlend);
2370 checkGLcall("glBlendFunc");
2374 case D3DRS_ALPHATESTENABLE :
2376 glEnable(GL_ALPHA_TEST);
2377 checkGLcall("glEnable GL_ALPHA_TEST");
2379 glDisable(GL_ALPHA_TEST);
2380 checkGLcall("glDisable GL_ALPHA_TEST");
2384 case D3DRS_ALPHAFUNC :
2386 int glParm = GL_LESS;
2387 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2389 switch ((D3DCMPFUNC) Value) {
2390 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2391 case D3DCMP_LESS: glParm = GL_LESS; break;
2392 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2393 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2394 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2395 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2396 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2397 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2399 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2401 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2402 glAlphaFunc(glParm, ref);
2403 This->alphafunc = glParm;
2404 checkGLcall("glAlphaFunc");
2408 case D3DRS_ALPHAREF :
2410 int glParm = This->alphafunc;
2413 ref = ((float) Value) / 255.0f;
2414 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2415 glAlphaFunc(glParm, ref);
2416 checkGLcall("glAlphaFunc");
2420 case D3DRS_CLIPPLANEENABLE :
2421 case D3DRS_CLIPPING :
2423 /* Ensure we only do the changed clip planes */
2424 DWORD enable = 0xFFFFFFFF;
2425 DWORD disable = 0x00000000;
2427 /* If enabling / disabling all */
2428 if (State == D3DRS_CLIPPING) {
2430 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2433 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2437 enable = Value & ~OldValue;
2438 disable = ~Value & OldValue;
2441 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2442 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2443 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2444 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2445 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2446 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2448 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2449 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2450 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2451 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2452 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2453 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2457 case D3DRS_BLENDOP :
2459 int glParm = GL_FUNC_ADD;
2461 switch ((D3DBLENDOP) Value) {
2462 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2463 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2464 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2465 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2466 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2468 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2470 TRACE("glBlendEquation(%x)\n", glParm);
2471 glBlendEquation(glParm);
2472 checkGLcall("glBlendEquation");
2476 case D3DRS_TEXTUREFACTOR :
2480 /* Note the texture color applies to all textures whereas
2481 GL_TEXTURE_ENV_COLOR applies to active only */
2483 D3DCOLORTOGLFLOAT4(Value, col);
2484 /* Set the default alpha blend color */
2485 glBlendColor(col[0], col[1], col[2], col[3]);
2486 checkGLcall("glBlendColor");
2488 /* And now the default texture color as well */
2489 for (i = 0; i < GL_LIMITS(textures); i++) {
2491 /* Note the D3DRS value applies to all textures, but GL has one
2492 per texture, so apply it now ready to be used! */
2493 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2494 #if defined(GL_VERSION_1_3)
2495 glActiveTexture(GL_TEXTURE0 + i);
2497 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2499 checkGLcall("Activate texture.. to update const color");
2501 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2504 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2505 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2510 case D3DRS_SPECULARENABLE :
2512 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2513 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2514 specular color. This is wrong:
2515 Separate specular color means the specular colour is maintained separately, whereas
2516 single color means it is merged in. However in both cases they are being used to
2518 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2519 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2523 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2524 checkGLcall("glMaterialfv");
2525 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2526 glEnable(GL_COLOR_SUM_EXT);
2528 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2530 checkGLcall("glEnable(GL_COLOR_SUM)");
2532 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2534 /* for the case of enabled lighting: */
2535 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2536 checkGLcall("glMaterialfv");
2538 /* for the case of disabled lighting: */
2539 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2540 glDisable(GL_COLOR_SUM_EXT);
2542 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2544 checkGLcall("glDisable(GL_COLOR_SUM)");
2549 case D3DRS_STENCILENABLE :
2551 glEnable(GL_STENCIL_TEST);
2552 checkGLcall("glEnable GL_STENCIL_TEST");
2554 glDisable(GL_STENCIL_TEST);
2555 checkGLcall("glDisable GL_STENCIL_TEST");
2559 case D3DRS_STENCILFUNC :
2561 int glParm = GL_ALWAYS;
2562 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2563 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2565 switch ((D3DCMPFUNC) Value) {
2566 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2567 case D3DCMP_LESS: glParm=GL_LESS; break;
2568 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2569 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2570 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2571 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2572 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2573 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2575 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2577 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2578 This->stencilfunc = glParm;
2579 glStencilFunc(glParm, ref, mask);
2580 checkGLcall("glStencilFunc");
2584 case D3DRS_STENCILREF :
2586 int glParm = This->stencilfunc;
2588 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2591 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2592 glStencilFunc(glParm, ref, mask);
2593 checkGLcall("glStencilFunc");
2597 case D3DRS_STENCILMASK :
2599 int glParm = This->stencilfunc;
2600 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2601 GLuint mask = Value;
2603 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2604 glStencilFunc(glParm, ref, mask);
2605 checkGLcall("glStencilFunc");
2609 case D3DRS_STENCILFAIL :
2615 fail = StencilOp(Value);
2616 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2617 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2618 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2619 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2621 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2622 glStencilOp(fail, zfail, zpass);
2623 checkGLcall("glStencilOp(fail, zfail, zpass);");
2626 case D3DRS_STENCILZFAIL :
2632 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2633 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2634 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2635 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2636 zfail = StencilOp(Value);
2638 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2639 glStencilOp(fail, zfail, zpass);
2640 checkGLcall("glStencilOp(fail, zfail, zpass);");
2643 case D3DRS_STENCILPASS :
2649 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2650 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2651 zpass = StencilOp(Value);
2652 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2653 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2655 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2656 glStencilOp(fail, zfail, zpass);
2657 checkGLcall("glStencilOp(fail, zfail, zpass);");
2661 case D3DRS_STENCILWRITEMASK :
2663 glStencilMask(Value);
2664 TRACE("glStencilMask(%lu)\n", Value);
2665 checkGLcall("glStencilMask");
2669 case D3DRS_FOGENABLE :
2671 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2673 checkGLcall("glEnable GL_FOG");
2676 checkGLcall("glDisable GL_FOG");
2681 case D3DRS_FOGCOLOR :
2684 D3DCOLORTOGLFLOAT4(Value, col);
2685 /* Set the default alpha blend color */
2686 glFogfv(GL_FOG_COLOR, &col[0]);
2687 checkGLcall("glFog GL_FOG_COLOR");
2691 case D3DRS_FOGTABLEMODE :
2694 case D3DFOG_NONE: /* I don't know what to do here */ break;
2695 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2696 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2697 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2699 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2704 case D3DRS_FOGSTART :
2706 float *f = (float*) &Value;
2707 glFogfv(GL_FOG_START, f);
2708 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2709 TRACE("Fog Start == %f\n", *f);
2715 float *f = (float*) &Value;
2716 glFogfv(GL_FOG_END, f);
2717 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2718 TRACE("Fog End == %f\n", *f);
2722 case D3DRS_FOGDENSITY :
2724 float *f = (float*) &Value;
2725 glFogfv(GL_FOG_DENSITY, f);
2726 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2730 case D3DRS_VERTEXBLEND :
2732 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2733 TRACE("Vertex Blending state to %ld\n", Value);
2737 case D3DRS_TWEENFACTOR :
2739 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2740 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2744 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2746 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2750 case D3DRS_COLORVERTEX :
2751 case D3DRS_DIFFUSEMATERIALSOURCE :
2752 case D3DRS_SPECULARMATERIALSOURCE :
2753 case D3DRS_AMBIENTMATERIALSOURCE :
2754 case D3DRS_EMISSIVEMATERIALSOURCE :
2756 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2758 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2759 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2760 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2761 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2762 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2763 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2765 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2766 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2767 Parm = GL_AMBIENT_AND_DIFFUSE;
2771 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2773 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2775 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2782 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2784 This->tracking_color = NEEDS_TRACKING;
2785 This->tracking_parm = Parm;
2789 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2794 case D3DRS_LINEPATTERN :
2796 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2797 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2799 if (pattern->wRepeatFactor) {
2800 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2801 checkGLcall("glLineStipple(repeat, linepattern)");
2802 glEnable(GL_LINE_STIPPLE);
2803 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2805 glDisable(GL_LINE_STIPPLE);
2806 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2814 TRACE("ZBias value %f\n", *((float*)&Value));
2815 glPolygonOffset(0, -*((float*)&Value));
2816 checkGLcall("glPolygonOffset(0, -Value)");
2817 glEnable(GL_POLYGON_OFFSET_FILL);
2818 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2819 glEnable(GL_POLYGON_OFFSET_LINE);
2820 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2821 glEnable(GL_POLYGON_OFFSET_POINT);
2822 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2824 glDisable(GL_POLYGON_OFFSET_FILL);
2825 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2826 glDisable(GL_POLYGON_OFFSET_LINE);
2827 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2828 glDisable(GL_POLYGON_OFFSET_POINT);
2829 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2834 case D3DRS_NORMALIZENORMALS :
2836 glEnable(GL_NORMALIZE);
2837 checkGLcall("glEnable(GL_NORMALIZE);");
2839 glDisable(GL_NORMALIZE);
2840 checkGLcall("glDisable(GL_NORMALIZE);");
2844 case D3DRS_POINTSIZE :
2845 TRACE("Set point size to %f\n", *((float*)&Value));
2846 glPointSize(*((float*)&Value));
2847 checkGLcall("glPointSize(...);");
2850 case D3DRS_POINTSIZE_MIN :
2851 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2852 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2853 checkGLcall("glPointParameterfEXT(...);");
2855 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2859 case D3DRS_POINTSIZE_MAX :
2860 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2861 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2862 checkGLcall("glPointParameterfEXT(...);");
2864 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2868 case D3DRS_POINTSCALE_A :
2869 case D3DRS_POINTSCALE_B :
2870 case D3DRS_POINTSCALE_C :
2871 case D3DRS_POINTSCALEENABLE :
2873 /* If enabled, supply the parameters, otherwise fall back to defaults */
2874 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2875 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2876 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2877 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2878 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2880 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2881 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2882 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2884 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2887 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2888 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2889 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2890 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2892 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2898 case D3DRS_COLORWRITEENABLE :
2899 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2900 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2901 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2902 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2903 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2904 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
2905 Value & D3DCOLORWRITEENABLE_GREEN,
2906 Value & D3DCOLORWRITEENABLE_BLUE,
2907 Value & D3DCOLORWRITEENABLE_ALPHA);
2908 checkGLcall("glColorMask(...)");
2911 /* Unhandled yet...! */
2912 case D3DRS_LASTPIXEL :
2913 case D3DRS_ZVISIBLE :
2914 case D3DRS_EDGEANTIALIAS :
2915 case D3DRS_RANGEFOGENABLE :
2924 case D3DRS_FOGVERTEXMODE :
2925 case D3DRS_LOCALVIEWER :
2926 case D3DRS_SOFTWAREVERTEXPROCESSING :
2927 case D3DRS_POINTSPRITEENABLE :
2928 case D3DRS_MULTISAMPLEANTIALIAS :
2929 case D3DRS_MULTISAMPLEMASK :
2930 case D3DRS_PATCHEDGESTYLE :
2931 case D3DRS_PATCHSEGMENTS :
2932 case D3DRS_DEBUGMONITORTOKEN :
2933 case D3DRS_POSITIONORDER :
2934 case D3DRS_NORMALORDER :
2935 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2936 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2939 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2946 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2947 ICOM_THIS(IDirect3DDevice8Impl,iface);
2948 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2949 *pValue = This->StateBlock->renderstate[State];
2952 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2953 ICOM_THIS(IDirect3DDevice8Impl,iface);
2955 TRACE("(%p)\n", This);
2957 return IDirect3DDeviceImpl_BeginStateBlock(This);
2959 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2960 IDirect3DStateBlockImpl* pSB;
2961 ICOM_THIS(IDirect3DDevice8Impl,iface);
2964 TRACE("(%p)\n", This);
2966 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2967 *pToken = (DWORD) pSB;
2971 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2972 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2973 ICOM_THIS(IDirect3DDevice8Impl,iface);
2975 TRACE("(%p)\n", This);
2977 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2980 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2981 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2982 ICOM_THIS(IDirect3DDevice8Impl,iface);
2984 TRACE("(%p)\n", This);
2986 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2988 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2989 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2990 ICOM_THIS(IDirect3DDevice8Impl,iface);
2992 TRACE("(%p)\n", This);
2994 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2997 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2998 IDirect3DStateBlockImpl* pSB;
2999 ICOM_THIS(IDirect3DDevice8Impl,iface);
3002 TRACE("(%p) : for type %d\n", This, Type);
3004 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3005 *pToken = (DWORD) pSB;
3009 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3010 ICOM_THIS(IDirect3DDevice8Impl,iface);
3011 FIXME("(%p) : stub\n", This); return D3D_OK;
3013 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3014 ICOM_THIS(IDirect3DDevice8Impl,iface);
3015 FIXME("(%p) : stub\n", This); return D3D_OK;
3017 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3018 ICOM_THIS(IDirect3DDevice8Impl,iface);
3019 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3020 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3021 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3024 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3026 IDirect3DBaseTexture8 *oldTxt;
3027 BOOL reapplyStates = TRUE;
3028 DWORD oldTextureDimensions = -1;
3029 DWORD reapplyFlags = 0;
3031 ICOM_THIS(IDirect3DDevice8Impl,iface);
3032 D3DRESOURCETYPE textureType;
3034 oldTxt = This->UpdateStateBlock->textures[Stage];
3035 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3037 /* Reject invalid texture units */
3038 if (Stage >= GL_LIMITS(textures)) {
3039 TRACE("Attempt to access invalid texture rejected\n");
3040 return D3DERR_INVALIDCALL;
3043 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3044 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3045 This->UpdateStateBlock->textures[Stage] = pTexture;
3047 /* Handle recording of state blocks */
3048 if (This->isRecordingState) {
3049 TRACE("Recording... not performing anything\n");
3053 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3056 /* Make appropriate texture active */
3057 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3058 #if defined(GL_VERSION_1_3)
3059 glActiveTexture(GL_TEXTURE0 + Stage);
3061 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3063 checkGLcall("glActiveTextureARB");
3064 } else if (Stage>0) {
3065 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3068 /* Decrement the count of the previous texture */
3069 if (NULL != oldTxt) {
3070 IDirect3DBaseTexture8Impl_Release(oldTxt);
3073 if (NULL != pTexture) {
3074 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3076 /* Now setup the texture appropraitly */
3077 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3079 if (textureType == D3DRTYPE_TEXTURE) {
3080 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3081 TRACE("Skipping setting texture as old == new\n");
3082 reapplyStates = FALSE;
3084 /* Standard 2D texture */
3085 TRACE("Standard 2d texture\n");
3086 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3088 /* Load up the texture now */
3089 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3091 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3092 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3093 TRACE("Skipping setting texture as old == new\n");
3094 reapplyStates = FALSE;
3096 /* Standard 3D (volume) texture */
3097 TRACE("Standard 3d texture\n");
3098 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3100 /* Load up the texture now */
3101 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3103 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3104 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3105 TRACE("Skipping setting texture as old == new\n");
3106 reapplyStates = FALSE;
3108 /* Standard Cube texture */
3109 TRACE("Standard Cube texture\n");
3110 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3112 /* Load up the texture now */
3113 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3116 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3119 TRACE("Setting to no texture (ie default texture)\n");
3120 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3121 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3122 checkGLcall("glBindTexture");
3123 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3126 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3127 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3128 glDisable(oldTextureDimensions);
3129 checkGLcall("Disable oldTextureDimensions");
3130 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3131 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3132 checkGLcall("glEnable new texture dimensions");
3135 /* If Alpha arg1 is texture then handle the special case when there changes between a
3136 texture and no texture - See comments in set_tex_op */
3137 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3138 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3140 reapplyFlags |= REAPPLY_ALPHAOP;
3145 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3146 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3147 if (reapplyStates) {
3148 setupTextureStates(iface, Stage, reapplyFlags);
3156 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3157 ICOM_THIS(IDirect3DDevice8Impl,iface);
3158 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3159 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3163 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3164 ICOM_THIS(IDirect3DDevice8Impl,iface);
3166 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3168 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3170 /* Reject invalid texture units */
3171 if (Stage >= GL_LIMITS(textures)) {
3172 TRACE("Attempt to access invalid texture rejected\n");
3173 return D3DERR_INVALIDCALL;
3176 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3177 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3178 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3180 /* Handle recording of state blocks */
3181 if (This->isRecordingState) {
3182 TRACE("Recording... not performing anything\n");
3188 /* Make appropriate texture active */
3189 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3190 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3191 #if defined(GL_VERSION_1_3)
3192 glActiveTexture(GL_TEXTURE0 + Stage);
3193 vcheckGLcall("glActiveTexture");
3195 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3196 vcheckGLcall("glActiveTextureARB");
3198 } else if (Stage > 0) {
3199 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3204 case D3DTSS_MINFILTER :
3205 case D3DTSS_MIPFILTER :
3207 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3208 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3209 GLint realVal = GL_LINEAR;
3211 if (ValueMIN == D3DTEXF_POINT) {
3213 if (ValueMIP == D3DTEXF_POINT) {
3214 realVal = GL_NEAREST_MIPMAP_NEAREST;
3215 } else if (ValueMIP == D3DTEXF_LINEAR) {
3216 realVal = GL_NEAREST_MIPMAP_LINEAR;
3217 } else if (ValueMIP == D3DTEXF_NONE) {
3218 realVal = GL_NEAREST;
3220 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3221 realVal = GL_NEAREST_MIPMAP_LINEAR;
3223 } else if (ValueMIN == D3DTEXF_LINEAR) {
3225 if (ValueMIP == D3DTEXF_POINT) {
3226 realVal = GL_LINEAR_MIPMAP_NEAREST;
3227 } else if (ValueMIP == D3DTEXF_LINEAR) {
3228 realVal = GL_LINEAR_MIPMAP_LINEAR;
3229 } else if (ValueMIP == D3DTEXF_NONE) {
3230 realVal = GL_LINEAR;
3232 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3233 realVal = GL_LINEAR_MIPMAP_LINEAR;
3235 } else if (ValueMIN == D3DTEXF_NONE) {
3236 /* Doesnt really make sense - Windows just seems to disable
3237 mipmapping when this occurs */
3238 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3239 realVal = GL_LINEAR;
3242 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3243 realVal = GL_LINEAR_MIPMAP_LINEAR;
3246 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3247 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3248 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3252 case D3DTSS_MAXANISOTROPY :
3254 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3255 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3256 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3261 case D3DTSS_MAGFILTER :
3262 if (Value == D3DTEXF_POINT) {
3263 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3264 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3265 } else if (Value == D3DTEXF_LINEAR) {
3266 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3267 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3269 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3273 case D3DTSS_ALPHAOP :
3274 case D3DTSS_COLOROP :
3277 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3278 /* TODO: Disable by making this and all later levels disabled */
3279 glDisable(GL_TEXTURE_1D);
3280 checkGLcall("Disable GL_TEXTURE_1D");
3281 glDisable(GL_TEXTURE_2D);
3282 checkGLcall("Disable GL_TEXTURE_2D");
3283 glDisable(GL_TEXTURE_3D);
3284 checkGLcall("Disable GL_TEXTURE_3D");
3285 break; /* Dont bother setting the texture operations */
3287 /* Enable only the appropriate texture dimension */
3288 if (Type == D3DTSS_COLOROP) {
3289 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3290 glEnable(GL_TEXTURE_1D);
3291 checkGLcall("Enable GL_TEXTURE_1D");
3293 glDisable(GL_TEXTURE_1D);
3294 checkGLcall("Disable GL_TEXTURE_1D");
3296 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3297 glEnable(GL_TEXTURE_2D);
3298 checkGLcall("Enable GL_TEXTURE_2D");
3300 glDisable(GL_TEXTURE_2D);
3301 checkGLcall("Disable GL_TEXTURE_2D");
3303 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3304 glEnable(GL_TEXTURE_3D);
3305 checkGLcall("Enable GL_TEXTURE_3D");
3307 glDisable(GL_TEXTURE_3D);
3308 checkGLcall("Disable GL_TEXTURE_3D");
3310 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3311 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3312 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3314 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3315 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3319 /* Drop through... (Except disable case) */
3320 case D3DTSS_COLORARG0 :
3321 case D3DTSS_COLORARG1 :
3322 case D3DTSS_COLORARG2 :
3323 case D3DTSS_ALPHAARG0 :
3324 case D3DTSS_ALPHAARG1 :
3325 case D3DTSS_ALPHAARG2 :
3327 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3328 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3330 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3331 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3332 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3333 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3335 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3336 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3337 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3338 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3344 case D3DTSS_ADDRESSU :
3345 case D3DTSS_ADDRESSV :
3346 case D3DTSS_ADDRESSW :
3348 GLint wrapParm = GL_REPEAT;
3350 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3351 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3352 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3353 #if defined(GL_VERSION_1_4)
3354 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3355 #elif defined(GL_ARB_texture_mirrored_repeat)
3356 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3358 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3360 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3362 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3363 wrapParm = GL_REPEAT;
3367 case D3DTSS_ADDRESSU:
3368 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3369 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3370 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3372 case D3DTSS_ADDRESSV:
3373 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3374 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3375 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3377 case D3DTSS_ADDRESSW:
3378 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3379 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3380 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3383 break; /** stupic compilator */
3388 case D3DTSS_BORDERCOLOR :
3391 D3DCOLORTOGLFLOAT4(Value, col);
3392 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3393 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3394 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3398 case D3DTSS_TEXCOORDINDEX :
3400 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3402 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3403 one flag, you can still specify an index value, which the system uses to
3404 determine the texture wrapping mode.
3405 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3406 means use the vertex position (camera-space) as the input texture coordinates
3407 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3408 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3409 to the TEXCOORDINDEX value */
3412 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3414 switch (Value & 0xFFFF0000) {
3415 case D3DTSS_TCI_PASSTHRU:
3416 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3417 glDisable(GL_TEXTURE_GEN_S);
3418 glDisable(GL_TEXTURE_GEN_T);
3419 glDisable(GL_TEXTURE_GEN_R);
3420 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3423 case D3DTSS_TCI_CAMERASPACEPOSITION:
3424 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3425 as the input texture coordinates for this stage's texture transformation. This
3426 equates roughly to EYE_LINEAR */
3428 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3429 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3430 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3431 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3432 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3434 glMatrixMode(GL_MODELVIEW);
3437 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3438 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3439 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3440 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3443 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3444 glEnable(GL_TEXTURE_GEN_S);
3445 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3446 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3447 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3448 glEnable(GL_TEXTURE_GEN_T);
3449 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3450 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3451 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3452 glEnable(GL_TEXTURE_GEN_R);
3453 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3454 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3455 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3459 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3460 case D3DTSS_TCI_CAMERASPACENORMAL:
3462 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3463 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3464 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3465 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3466 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3468 glMatrixMode(GL_MODELVIEW);
3471 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3472 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3473 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3474 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3477 glEnable(GL_TEXTURE_GEN_S);
3478 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3479 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3480 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3481 glEnable(GL_TEXTURE_GEN_T);
3482 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3483 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3484 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3485 glEnable(GL_TEXTURE_GEN_R);
3486 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3487 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3488 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3493 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3494 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3497 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3498 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3499 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3500 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3501 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3503 glMatrixMode(GL_MODELVIEW);
3506 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3507 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3508 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3509 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3512 glEnable(GL_TEXTURE_GEN_S);
3513 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3514 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3515 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3516 glEnable(GL_TEXTURE_GEN_T);
3517 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3518 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3519 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3520 glEnable(GL_TEXTURE_GEN_R);
3521 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3522 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3523 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3528 /* Unhandled types: */
3531 /* ? disable GL_TEXTURE_GEN_n ? */
3532 glDisable(GL_TEXTURE_GEN_S);
3533 glDisable(GL_TEXTURE_GEN_T);
3534 glDisable(GL_TEXTURE_GEN_R);
3535 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3542 case D3DTSS_BUMPENVMAT00 :
3543 case D3DTSS_BUMPENVMAT01 :
3544 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3546 case D3DTSS_BUMPENVMAT10 :
3547 case D3DTSS_BUMPENVMAT11 :
3548 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3551 case D3DTSS_TEXTURETRANSFORMFLAGS :
3552 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3555 case D3DTSS_MIPMAPLODBIAS :
3556 case D3DTSS_MAXMIPLEVEL :
3557 case D3DTSS_BUMPENVLSCALE :
3558 case D3DTSS_BUMPENVLOFFSET :
3559 case D3DTSS_RESULTARG :
3561 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3562 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3569 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3570 ICOM_THIS(IDirect3DDevice8Impl,iface);
3571 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3574 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3575 ICOM_THIS(IDirect3DDevice8Impl,iface);
3576 FIXME("(%p) : stub\n", This);
3579 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3580 ICOM_THIS(IDirect3DDevice8Impl,iface);
3581 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3582 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3583 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3586 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3587 ICOM_THIS(IDirect3DDevice8Impl,iface);
3588 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3589 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3590 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3593 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3594 ICOM_THIS(IDirect3DDevice8Impl,iface);
3595 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3596 This->currentPalette = PaletteNumber;
3598 #if defined(GL_EXT_paletted_texture)
3599 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3603 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3604 GL_RGBA, /* internal format */
3605 256, /* table size */
3606 GL_RGBA, /* table format */
3607 GL_UNSIGNED_BYTE, /* table type */
3608 This->palettes[PaletteNumber]);
3609 checkGLcall("glColorTableEXT");
3614 /* Delayed palette handling ... waiting for software emulation into preload code */
3619 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3620 ICOM_THIS(IDirect3DDevice8Impl,iface);
3621 *PaletteNumber = This->currentPalette;
3622 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3625 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3627 ICOM_THIS(IDirect3DDevice8Impl,iface);
3628 This->StateBlock->streamIsUP = FALSE;
3630 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3631 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3635 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3636 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3638 IDirect3DIndexBuffer8 *pIB;
3639 D3DINDEXBUFFER_DESC IdxBufDsc;
3641 ICOM_THIS(IDirect3DDevice8Impl,iface);
3642 pIB = This->StateBlock->pIndexData;
3643 This->StateBlock->streamIsUP = FALSE;
3645 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3646 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3647 minIndex, NumVertices, startIndex, primCount);
3649 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3650 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3656 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3661 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3662 ICOM_THIS(IDirect3DDevice8Impl,iface);
3664 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3665 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3667 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3669 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3670 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3671 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3672 This->StateBlock->streamIsUP = TRUE;
3673 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3674 This->StateBlock->stream_stride[0] = 0;
3675 This->StateBlock->stream_source[0] = NULL;
3677 /*stream zero settings set to null at end */
3680 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3681 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3682 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3683 UINT VertexStreamZeroStride) {
3685 ICOM_THIS(IDirect3DDevice8Impl,iface);
3686 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),
3687 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3689 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3690 if (IndexDataFormat == D3DFMT_INDEX16) {
3696 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3697 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3698 This->StateBlock->streamIsUP = TRUE;
3699 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3700 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3702 /*stream zero settings set to null at end */
3703 This->StateBlock->stream_source[0] = NULL;
3704 This->StateBlock->stream_stride[0] = 0;
3705 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3709 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3710 ICOM_THIS(IDirect3DDevice8Impl,iface);
3711 FIXME("(%p) : stub\n", This); return D3D_OK;
3713 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3714 ICOM_THIS(IDirect3DDevice8Impl,iface);
3715 IDirect3DVertexShaderImpl* object;
3716 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3720 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3721 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3722 return D3DERR_INVALIDCALL;
3724 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3725 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3726 return D3DERR_OUTOFVIDEOMEMORY;
3729 /** Create the Vertex Shader */
3730 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3731 /** TODO: check FAILED(res) */
3733 /** Create and Bind the Vertex Shader Declaration */
3734 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3735 /** TODO: check FAILED(res) */
3737 VertexShaders[i] = object;
3738 VertexShaderDeclarations[i] = attached_decl;
3739 *pHandle = VS_HIGHESTFIXEDFXF + i;
3740 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3744 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3745 ICOM_THIS(IDirect3DDevice8Impl,iface);
3747 This->UpdateStateBlock->VertexShader = Handle;
3748 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3749 This->UpdateStateBlock->Set.vertexShader = TRUE;
3751 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3752 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3753 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3754 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3755 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3756 } else { /* use a fvf, so desactivate the vshader decl */
3757 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3758 This->UpdateStateBlock->vertexShaderDecl = NULL;
3759 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3760 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3762 /* Handle recording of state blocks */
3763 if (This->isRecordingState) {
3764 TRACE("Recording... not performing anything\n");
3768 * TODO: merge HAL shaders context switching from prototype
3772 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3773 ICOM_THIS(IDirect3DDevice8Impl,iface);
3774 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3775 *pHandle = This->StateBlock->VertexShader;
3779 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3780 ICOM_THIS(IDirect3DDevice8Impl,iface);
3781 IDirect3DVertexShaderImpl* object;
3782 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3784 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3785 return D3DERR_INVALIDCALL;
3789 * Delete Vertex Shader
3791 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3792 if (NULL == object) {
3793 return D3DERR_INVALIDCALL;
3795 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3796 /* TODO: check validity of object */
3797 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3798 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3799 HeapFree(GetProcessHeap(), 0, (void *)object);
3800 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3803 * Delete Vertex Shader Declaration
3805 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3806 if (NULL == attached_decl) {
3807 return D3DERR_INVALIDCALL;
3809 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3810 /* TODO: check validity of object */
3811 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3812 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3813 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3818 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3819 ICOM_THIS(IDirect3DDevice8Impl,iface);
3821 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3822 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3823 return D3DERR_INVALIDCALL;
3825 if (NULL == pConstantData) {
3826 return D3DERR_INVALIDCALL;
3828 if (ConstantCount > 1) {
3829 FLOAT* f = (FLOAT*)pConstantData;
3831 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3832 for (i = 0; i < ConstantCount; ++i) {
3833 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3837 FLOAT* f = (FLOAT*) pConstantData;
3838 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3840 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3841 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3844 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3845 ICOM_THIS(IDirect3DDevice8Impl,iface);
3847 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3848 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3849 return D3DERR_INVALIDCALL;
3851 if (NULL == pConstantData) {
3852 return D3DERR_INVALIDCALL;
3854 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3857 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3858 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3859 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3861 attached_decl = VERTEX_SHADER_DECL(Handle);
3862 if (NULL == attached_decl) {
3863 return D3DERR_INVALIDCALL;
3865 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3867 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3868 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3869 IDirect3DVertexShaderImpl* object;
3871 object = VERTEX_SHADER(Handle);
3872 if (NULL == object) {
3873 return D3DERR_INVALIDCALL;
3875 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3878 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3879 ICOM_THIS(IDirect3DDevice8Impl,iface);
3880 IDirect3DIndexBuffer8 *oldIdxs;
3882 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3883 oldIdxs = This->StateBlock->pIndexData;
3885 This->UpdateStateBlock->Changed.Indices = TRUE;
3886 This->UpdateStateBlock->Set.Indices = TRUE;
3887 This->UpdateStateBlock->pIndexData = pIndexData;
3888 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3890 /* Handle recording of state blocks */
3891 if (This->isRecordingState) {
3892 TRACE("Recording... not performing anything\n");
3896 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3897 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3900 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3901 ICOM_THIS(IDirect3DDevice8Impl,iface);
3902 FIXME("(%p) : stub\n", This);
3904 *ppIndexData = This->StateBlock->pIndexData;
3905 /* up ref count on ppindexdata */
3906 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3907 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3911 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3912 ICOM_THIS(IDirect3DDevice8Impl,iface);
3913 IDirect3DPixelShaderImpl* object;
3917 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3918 if (NULL == pFunction || NULL == pHandle) {
3919 return D3DERR_INVALIDCALL;
3921 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3922 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3923 return D3DERR_OUTOFVIDEOMEMORY;
3926 /** Create the Pixel Shader */
3927 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3928 if (SUCCEEDED(res)) {
3929 PixelShaders[i] = object;
3930 *pHandle = VS_HIGHESTFIXEDFXF + i;
3933 *pHandle = 0xFFFFFFFF;
3936 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3937 ICOM_THIS(IDirect3DDevice8Impl,iface);
3939 This->UpdateStateBlock->PixelShader = Handle;
3940 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3941 This->UpdateStateBlock->Set.pixelShader = TRUE;
3943 /* Handle recording of state blocks */
3944 if (This->isRecordingState) {
3945 TRACE_(d3d_shader)("Recording... not performing anything\n");
3949 /* FIXME: Quieten when not being used */
3951 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3953 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3958 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3959 ICOM_THIS(IDirect3DDevice8Impl,iface);
3960 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3961 *pHandle = This->StateBlock->PixelShader;
3965 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3966 ICOM_THIS(IDirect3DDevice8Impl,iface);
3967 IDirect3DPixelShaderImpl* object;
3969 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3970 return D3DERR_INVALIDCALL;
3972 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3973 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3974 /* TODO: check validity of object before free */
3975 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3976 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3977 HeapFree(GetProcessHeap(), 0, (void *)object);
3978 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3983 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3984 ICOM_THIS(IDirect3DDevice8Impl,iface);
3986 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3987 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3988 return D3DERR_INVALIDCALL;
3990 if (NULL == pConstantData) {
3991 return D3DERR_INVALIDCALL;
3993 if (ConstantCount > 1) {
3994 FLOAT* f = (FLOAT*)pConstantData;
3996 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3997 for (i = 0; i < ConstantCount; ++i) {
3998 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4002 FLOAT* f = (FLOAT*) pConstantData;
4003 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4005 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4006 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4009 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4010 ICOM_THIS(IDirect3DDevice8Impl,iface);
4012 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4013 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4014 return D3DERR_INVALIDCALL;
4016 if (NULL == pConstantData) {
4017 return D3DERR_INVALIDCALL;
4019 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4022 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4023 IDirect3DPixelShaderImpl* object;
4025 object = PIXEL_SHADER(Handle);
4026 if (NULL == object) {
4027 return D3DERR_INVALIDCALL;
4029 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4031 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4032 ICOM_THIS(IDirect3DDevice8Impl,iface);
4033 FIXME("(%p) : stub\n", This); return D3D_OK;
4035 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4036 ICOM_THIS(IDirect3DDevice8Impl,iface);
4037 FIXME("(%p) : stub\n", This); return D3D_OK;
4039 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4040 ICOM_THIS(IDirect3DDevice8Impl,iface);
4041 FIXME("(%p) : stub\n", This); return D3D_OK;
4044 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4045 IDirect3DVertexBuffer8 *oldSrc;
4046 ICOM_THIS(IDirect3DDevice8Impl,iface);
4048 oldSrc = This->StateBlock->stream_source[StreamNumber];
4049 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4051 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4052 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4053 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4054 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4056 /* Handle recording of state blocks */
4057 if (This->isRecordingState) {
4058 TRACE("Recording... not performing anything\n");
4062 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4063 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4066 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4067 ICOM_THIS(IDirect3DDevice8Impl,iface);
4068 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4069 *pStream = This->StateBlock->stream_source[StreamNumber];
4070 *pStride = This->StateBlock->stream_stride[StreamNumber];
4071 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4076 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4078 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4079 IDirect3DDevice8Impl_QueryInterface,
4080 IDirect3DDevice8Impl_AddRef,
4081 IDirect3DDevice8Impl_Release,
4082 IDirect3DDevice8Impl_TestCooperativeLevel,
4083 IDirect3DDevice8Impl_GetAvailableTextureMem,
4084 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4085 IDirect3DDevice8Impl_GetDirect3D,
4086 IDirect3DDevice8Impl_GetDeviceCaps,
4087 IDirect3DDevice8Impl_GetDisplayMode,
4088 IDirect3DDevice8Impl_GetCreationParameters,
4089 IDirect3DDevice8Impl_SetCursorProperties,
4090 IDirect3DDevice8Impl_SetCursorPosition,
4091 IDirect3DDevice8Impl_ShowCursor,
4092 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4093 IDirect3DDevice8Impl_Reset,
4094 IDirect3DDevice8Impl_Present,
4095 IDirect3DDevice8Impl_GetBackBuffer,
4096 IDirect3DDevice8Impl_GetRasterStatus,
4097 IDirect3DDevice8Impl_SetGammaRamp,
4098 IDirect3DDevice8Impl_GetGammaRamp,
4099 IDirect3DDevice8Impl_CreateTexture,
4100 IDirect3DDevice8Impl_CreateVolumeTexture,
4101 IDirect3DDevice8Impl_CreateCubeTexture,
4102 IDirect3DDevice8Impl_CreateVertexBuffer,
4103 IDirect3DDevice8Impl_CreateIndexBuffer,
4104 IDirect3DDevice8Impl_CreateRenderTarget,
4105 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4106 IDirect3DDevice8Impl_CreateImageSurface,
4107 IDirect3DDevice8Impl_CopyRects,
4108 IDirect3DDevice8Impl_UpdateTexture,
4109 IDirect3DDevice8Impl_GetFrontBuffer,
4110 IDirect3DDevice8Impl_SetRenderTarget,
4111 IDirect3DDevice8Impl_GetRenderTarget,
4112 IDirect3DDevice8Impl_GetDepthStencilSurface,
4113 IDirect3DDevice8Impl_BeginScene,
4114 IDirect3DDevice8Impl_EndScene,
4115 IDirect3DDevice8Impl_Clear,
4116 IDirect3DDevice8Impl_SetTransform,
4117 IDirect3DDevice8Impl_GetTransform,
4118 IDirect3DDevice8Impl_MultiplyTransform,
4119 IDirect3DDevice8Impl_SetViewport,
4120 IDirect3DDevice8Impl_GetViewport,
4121 IDirect3DDevice8Impl_SetMaterial,
4122 IDirect3DDevice8Impl_GetMaterial,
4123 IDirect3DDevice8Impl_SetLight,
4124 IDirect3DDevice8Impl_GetLight,
4125 IDirect3DDevice8Impl_LightEnable,
4126 IDirect3DDevice8Impl_GetLightEnable,
4127 IDirect3DDevice8Impl_SetClipPlane,
4128 IDirect3DDevice8Impl_GetClipPlane,
4129 IDirect3DDevice8Impl_SetRenderState,
4130 IDirect3DDevice8Impl_GetRenderState,
4131 IDirect3DDevice8Impl_BeginStateBlock,
4132 IDirect3DDevice8Impl_EndStateBlock,
4133 IDirect3DDevice8Impl_ApplyStateBlock,
4134 IDirect3DDevice8Impl_CaptureStateBlock,
4135 IDirect3DDevice8Impl_DeleteStateBlock,
4136 IDirect3DDevice8Impl_CreateStateBlock,
4137 IDirect3DDevice8Impl_SetClipStatus,
4138 IDirect3DDevice8Impl_GetClipStatus,
4139 IDirect3DDevice8Impl_GetTexture,
4140 IDirect3DDevice8Impl_SetTexture,
4141 IDirect3DDevice8Impl_GetTextureStageState,
4142 IDirect3DDevice8Impl_SetTextureStageState,
4143 IDirect3DDevice8Impl_ValidateDevice,
4144 IDirect3DDevice8Impl_GetInfo,
4145 IDirect3DDevice8Impl_SetPaletteEntries,
4146 IDirect3DDevice8Impl_GetPaletteEntries,
4147 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4148 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4149 IDirect3DDevice8Impl_DrawPrimitive,
4150 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4151 IDirect3DDevice8Impl_DrawPrimitiveUP,
4152 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4153 IDirect3DDevice8Impl_ProcessVertices,
4154 IDirect3DDevice8Impl_CreateVertexShader,
4155 IDirect3DDevice8Impl_SetVertexShader,
4156 IDirect3DDevice8Impl_GetVertexShader,
4157 IDirect3DDevice8Impl_DeleteVertexShader,
4158 IDirect3DDevice8Impl_SetVertexShaderConstant,
4159 IDirect3DDevice8Impl_GetVertexShaderConstant,
4160 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4161 IDirect3DDevice8Impl_GetVertexShaderFunction,
4162 IDirect3DDevice8Impl_SetStreamSource,
4163 IDirect3DDevice8Impl_GetStreamSource,
4164 IDirect3DDevice8Impl_SetIndices,
4165 IDirect3DDevice8Impl_GetIndices,
4166 IDirect3DDevice8Impl_CreatePixelShader,
4167 IDirect3DDevice8Impl_SetPixelShader,
4168 IDirect3DDevice8Impl_GetPixelShader,
4169 IDirect3DDevice8Impl_DeletePixelShader,
4170 IDirect3DDevice8Impl_SetPixelShaderConstant,
4171 IDirect3DDevice8Impl_GetPixelShaderConstant,
4172 IDirect3DDevice8Impl_GetPixelShaderFunction,
4173 IDirect3DDevice8Impl_DrawRectPatch,
4174 IDirect3DDevice8Impl_DrawTriPatch,
4175 IDirect3DDevice8Impl_DeletePatch
4178 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4180 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4181 ICOM_THIS(IDirect3DDevice8Impl,iface);
4186 if (This->glCtx != This->render_ctx) {
4187 glXDestroyContext(This->display, This->render_ctx);
4188 This->render_ctx = This->glCtx;
4191 if (This->win != This->drawable) {
4192 glXDestroyPbuffer(This->display, This->drawable);
4193 This->drawable = This->win;
4202 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4203 IDirect3DSurface8* RenderSurface,
4204 IDirect3DSurface8* StencilSurface) {
4206 HRESULT ret = D3DERR_INVALIDCALL;
4208 * Currently only active for GLX >= 1.3
4209 * for others versions we'll have to use GLXPixmaps
4211 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4212 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4213 * so only check OpenGL version
4215 #if defined(GL_VERSION_1_3)
4216 GLXFBConfig* cfgs = NULL;
4220 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4221 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4222 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4223 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4224 IDirect3DSurface8Impl* tmp;
4226 ICOM_THIS(IDirect3DDevice8Impl,iface);
4228 #define PUSH1(att) attribs[nAttribs++] = (att);
4229 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4231 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4232 PUSH2(GLX_X_RENDERABLE, TRUE);
4233 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4235 switch (BackBufferFormat) {
4238 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4239 PUSH2(GLX_BUFFER_SIZE, 8);
4240 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4244 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4245 PUSH2(GLX_RED_SIZE, 3);
4246 PUSH2(GLX_GREEN_SIZE, 3);
4247 PUSH2(GLX_BLUE_SIZE, 2);
4250 case D3DFMT_A1R5G5B5:
4251 PUSH2(GLX_ALPHA_SIZE, 1);
4252 case D3DFMT_X1R5G5B5:
4253 PUSH2(GLX_RED_SIZE, 5);
4254 PUSH2(GLX_GREEN_SIZE, 5);
4255 PUSH2(GLX_BLUE_SIZE, 5);
4259 PUSH2(GLX_RED_SIZE, 5);
4260 PUSH2(GLX_GREEN_SIZE, 6);
4261 PUSH2(GLX_BLUE_SIZE, 5);
4264 case D3DFMT_A4R4G4B4:
4265 PUSH2(GLX_ALPHA_SIZE, 4);
4266 case D3DFMT_X4R4G4B4:
4267 PUSH2(GLX_RED_SIZE, 4);
4268 PUSH2(GLX_GREEN_SIZE, 4);
4269 PUSH2(GLX_BLUE_SIZE, 4);
4272 case D3DFMT_A8R8G8B8:
4273 PUSH2(GLX_ALPHA_SIZE, 8);
4275 case D3DFMT_X8R8G8B8:
4276 PUSH2(GLX_RED_SIZE, 8);
4277 PUSH2(GLX_GREEN_SIZE, 8);
4278 PUSH2(GLX_BLUE_SIZE, 8);
4285 switch (StencilBufferFormat) {
4286 case D3DFMT_D16_LOCKABLE:
4288 PUSH2(GLX_DEPTH_SIZE, 16);
4292 PUSH2(GLX_DEPTH_SIZE, 15);
4296 PUSH2(GLX_DEPTH_SIZE, 24);
4299 case D3DFMT_D24X4S4:
4300 PUSH2(GLX_DEPTH_SIZE, 24);
4301 PUSH2(GLX_STENCIL_SIZE, 4);
4305 PUSH2(GLX_DEPTH_SIZE, 24);
4306 PUSH2(GLX_STENCIL_SIZE, 8);
4310 PUSH2(GLX_DEPTH_SIZE, 32);
4321 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4325 for (i = 0; i < nCfgs; ++i) {
4326 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4330 if (NULL != This->renderTarget) {
4333 vcheckGLcall("glFlush");
4336 /** very very usefull debug code */
4337 glXSwapBuffers(This->display, This->drawable);
4338 printf("Hit Enter to get next frame ...\n");
4342 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4343 vcheckGLcall("glIntegerv");
4344 glReadBuffer(GL_BACK);
4345 vcheckGLcall("glReadBuffer");
4348 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4350 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4353 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4355 This->renderTarget->myDesc.Height - j - 1,
4356 This->renderTarget->myDesc.Width,
4358 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4359 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4360 This->renderTarget->allocatedMemory + j * pitch);
4361 vcheckGLcall("glReadPixels");
4364 glReadBuffer(prev_read);
4365 vcheckGLcall("glReadBuffer");
4368 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4369 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4371 PUSH2(GLX_PBUFFER_WIDTH, Width);
4372 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4374 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4376 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4377 if (NULL == This->render_ctx) {
4378 ERR("cannot create glxContext\n");
4382 glXSwapBuffers(This->display, This->drawable);
4383 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4384 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4386 checkGLcall("glXMakeContextCurrent");
4389 tmp = This->renderTarget;
4390 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4391 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4392 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4394 tmp = This->stencilBufferTarget;
4395 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4396 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4397 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4402 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));