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 doesn't 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 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
489 glXSwapBuffers(This->display, This->drawable);
490 /* Don't call checkGLcall, as glGetError is not applicable here */
491 TRACE("glXSwapBuffers called, Starting new frame\n");
496 static long prev_time, frames;
498 DWORD time = GetTickCount();
500 /* every 1.5 seconds */
501 if (time - prev_time > 1500) {
502 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
508 #if defined(FRAME_DEBUGGING)
510 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
513 FIXME("Enabling D3D Trace\n");
514 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
515 #if defined(SHOW_FRAME_MAKEUP)
516 FIXME("Singe Frame snapshots Starting\n");
517 isDumpingFrames = TRUE;
518 glClear(GL_COLOR_BUFFER_BIT);
521 #if defined(SINGLE_FRAME_DEBUGGING)
523 #if defined(SHOW_FRAME_MAKEUP)
524 FIXME("Singe Frame snapshots Finishing\n");
525 isDumpingFrames = FALSE;
527 FIXME("Singe Frame trace complete\n");
528 DeleteFileA("C:\\D3DTRACE");
529 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
535 #if defined(SHOW_FRAME_MAKEUP)
536 FIXME("Singe Frame snapshots Finishing\n");
537 isDumpingFrames = FALSE;
539 FIXME("Disabling D3D Trace\n");
540 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
547 /* Although this is not strictly required, a simple demo showed this does occur
548 on (at least non-debug) d3d */
549 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
550 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
555 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
556 ICOM_THIS(IDirect3DDevice8Impl,iface);
557 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
558 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
560 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
561 FIXME("Only one backBuffer currently supported\n");
562 return D3DERR_INVALIDCALL;
565 /* Note inc ref on returned surface */
566 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
570 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
571 ICOM_THIS(IDirect3DDevice8Impl,iface);
572 FIXME("(%p) : stub\n", This);
575 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
577 ICOM_THIS(IDirect3DDevice8Impl,iface);
579 FIXME("(%p) : pRamp@%p\n", This, pRamp);
580 hDC = GetDC(This->win_handle);
581 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
582 ReleaseDC(This->win_handle, hDC);
585 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
587 ICOM_THIS(IDirect3DDevice8Impl,iface);
589 FIXME("(%p) : pRamp@%p\n", This, pRamp);
590 hDC = GetDC(This->win_handle);
591 GetDeviceGammaRamp(hDC, pRamp);
592 ReleaseDC(This->win_handle, hDC);
595 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
596 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
597 IDirect3DTexture8Impl *object;
602 ICOM_THIS(IDirect3DDevice8Impl,iface);
604 /* Allocate the storage for the device */
605 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);
606 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
607 object->lpVtbl = &Direct3DTexture8_Vtbl;
608 object->Device = This;
609 object->ResourceType = D3DRTYPE_TEXTURE;
611 object->width = Width;
612 object->height = Height;
613 object->levels = Levels;
614 object->usage = Usage;
615 object->format = Format;
617 /* Calculate levels for mip mapping */
622 while (tmpW > 1 && tmpH > 1) {
623 tmpW = max(1, tmpW / 2);
624 tmpH = max(1, tmpH / 2);
627 TRACE("Calculated levels = %d\n", object->levels);
630 /* Generate all the surfaces */
633 for (i = 0; i < object->levels; i++)
635 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
636 object->surfaces[i]->Container = (IUnknown*) object;
637 object->surfaces[i]->myDesc.Usage = Usage;
638 object->surfaces[i]->myDesc.Pool = Pool;
640 * As written in msdn in IDirect3DTexture8::LockRect
641 * Textures created in D3DPOOL_DEFAULT are not lockable.
643 if (D3DPOOL_DEFAULT == Pool) {
644 object->surfaces[i]->lockable = FALSE;
647 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
648 tmpW = max(1, tmpW / 2);
649 tmpH = max(1, tmpH / 2);
652 *ppTexture = (LPDIRECT3DTEXTURE8) object;
653 TRACE("(%p) : Created texture %p\n", This, object);
656 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
657 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
658 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
660 IDirect3DVolumeTexture8Impl *object;
666 ICOM_THIS(IDirect3DDevice8Impl,iface);
668 /* Allocate the storage for it */
669 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));
670 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
671 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
672 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
673 object->Device = This;
676 object->width = Width;
677 object->height = Height;
678 object->depth = Depth;
679 object->levels = Levels;
680 object->usage = Usage;
681 object->format = Format;
683 /* Calculate levels for mip mapping */
689 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
690 tmpW = max(1, tmpW / 2);
691 tmpH = max(1, tmpH / 2);
692 tmpD = max(1, tmpD / 2);
695 TRACE("Calculated levels = %d\n", object->levels);
698 /* Generate all the surfaces */
703 for (i = 0; i < object->levels; i++)
705 IDirect3DVolume8Impl* volume;
707 /* Create the volume - No entry point for this seperately?? */
708 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
709 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
711 volume->lpVtbl = &Direct3DVolume8_Vtbl;
712 volume->Device = This;
713 volume->ResourceType = D3DRTYPE_VOLUME;
714 volume->Container = (IUnknown*) object;
717 volume->myDesc.Width = Width;
718 volume->myDesc.Height = Height;
719 volume->myDesc.Depth = Depth;
720 volume->myDesc.Format = Format;
721 volume->myDesc.Type = D3DRTYPE_VOLUME;
722 volume->myDesc.Pool = Pool;
723 volume->myDesc.Usage = Usage;
724 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
725 /* Note: Volume textures cannot be dxtn, hence no need to check here */
726 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
727 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
729 volume->lockable = TRUE;
730 volume->locked = FALSE;
731 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
732 volume->Dirty = FALSE;
733 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
735 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
736 This, Width, Height, Depth, Format, debug_d3dformat(Format),
737 volume, volume->allocatedMemory, volume->myDesc.Size);
739 tmpW = max(1, tmpW / 2);
740 tmpH = max(1, tmpH / 2);
741 tmpD = max(1, tmpD / 2);
744 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
745 TRACE("(%p) : Created volume texture %p\n", This, object);
748 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
749 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
751 IDirect3DCubeTexture8Impl *object;
752 ICOM_THIS(IDirect3DDevice8Impl,iface);
756 /* Allocate the storage for it */
757 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));
758 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
759 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
761 object->Device = This;
762 object->ResourceType = D3DRTYPE_CUBETEXTURE;
764 object->edgeLength = EdgeLength;
765 object->levels = Levels;
766 object->usage = Usage;
767 object->format = Format;
769 /* Calculate levels for mip mapping */
774 tmpW = max(1, tmpW / 2);
777 TRACE("Calculated levels = %d\n", object->levels);
780 /* Generate all the surfaces */
782 for (i = 0; i < object->levels; i++) {
783 /* Create the 6 faces */
784 for (j = 0; j < 6; j++) {
785 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
786 object->surfaces[j][i]->Container = (IUnknown*) object;
787 object->surfaces[j][i]->myDesc.Usage = Usage;
788 object->surfaces[j][i]->myDesc.Pool = Pool;
790 * As written in msdn in IDirect3DCubeTexture8::LockRect
791 * Textures created in D3DPOOL_DEFAULT are not lockable.
793 if (D3DPOOL_DEFAULT == Pool) {
794 object->surfaces[j][i]->lockable = FALSE;
797 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
799 tmpW = max(1, tmpW / 2);
802 TRACE("(%p) : Iface@%p\n", This, object);
803 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
806 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
807 IDirect3DVertexBuffer8Impl *object;
809 ICOM_THIS(IDirect3DDevice8Impl,iface);
811 /* Allocate the storage for the device */
812 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
813 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
814 object->Device = This;
815 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
817 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
818 object->currentDesc.Usage = Usage;
819 object->currentDesc.Pool = Pool;
820 object->currentDesc.FVF = FVF;
821 object->currentDesc.Size = Size;
823 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
825 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
829 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
830 IDirect3DIndexBuffer8Impl *object;
832 ICOM_THIS(IDirect3DDevice8Impl,iface);
833 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
835 /* Allocate the storage for the device */
836 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
837 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
838 object->Device = This;
840 object->ResourceType = D3DRTYPE_INDEXBUFFER;
842 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
843 object->currentDesc.Usage = Usage;
844 object->currentDesc.Pool = Pool;
845 object->currentDesc.Format = Format;
846 object->currentDesc.Size = Length;
848 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
850 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
852 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
856 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
857 IDirect3DSurface8Impl *object;
858 ICOM_THIS(IDirect3DDevice8Impl,iface);
860 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
861 if (NULL == object) {
863 return D3DERR_OUTOFVIDEOMEMORY;
865 *ppSurface = (LPDIRECT3DSURFACE8) object;
866 object->lpVtbl = &Direct3DSurface8_Vtbl;
867 object->Device = This;
868 object->ResourceType = D3DRTYPE_SURFACE;
869 object->Container = (IUnknown*) This;
872 object->myDesc.Width = Width;
873 object->myDesc.Height = Height;
874 object->myDesc.Format = Format;
875 object->myDesc.Type = D3DRTYPE_SURFACE;
876 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
877 object->myDesc.Pool = D3DPOOL_DEFAULT;
878 object->myDesc.MultiSampleType = MultiSample;
879 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
880 if (Format == D3DFMT_DXT1) {
881 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
883 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
885 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
886 object->lockable = Lockable;
887 object->locked = FALSE;
888 memset(&object->lockedRect, 0, sizeof(RECT));
889 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
891 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);
894 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
895 IDirect3DSurface8Impl *object;
897 ICOM_THIS(IDirect3DDevice8Impl,iface);
899 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
900 if (NULL == object) {
902 return D3DERR_OUTOFVIDEOMEMORY;
904 *ppSurface = (LPDIRECT3DSURFACE8) object;
905 object->lpVtbl = &Direct3DSurface8_Vtbl;
906 object->Device = This;
907 object->ResourceType = D3DRTYPE_SURFACE;
908 object->Container = (IUnknown*) This;
911 object->myDesc.Width = Width;
912 object->myDesc.Height = Height;
913 object->myDesc.Format = Format;
914 object->myDesc.Type = D3DRTYPE_SURFACE;
915 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
916 object->myDesc.Pool = D3DPOOL_DEFAULT;
917 object->myDesc.MultiSampleType = MultiSample;
918 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
919 if (Format == D3DFMT_DXT1) {
920 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
922 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
924 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
925 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
926 object->locked = FALSE;
927 memset(&object->lockedRect, 0, sizeof(RECT));
928 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
930 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);
933 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
934 IDirect3DSurface8Impl *object;
936 ICOM_THIS(IDirect3DDevice8Impl,iface);
938 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
939 *ppSurface = (LPDIRECT3DSURFACE8) object;
940 object->lpVtbl = &Direct3DSurface8_Vtbl;
941 object->Device = This;
942 object->ResourceType = D3DRTYPE_SURFACE;
943 object->Container = (IUnknown*) This;
946 object->myDesc.Width = Width;
947 object->myDesc.Height = Height;
948 object->myDesc.Format = Format;
949 object->myDesc.Type = D3DRTYPE_SURFACE;
950 object->myDesc.Usage = 0;
951 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
952 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
953 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
954 it is based around 4x4 pixel blocks it requires padding, so allocate enough
956 if (Format == D3DFMT_DXT1) {
957 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
958 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
959 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
960 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
962 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
964 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
965 object->lockable = TRUE;
966 object->locked = FALSE;
967 memset(&object->lockedRect, 0, sizeof(RECT));
968 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
970 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);
973 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
974 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
975 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
978 IDirect3DBaseTexture8* texture = NULL;
981 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
982 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
984 ICOM_THIS(IDirect3DDevice8Impl,iface);
985 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
986 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
988 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
989 a sample and doesn't seem to break anything as far as I can tell */
990 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
991 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
992 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
993 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
994 rc = D3DERR_INVALIDCALL;
996 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
997 TRACE("Converting dest to same format as source, since dest was unknown\n");
998 dst->myDesc.Format = src->myDesc.Format;
1000 /* Convert container as well */
1001 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1002 if (SUCCEEDED(rc) && NULL != texture) {
1003 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1004 /** Releasing texture after GetContainer */
1005 IDirect3DBaseTexture8_Release(texture);
1010 /* Quick if complete copy ... */
1011 if (SUCCEEDED(rc)) {
1012 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1014 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1016 D3DLOCKED_RECT lrSrc;
1017 D3DLOCKED_RECT lrDst;
1018 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1019 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1020 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1022 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1024 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1025 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1026 TRACE("Unlocked src and dst\n");
1030 FIXME("Wanted to copy all surfaces but size not compatible\n");
1031 rc = D3DERR_INVALIDCALL;
1037 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1039 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1042 /* Copy rect by rect */
1043 for (i = 0; i < cRects; i++) {
1044 CONST RECT* r = &pSourceRectsArray[i];
1045 CONST POINT* p = &pDestPointsArray[i];
1048 D3DLOCKED_RECT lrSrc;
1049 D3DLOCKED_RECT lrDst;
1052 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1053 if (src->myDesc.Format == D3DFMT_DXT1) {
1054 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1056 copyperline = ((r->right - r->left) * bytesPerPixel);
1058 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1059 dest_rect.left = p->x;
1060 dest_rect.top = p->y;
1061 dest_rect.right = p->x + (r->right - r->left);
1062 dest_rect.bottom= p->y + (r->bottom - r->top);
1063 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1064 TRACE("Locked src and dst\n");
1066 /* Find where to start */
1067 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1068 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1070 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1071 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1072 TRACE("Unlocked src and dst\n");
1075 FIXME("Wanted to copy partial surfaces not implemented\n");
1076 rc = D3DERR_INVALIDCALL;
1083 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1084 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1085 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1086 D3DRESOURCETYPE srcType;
1087 D3DRESOURCETYPE dstType;
1089 ICOM_THIS(IDirect3DDevice8Impl,iface);
1090 TRACE("(%p) : first try\n", This);
1092 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1093 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1095 if (srcType != dstType) {
1096 return D3DERR_INVALIDCALL;
1098 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1099 return D3DERR_INVALIDCALL;
1101 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1102 return D3DERR_INVALIDCALL;
1104 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1105 /** Only copy Dirty textures */
1106 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1107 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1108 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1111 for (i = skipLevels; i < srcLevelCnt; ++i) {
1115 case D3DRTYPE_TEXTURE:
1117 IDirect3DSurface8* srcSur = NULL;
1118 IDirect3DSurface8* dstSur = NULL;
1119 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1120 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1122 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1123 about dst with less levels than the source?) */
1124 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1126 IDirect3DSurface8Impl_Release(srcSur);
1127 IDirect3DSurface8Impl_Release(dstSur);
1130 case D3DRTYPE_VOLUMETEXTURE:
1132 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1135 case D3DRTYPE_CUBETEXTURE:
1137 IDirect3DSurface8* srcSur = NULL;
1138 IDirect3DSurface8* dstSur = NULL;
1139 for (j = 0; j < 5; ++j) {
1140 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1141 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1142 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1143 IDirect3DSurface8Impl_Release(srcSur);
1144 IDirect3DSurface8Impl_Release(dstSur);
1152 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1157 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1159 D3DLOCKED_RECT lockedRect;
1164 ICOM_THIS(IDirect3DDevice8Impl,iface);
1166 FIXME("(%p) : see if behavior correct\n", This);
1168 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1169 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1170 return D3DERR_INVALIDCALL;
1173 wantedRect.left = 0;
1175 wantedRect.right = This->PresentParms.BackBufferWidth;
1176 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1178 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1180 ERR("(%p) : cannot lock surface\n", This);
1181 return D3DERR_INVALIDCALL;
1187 vcheckGLcall("glFlush");
1188 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1189 vcheckGLcall("glIntegerv");
1190 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1191 vcheckGLcall("glIntegerv");
1193 glReadBuffer(GL_FRONT);
1194 vcheckGLcall("glReadBuffer");
1195 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1196 vcheckGLcall("glPixelStorei");
1200 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1201 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1202 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1203 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1204 vcheckGLcall("glReadPixels");
1207 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1208 vcheckGLcall("glPixelStorei");
1209 glReadBuffer(prev_read);
1210 vcheckGLcall("glReadBuffer");
1214 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1217 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1220 ICOM_THIS(IDirect3DDevice8Impl,iface);
1222 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1223 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1227 IDirect3DDevice8Impl_CleanRender(iface);
1229 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1230 IDirect3DSurface8Impl* tmp;
1232 TRACE("retoring SetRenderTarget defaults\n");
1234 tmp = This->renderTarget;
1235 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1236 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1237 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1239 tmp = This->stencilBufferTarget;
1240 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1241 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1242 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1247 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1249 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1254 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1255 ICOM_THIS(IDirect3DDevice8Impl,iface);
1257 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1259 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1260 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1265 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1266 ICOM_THIS(IDirect3DDevice8Impl,iface);
1268 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1270 /* Note inc ref on returned surface */
1271 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1272 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1277 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1278 ICOM_THIS(IDirect3DDevice8Impl,iface);
1279 TRACE("(%p) : stub\n", This);
1282 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1283 IDirect3DBaseTexture8* cont = NULL;
1285 ICOM_THIS(IDirect3DDevice8Impl,iface);
1286 TRACE("(%p)\n", This);
1291 checkGLcall("glFlush");
1293 /* Useful for debugging sometimes!
1294 printf("Hit Enter ...\n");
1297 if (This->frontBuffer != This->renderTarget) {
1300 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1301 vcheckGLcall("glIntegerv");
1302 glReadBuffer(GL_BACK);
1303 vcheckGLcall("glReadBuffer");
1306 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1308 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1311 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1313 This->renderTarget->myDesc.Height - j - 1,
1314 This->renderTarget->myDesc.Width,
1316 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1317 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1318 This->renderTarget->allocatedMemory + j * pitch);
1319 vcheckGLcall("glReadPixels");
1322 glReadBuffer(prev_read);
1323 vcheckGLcall("glReadBuffer");
1326 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1327 if (SUCCEEDED(hr) && NULL != cont) {
1328 /** always dirtify for now. we must find a better way to see that surface have been modified */
1329 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1330 IDirect3DBaseTexture8_PreLoad(cont);
1331 IDirect3DBaseTexture8Impl_Release(cont);
1339 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1340 ICOM_THIS(IDirect3DDevice8Impl,iface);
1342 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1343 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1344 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1345 GLbitfield glMask = 0;
1346 GLboolean old_ztest;
1347 GLfloat old_z_clear_value;
1348 GLint old_stencil_clear_value;
1349 GLfloat old_color_clear_value[4];
1351 CONST D3DRECT* curRect;
1353 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1354 Count, pRects, Flags, Z, Stencil);
1357 glEnable(GL_SCISSOR_TEST);
1358 checkGLcall("glEnable GL_SCISSOR_TEST");
1359 if (Count > 0 && pRects) {
1365 /* Only set the values up once, as they are not changing */
1366 if (Flags & D3DCLEAR_STENCIL) {
1367 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1368 glClearStencil(Stencil);
1369 checkGLcall("glClearStencil");
1370 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1371 glStencilMask(0xFFFFFFFF);
1374 if (Flags & D3DCLEAR_ZBUFFER) {
1375 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1376 glDepthMask(GL_TRUE);
1377 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1379 checkGLcall("glClearDepth");
1380 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1383 if (Flags & D3DCLEAR_TARGET) {
1384 TRACE("Clearing screen with glClear to color %lx\n", Color);
1385 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1386 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1387 ((Color >> 8) & 0xFF) / 255.0f,
1388 ((Color >> 0) & 0xFF) / 255.0f,
1389 ((Color >> 24) & 0xFF) / 255.0f);
1390 checkGLcall("glClearColor");
1392 /* Clear ALL colors! */
1393 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1394 glMask = glMask | GL_COLOR_BUFFER_BIT;
1397 /* Now process each rect in turn */
1398 for (i = 0; i < Count || i == 0; i++) {
1401 /* Note gl uses lower left, width/height */
1402 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1403 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1404 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1405 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1406 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1407 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1408 checkGLcall("glScissor");
1410 glScissor(This->StateBlock->viewport.X,
1411 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1412 This->StateBlock->viewport.Width,
1413 This->StateBlock->viewport.Height);
1414 checkGLcall("glScissor");
1417 /* Clear the selected rectangle (or full screen) */
1419 checkGLcall("glClear");
1421 /* Step to the next rectangle */
1422 if (curRect) curRect = curRect + sizeof(D3DRECT);
1425 /* Restore the old values (why..?) */
1426 if (Flags & D3DCLEAR_STENCIL) {
1427 glClearStencil(old_stencil_clear_value);
1428 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1430 if (Flags & D3DCLEAR_ZBUFFER) {
1431 glDepthMask(old_ztest);
1432 glClearDepth(old_z_clear_value);
1434 if (Flags & D3DCLEAR_TARGET) {
1435 glClearColor(old_color_clear_value[0],
1436 old_color_clear_value[1],
1437 old_color_clear_value[2],
1438 old_color_clear_value[3]);
1439 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1440 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1441 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1442 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1445 glDisable(GL_SCISSOR_TEST);
1446 checkGLcall("glDisable");
1451 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1452 ICOM_THIS(IDirect3DDevice8Impl,iface);
1455 /* Most of this routine, comments included copied from ddraw tree initially: */
1456 TRACE("(%p) : State=%d\n", This, d3dts);
1458 /* Handle recording of state blocks */
1459 if (This->isRecordingState) {
1460 TRACE("Recording... not performing anything\n");
1461 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1462 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1463 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1468 * if the new matrix is the same as the current one,
1469 * we cut off any further processing. this seems to be a reasonable
1470 * optimization because as was noticed, some apps (warcraft3 for example)
1471 * tend towards setting the same matrix repeatedly for some dumb reason.
1473 * From here on we assume that the new matrix is different, wherever it matters
1476 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1477 TRACE("The app is setting the same matrix over again\n");
1480 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1484 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1485 where ViewMat = Camera space, WorldMat = world space.
1487 In OpenGL, camera and world space is combined into GL_MODELVIEW
1488 matrix. The Projection matrix stay projection matrix.
1491 /* Capture the times we can just ignore the change */
1492 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1493 This->modelview_valid = FALSE;
1496 } else if (d3dts == D3DTS_PROJECTION) {
1497 This->proj_valid = FALSE;
1500 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1501 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1502 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1506 /* Chances are we really are going to have to change a matrix */
1509 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1510 if (d3dts < GL_LIMITS(textures)) {
1511 int tex = d3dts - D3DTS_TEXTURE0;
1512 #if defined(GL_VERSION_1_3)
1513 glActiveTexture(GL_TEXTURE0 + tex);
1515 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1517 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1520 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1522 PLIGHTINFOEL *lightChain = NULL;
1523 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1524 This->modelview_valid = FALSE;
1525 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1526 glMatrixMode(GL_MODELVIEW);
1527 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1529 glLoadMatrixf((float *)lpmatrix);
1530 checkGLcall("glLoadMatrixf(...)");
1532 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1533 * NOTE: We have to reset the positions even if the light/plane is not currently
1534 * enabled, since the call to enable it will not reset the position.
1535 * NOTE2: Apparently texture transforms do NOT need reapplying
1539 lightChain = This->StateBlock->lights;
1540 while (lightChain && lightChain->glIndex != -1) {
1541 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1542 checkGLcall("glLightfv posn");
1543 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1544 checkGLcall("glLightfv dirn");
1545 lightChain = lightChain->next;
1547 /* Reset Clipping Planes if clipping is enabled */
1548 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1549 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1550 checkGLcall("glClipPlane");
1554 } else { /* What was requested!?? */
1555 WARN("invalid matrix specified: %i\n", d3dts);
1559 /* Release lock, all done */
1564 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1565 ICOM_THIS(IDirect3DDevice8Impl,iface);
1566 TRACE("(%p) : for State %d\n", This, State);
1567 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1571 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1572 D3DMATRIX *mat = NULL;
1575 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1576 but works regardless of recording being on.
1577 If this is found to be wrong, change to StateBlock. */
1578 ICOM_THIS(IDirect3DDevice8Impl,iface);
1579 TRACE("(%p) : For state %u\n", This, State);
1581 if (State < HIGHEST_TRANSFORMSTATE)
1583 mat = &This->UpdateStateBlock->transforms[State];
1585 FIXME("Unhandled transform state!!\n");
1588 /* Copied from ddraw code: */
1589 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);
1590 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);
1591 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);
1592 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);
1594 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);
1595 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);
1596 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);
1597 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);
1599 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);
1600 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);
1601 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);
1602 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);
1604 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);
1605 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);
1606 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);
1607 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);
1609 /* Apply change via set transform - will reapply to eg. lights this way */
1610 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1613 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1614 ICOM_THIS(IDirect3DDevice8Impl,iface);
1616 TRACE("(%p)\n", This);
1617 This->UpdateStateBlock->Changed.viewport = TRUE;
1618 This->UpdateStateBlock->Set.viewport = TRUE;
1619 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1621 /* Handle recording of state blocks */
1622 if (This->isRecordingState) {
1623 TRACE("Recording... not performing anything\n");
1629 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1630 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1632 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1633 checkGLcall("glDepthRange");
1634 /* Note: GL requires lower left, DirectX supplies upper left */
1635 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1636 pViewport->Width, pViewport->Height);
1637 checkGLcall("glViewport");
1644 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1645 ICOM_THIS(IDirect3DDevice8Impl,iface);
1646 TRACE("(%p)\n", This);
1647 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1651 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1652 ICOM_THIS(IDirect3DDevice8Impl,iface);
1654 This->UpdateStateBlock->Changed.material = TRUE;
1655 This->UpdateStateBlock->Set.material = TRUE;
1656 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1658 /* Handle recording of state blocks */
1659 if (This->isRecordingState) {
1660 TRACE("Recording... not performing anything\n");
1665 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1666 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1667 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1668 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1669 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1671 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1672 checkGLcall("glMaterialfv");
1673 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1674 checkGLcall("glMaterialfv");
1676 /* Only change material color if specular is enabled, otherwise it is set to black */
1677 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1678 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1679 checkGLcall("glMaterialfv");
1681 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1682 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1683 checkGLcall("glMaterialfv");
1685 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1686 checkGLcall("glMaterialfv");
1687 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1688 checkGLcall("glMaterialf");
1693 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1694 ICOM_THIS(IDirect3DDevice8Impl,iface);
1695 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1696 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1697 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1698 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1699 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1700 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1704 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1705 you can reference any indexes you want as long as that number max are enabled are any
1706 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1707 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1708 but when recording, just build a chain pretty much of commands to be replayed. */
1710 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1712 PLIGHTINFOEL *object, *temp;
1714 ICOM_THIS(IDirect3DDevice8Impl,iface);
1715 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1717 /* If recording state block, just add to end of lights chain */
1718 if (This->isRecordingState) {
1719 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1720 if (NULL == object) {
1721 return D3DERR_OUTOFVIDEOMEMORY;
1723 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1724 object->OriginalIndex = Index;
1725 object->glIndex = -1;
1726 object->changed = TRUE;
1728 /* Add to the END of the chain of lights changes to be replayed */
1729 if (This->UpdateStateBlock->lights == NULL) {
1730 This->UpdateStateBlock->lights = object;
1732 temp = This->UpdateStateBlock->lights;
1733 while (temp->next != NULL) temp=temp->next;
1734 temp->next = object;
1736 TRACE("Recording... not performing anything more\n");
1740 /* Ok, not recording any longer so do real work */
1741 object = This->StateBlock->lights;
1742 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1744 /* If we didn't find it in the list of lights, time to add it */
1745 if (object == NULL) {
1746 PLIGHTINFOEL *insertAt,*prevPos;
1748 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1749 if (NULL == object) {
1750 return D3DERR_OUTOFVIDEOMEMORY;
1752 object->OriginalIndex = Index;
1753 object->glIndex = -1;
1755 /* Add it to the front of list with the idea that lights will be changed as needed
1756 BUT after any lights currently assigned GL indexes */
1757 insertAt = This->StateBlock->lights;
1759 while (insertAt != NULL && insertAt->glIndex != -1) {
1761 insertAt = insertAt->next;
1764 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1765 This->StateBlock->lights = object;
1766 } else if (insertAt == NULL) { /* End of list */
1767 prevPos->next = object;
1768 object->prev = prevPos;
1769 } else { /* Middle of chain */
1770 if (prevPos == NULL) {
1771 This->StateBlock->lights = object;
1773 prevPos->next = object;
1775 object->prev = prevPos;
1776 object->next = insertAt;
1777 insertAt->prev = object;
1781 /* Initialze the object */
1782 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,
1783 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1784 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1785 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1786 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1787 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1788 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1790 /* Save away the information */
1791 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1793 switch (pLight->Type) {
1794 case D3DLIGHT_POINT:
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.0f;
1800 object->cutoff = 180.0f;
1806 object->lightPosn[0] = pLight->Position.x;
1807 object->lightPosn[1] = pLight->Position.y;
1808 object->lightPosn[2] = pLight->Position.z;
1809 object->lightPosn[3] = 1.0;
1812 object->lightDirn[0] = pLight->Direction.x;
1813 object->lightDirn[1] = pLight->Direction.y;
1814 object->lightDirn[2] = pLight->Direction.z;
1815 object->lightDirn[3] = 1.0;
1818 * opengl-ish and d3d-ish spot lights use too different models for the
1819 * light "intensity" as a function of the angle towards the main light direction,
1820 * so we only can approximate very roughly.
1821 * however spot lights are rather rarely used in games (if ever used at all).
1822 * furthermore if still used, probably nobody pays attention to such details.
1824 if (pLight->Falloff == 0) {
1827 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1829 if (rho < 0.0001) rho = 0.0001f;
1830 object->exponent = -0.3/log(cos(rho/2));
1831 object->cutoff = pLight->Phi*90/M_PI;
1836 case D3DLIGHT_DIRECTIONAL:
1838 object->lightPosn[0] = -pLight->Direction.x;
1839 object->lightPosn[1] = -pLight->Direction.y;
1840 object->lightPosn[2] = -pLight->Direction.z;
1841 object->lightPosn[3] = 0.0;
1842 object->exponent = 0.0f;
1843 object->cutoff = 180.0f;
1847 FIXME("Unrecognized light type %d\n", pLight->Type);
1850 /* Update the live definitions if the light is currently assigned a glIndex */
1851 if (object->glIndex != -1) {
1852 setup_light(iface, object->glIndex, object);
1856 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1857 PLIGHTINFOEL *lightInfo = NULL;
1858 ICOM_THIS(IDirect3DDevice8Impl,iface);
1859 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1861 /* Locate the light in the live lights */
1862 lightInfo = This->StateBlock->lights;
1863 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1865 if (lightInfo == NULL) {
1866 TRACE("Light information requested but light not defined\n");
1867 return D3DERR_INVALIDCALL;
1870 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1873 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1874 PLIGHTINFOEL *lightInfo = NULL;
1875 ICOM_THIS(IDirect3DDevice8Impl,iface);
1876 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1878 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1879 if (This->isRecordingState) {
1880 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1881 if (NULL == lightInfo) {
1882 return D3DERR_OUTOFVIDEOMEMORY;
1884 lightInfo->OriginalIndex = Index;
1885 lightInfo->glIndex = -1;
1886 lightInfo->enabledChanged = TRUE;
1888 /* Add to the END of the chain of lights changes to be replayed */
1889 if (This->UpdateStateBlock->lights == NULL) {
1890 This->UpdateStateBlock->lights = lightInfo;
1892 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1893 while (temp->next != NULL) temp=temp->next;
1894 temp->next = lightInfo;
1896 TRACE("Recording... not performing anything more\n");
1900 /* Not recording... So, locate the light in the live lights */
1901 lightInfo = This->StateBlock->lights;
1902 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1904 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1905 if (lightInfo == NULL) {
1906 D3DLIGHT8 lightParms;
1907 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1908 wait until someone confirms it seems to work! */
1909 TRACE("Light enabled requested but light not defined, so defining one!\n");
1910 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1911 lightParms.Diffuse.r = 1.0;
1912 lightParms.Diffuse.g = 1.0;
1913 lightParms.Diffuse.b = 1.0;
1914 lightParms.Diffuse.a = 0.0;
1915 lightParms.Specular.r = 0.0;
1916 lightParms.Specular.g = 0.0;
1917 lightParms.Specular.b = 0.0;
1918 lightParms.Specular.a = 0.0;
1919 lightParms.Ambient.r = 0.0;
1920 lightParms.Ambient.g = 0.0;
1921 lightParms.Ambient.b = 0.0;
1922 lightParms.Ambient.a = 0.0;
1923 lightParms.Position.x = 0.0;
1924 lightParms.Position.y = 0.0;
1925 lightParms.Position.z = 0.0;
1926 lightParms.Direction.x = 0.0;
1927 lightParms.Direction.y = 0.0;
1928 lightParms.Direction.z = 1.0;
1929 lightParms.Range = 0.0;
1930 lightParms.Falloff = 0.0;
1931 lightParms.Attenuation0 = 0.0;
1932 lightParms.Attenuation1 = 0.0;
1933 lightParms.Attenuation2 = 0.0;
1934 lightParms.Theta = 0.0;
1935 lightParms.Phi = 0.0;
1936 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1938 /* Search for it again! Should be fairly quick as near head of list */
1939 lightInfo = This->StateBlock->lights;
1940 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1941 if (lightInfo == NULL) {
1942 FIXME("Adding default lights has failed dismally\n");
1943 return D3DERR_INVALIDCALL;
1947 /* OK, we now have a light... */
1948 if (Enable == FALSE) {
1950 /* If we are disabling it, check it was enabled, and
1951 still only do something if it has assigned a glIndex (which it should have!) */
1952 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1953 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1955 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1956 checkGLcall("glDisable GL_LIGHT0+Index");
1959 TRACE("Nothing to do as light was not enabled\n");
1961 lightInfo->lightEnabled = FALSE;
1964 /* We are enabling it. If it is enabled, its really simple */
1965 if (lightInfo->lightEnabled == TRUE) {
1967 TRACE("Nothing to do as light was enabled\n");
1969 /* If it already has a glIndex, its still simple */
1970 } else if (lightInfo->glIndex != -1) {
1971 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1972 lightInfo->lightEnabled = TRUE;
1974 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1975 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1978 /* Otherwise got to find space - lights are ordered gl indexes first */
1980 PLIGHTINFOEL *bsf = NULL;
1981 PLIGHTINFOEL *pos = This->StateBlock->lights;
1982 PLIGHTINFOEL *prev = NULL;
1986 /* Try to minimize changes as much as possible */
1987 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1989 /* Try to remember which index can be replaced if necessary */
1990 if (bsf==NULL && pos->lightEnabled == FALSE) {
1991 /* Found a light we can replace, save as best replacement */
1995 /* Step to next space */
2001 /* If we have too many active lights, fail the call */
2002 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2003 FIXME("Program requests too many concurrent lights\n");
2004 return D3DERR_INVALIDCALL;
2006 /* If we have allocated all lights, but not all are enabled,
2007 reuse one which is not enabled */
2008 } else if (Index == This->maxConcurrentLights) {
2009 /* use bsf - Simply swap the new light and the BSF one */
2010 PLIGHTINFOEL *bsfNext = bsf->next;
2011 PLIGHTINFOEL *bsfPrev = bsf->prev;
2014 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2015 if (bsf->prev != NULL) {
2016 bsf->prev->next = lightInfo;
2018 This->StateBlock->lights = lightInfo;
2021 /* If not side by side, lots of chains to update */
2022 if (bsf->next != lightInfo) {
2023 lightInfo->prev->next = bsf;
2024 bsf->next->prev = lightInfo;
2025 bsf->next = lightInfo->next;
2026 bsf->prev = lightInfo->prev;
2027 lightInfo->next = bsfNext;
2028 lightInfo->prev = bsfPrev;
2032 bsf->prev = lightInfo;
2033 bsf->next = lightInfo->next;
2034 lightInfo->next = bsf;
2035 lightInfo->prev = bsfPrev;
2040 glIndex = bsf->glIndex;
2042 lightInfo->glIndex = glIndex;
2043 lightInfo->lightEnabled = TRUE;
2045 /* Finally set up the light in gl itself */
2046 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2048 setup_light(iface, glIndex, lightInfo);
2049 glEnable(GL_LIGHT0 + glIndex);
2050 checkGLcall("glEnable GL_LIGHT0 new setup");
2053 /* If we reached the end of the allocated lights, with space in the
2054 gl lights, setup a new light */
2055 } else if (pos->glIndex == -1) {
2057 /* We reached the end of the allocated gl lights, so already
2058 know the index of the next one! */
2060 lightInfo->glIndex = glIndex;
2061 lightInfo->lightEnabled = TRUE;
2063 /* In an ideal world, its already in the right place */
2064 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2065 /* No need to move it */
2067 /* Remove this light from the list */
2068 lightInfo->prev->next = lightInfo->next;
2069 if (lightInfo->next != NULL) {
2070 lightInfo->next->prev = lightInfo->prev;
2073 /* Add in at appropriate place (inbetween prev and pos) */
2074 lightInfo->prev = prev;
2075 lightInfo->next = pos;
2077 This->StateBlock->lights = lightInfo;
2079 prev->next = lightInfo;
2082 pos->prev = lightInfo;
2086 /* Finally set up the light in gl itself */
2087 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2089 setup_light(iface, glIndex, lightInfo);
2090 glEnable(GL_LIGHT0 + glIndex);
2091 checkGLcall("glEnable GL_LIGHT0 new setup");
2099 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2101 PLIGHTINFOEL *lightInfo = NULL;
2102 ICOM_THIS(IDirect3DDevice8Impl,iface);
2103 TRACE("(%p) : for idx(%ld)\n", This, Index);
2105 /* Locate the light in the live lights */
2106 lightInfo = This->StateBlock->lights;
2107 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2109 if (lightInfo == NULL) {
2110 TRACE("Light enabled state requested but light not defined\n");
2111 return D3DERR_INVALIDCALL;
2113 *pEnable = lightInfo->lightEnabled;
2116 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2117 ICOM_THIS(IDirect3DDevice8Impl,iface);
2118 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2120 /* Validate Index */
2121 if (Index >= GL_LIMITS(clipplanes)) {
2122 TRACE("Application has requested clipplane this device doesn't support\n");
2123 return D3DERR_INVALIDCALL;
2126 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2127 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2128 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2129 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2130 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2131 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2133 /* Handle recording of state blocks */
2134 if (This->isRecordingState) {
2135 TRACE("Recording... not performing anything\n");
2143 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2144 glMatrixMode(GL_MODELVIEW);
2146 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2148 TRACE("Clipplane [%f,%f,%f,%f]\n",
2149 This->UpdateStateBlock->clipplane[Index][0],
2150 This->UpdateStateBlock->clipplane[Index][1],
2151 This->UpdateStateBlock->clipplane[Index][2],
2152 This->UpdateStateBlock->clipplane[Index][3]);
2153 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2154 checkGLcall("glClipPlane");
2162 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2163 ICOM_THIS(IDirect3DDevice8Impl,iface);
2164 TRACE("(%p) : for idx %ld\n", This, Index);
2166 /* Validate Index */
2167 if (Index >= GL_LIMITS(clipplanes)) {
2168 TRACE("Application has requested clipplane this device doesn't support\n");
2169 return D3DERR_INVALIDCALL;
2172 pPlane[0] = This->StateBlock->clipplane[Index][0];
2173 pPlane[1] = This->StateBlock->clipplane[Index][1];
2174 pPlane[2] = This->StateBlock->clipplane[Index][2];
2175 pPlane[3] = This->StateBlock->clipplane[Index][3];
2178 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2179 ICOM_THIS(IDirect3DDevice8Impl,iface);
2180 DWORD OldValue = This->StateBlock->renderstate[State];
2182 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2183 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2184 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2185 This->UpdateStateBlock->renderstate[State] = Value;
2187 /* Handle recording of state blocks */
2188 if (This->isRecordingState) {
2189 TRACE("Recording... not performing anything\n");
2196 case D3DRS_FILLMODE :
2197 switch ((D3DFILLMODE) Value) {
2198 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2199 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2200 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2202 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2204 checkGLcall("glPolygonMode (fillmode)");
2207 case D3DRS_LIGHTING :
2209 glEnable(GL_LIGHTING);
2210 checkGLcall("glEnable GL_LIGHTING");
2212 glDisable(GL_LIGHTING);
2213 checkGLcall("glDisable GL_LIGHTING");
2217 case D3DRS_ZENABLE :
2218 switch ((D3DZBUFFERTYPE) Value) {
2220 glDisable(GL_DEPTH_TEST);
2221 checkGLcall("glDisable GL_DEPTH_TEST");
2224 glEnable(GL_DEPTH_TEST);
2225 checkGLcall("glEnable GL_DEPTH_TEST");
2230 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2234 case D3DRS_CULLMODE :
2236 /* If we are culling "back faces with clockwise vertices" then
2237 set front faces to be counter clockwise and enable culling
2239 switch ((D3DCULL) Value) {
2241 glDisable(GL_CULL_FACE);
2242 checkGLcall("glDisable GL_CULL_FACE");
2245 glEnable(GL_CULL_FACE);
2246 checkGLcall("glEnable GL_CULL_FACE");
2247 glFrontFace(GL_CCW);
2248 checkGLcall("glFrontFace GL_CCW");
2249 glCullFace(GL_BACK);
2252 glEnable(GL_CULL_FACE);
2253 checkGLcall("glEnable GL_CULL_FACE");
2255 checkGLcall("glFrontFace GL_CW");
2256 glCullFace(GL_BACK);
2259 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2263 case D3DRS_SHADEMODE :
2264 switch ((D3DSHADEMODE) Value) {
2266 glShadeModel(GL_FLAT);
2267 checkGLcall("glShadeModel");
2269 case D3DSHADE_GOURAUD:
2270 glShadeModel(GL_SMOOTH);
2271 checkGLcall("glShadeModel");
2273 case D3DSHADE_PHONG:
2274 FIXME("D3DSHADE_PHONG isn't supported?\n");
2277 return D3DERR_INVALIDCALL;
2279 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2283 case D3DRS_DITHERENABLE :
2285 glEnable(GL_DITHER);
2286 checkGLcall("glEnable GL_DITHER");
2288 glDisable(GL_DITHER);
2289 checkGLcall("glDisable GL_DITHER");
2293 case D3DRS_ZWRITEENABLE :
2296 checkGLcall("glDepthMask");
2299 checkGLcall("glDepthMask");
2305 int glParm = GL_LESS;
2307 switch ((D3DCMPFUNC) Value) {
2308 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2309 case D3DCMP_LESS: glParm=GL_LESS; break;
2310 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2311 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2312 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2313 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2314 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2315 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2317 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2319 glDepthFunc(glParm);
2320 checkGLcall("glDepthFunc");
2324 case D3DRS_AMBIENT :
2327 D3DCOLORTOGLFLOAT4(Value, col);
2328 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2329 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2330 checkGLcall("glLightModel for MODEL_AMBIENT");
2335 case D3DRS_ALPHABLENDENABLE :
2338 checkGLcall("glEnable GL_BLEND");
2340 glDisable(GL_BLEND);
2341 checkGLcall("glDisable GL_BLEND");
2345 case D3DRS_SRCBLEND :
2346 case D3DRS_DESTBLEND :
2348 int newVal = GL_ZERO;
2350 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2351 case D3DBLEND_ONE : newVal = GL_ONE; break;
2352 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2353 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2354 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2355 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2356 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2357 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2358 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2359 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2360 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2362 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2363 This->srcBlend = newVal;
2364 This->dstBlend = newVal;
2367 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2368 This->srcBlend = newVal;
2369 This->dstBlend = newVal;
2372 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2375 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2376 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2377 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2378 glBlendFunc(This->srcBlend, This->dstBlend);
2380 checkGLcall("glBlendFunc");
2384 case D3DRS_ALPHATESTENABLE :
2386 glEnable(GL_ALPHA_TEST);
2387 checkGLcall("glEnable GL_ALPHA_TEST");
2389 glDisable(GL_ALPHA_TEST);
2390 checkGLcall("glDisable GL_ALPHA_TEST");
2394 case D3DRS_ALPHAFUNC :
2396 int glParm = GL_LESS;
2397 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2399 switch ((D3DCMPFUNC) Value) {
2400 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2401 case D3DCMP_LESS: glParm = GL_LESS; break;
2402 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2403 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2404 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2405 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2406 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2407 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2409 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2411 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2412 glAlphaFunc(glParm, ref);
2413 This->alphafunc = glParm;
2414 checkGLcall("glAlphaFunc");
2418 case D3DRS_ALPHAREF :
2420 int glParm = This->alphafunc;
2423 ref = ((float) Value) / 255.0f;
2424 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2425 glAlphaFunc(glParm, ref);
2426 checkGLcall("glAlphaFunc");
2430 case D3DRS_CLIPPLANEENABLE :
2431 case D3DRS_CLIPPING :
2433 /* Ensure we only do the changed clip planes */
2434 DWORD enable = 0xFFFFFFFF;
2435 DWORD disable = 0x00000000;
2437 /* If enabling / disabling all */
2438 if (State == D3DRS_CLIPPING) {
2440 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2443 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2447 enable = Value & ~OldValue;
2448 disable = ~Value & OldValue;
2451 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2452 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2453 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2454 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2455 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2456 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2458 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2459 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2460 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2461 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2462 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2463 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2467 case D3DRS_BLENDOP :
2469 int glParm = GL_FUNC_ADD;
2471 switch ((D3DBLENDOP) Value) {
2472 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2473 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2474 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2475 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2476 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2478 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2480 TRACE("glBlendEquation(%x)\n", glParm);
2481 glBlendEquation(glParm);
2482 checkGLcall("glBlendEquation");
2486 case D3DRS_TEXTUREFACTOR :
2490 /* Note the texture color applies to all textures whereas
2491 GL_TEXTURE_ENV_COLOR applies to active only */
2493 D3DCOLORTOGLFLOAT4(Value, col);
2494 /* Set the default alpha blend color */
2495 glBlendColor(col[0], col[1], col[2], col[3]);
2496 checkGLcall("glBlendColor");
2498 /* And now the default texture color as well */
2499 for (i = 0; i < GL_LIMITS(textures); i++) {
2501 /* Note the D3DRS value applies to all textures, but GL has one
2502 per texture, so apply it now ready to be used! */
2503 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2504 #if defined(GL_VERSION_1_3)
2505 glActiveTexture(GL_TEXTURE0 + i);
2507 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2509 checkGLcall("Activate texture.. to update const color");
2511 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2514 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2515 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2520 case D3DRS_SPECULARENABLE :
2522 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2523 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2524 specular color. This is wrong:
2525 Separate specular color means the specular colour is maintained separately, whereas
2526 single color means it is merged in. However in both cases they are being used to
2528 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2529 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2533 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2534 checkGLcall("glMaterialfv");
2535 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2536 glEnable(GL_COLOR_SUM_EXT);
2538 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2540 checkGLcall("glEnable(GL_COLOR_SUM)");
2542 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2544 /* for the case of enabled lighting: */
2545 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2546 checkGLcall("glMaterialfv");
2548 /* for the case of disabled lighting: */
2549 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2550 glDisable(GL_COLOR_SUM_EXT);
2552 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2554 checkGLcall("glDisable(GL_COLOR_SUM)");
2559 case D3DRS_STENCILENABLE :
2561 glEnable(GL_STENCIL_TEST);
2562 checkGLcall("glEnable GL_STENCIL_TEST");
2564 glDisable(GL_STENCIL_TEST);
2565 checkGLcall("glDisable GL_STENCIL_TEST");
2569 case D3DRS_STENCILFUNC :
2571 int glParm = GL_ALWAYS;
2572 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2573 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2575 switch ((D3DCMPFUNC) Value) {
2576 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2577 case D3DCMP_LESS: glParm=GL_LESS; break;
2578 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2579 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2580 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2581 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2582 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2583 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2585 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2587 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2588 This->stencilfunc = glParm;
2589 glStencilFunc(glParm, ref, mask);
2590 checkGLcall("glStencilFunc");
2594 case D3DRS_STENCILREF :
2596 int glParm = This->stencilfunc;
2598 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2601 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2602 glStencilFunc(glParm, ref, mask);
2603 checkGLcall("glStencilFunc");
2607 case D3DRS_STENCILMASK :
2609 int glParm = This->stencilfunc;
2610 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2611 GLuint mask = Value;
2613 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2614 glStencilFunc(glParm, ref, mask);
2615 checkGLcall("glStencilFunc");
2619 case D3DRS_STENCILFAIL :
2625 fail = StencilOp(Value);
2626 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2627 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2628 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2629 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2631 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2632 glStencilOp(fail, zfail, zpass);
2633 checkGLcall("glStencilOp(fail, zfail, zpass);");
2636 case D3DRS_STENCILZFAIL :
2642 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2643 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2644 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2645 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2646 zfail = StencilOp(Value);
2648 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2649 glStencilOp(fail, zfail, zpass);
2650 checkGLcall("glStencilOp(fail, zfail, zpass);");
2653 case D3DRS_STENCILPASS :
2659 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2660 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2661 zpass = StencilOp(Value);
2662 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2663 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2665 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2666 glStencilOp(fail, zfail, zpass);
2667 checkGLcall("glStencilOp(fail, zfail, zpass);");
2671 case D3DRS_STENCILWRITEMASK :
2673 glStencilMask(Value);
2674 TRACE("glStencilMask(%lu)\n", Value);
2675 checkGLcall("glStencilMask");
2679 case D3DRS_FOGENABLE :
2681 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2683 checkGLcall("glEnable GL_FOG");
2686 checkGLcall("glDisable GL_FOG");
2691 case D3DRS_FOGCOLOR :
2694 D3DCOLORTOGLFLOAT4(Value, col);
2695 /* Set the default alpha blend color */
2696 glFogfv(GL_FOG_COLOR, &col[0]);
2697 checkGLcall("glFog GL_FOG_COLOR");
2701 case D3DRS_FOGTABLEMODE :
2704 case D3DFOG_NONE: /* I don't know what to do here */ break;
2705 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2706 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2707 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2709 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2714 case D3DRS_FOGSTART :
2716 float *f = (float*) &Value;
2717 glFogfv(GL_FOG_START, f);
2718 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2719 TRACE("Fog Start == %f\n", *f);
2725 float *f = (float*) &Value;
2726 glFogfv(GL_FOG_END, f);
2727 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2728 TRACE("Fog End == %f\n", *f);
2732 case D3DRS_FOGDENSITY :
2734 float *f = (float*) &Value;
2735 glFogfv(GL_FOG_DENSITY, f);
2736 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2740 case D3DRS_VERTEXBLEND :
2742 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2743 TRACE("Vertex Blending state to %ld\n", Value);
2747 case D3DRS_TWEENFACTOR :
2749 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2750 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2754 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2756 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2760 case D3DRS_COLORVERTEX :
2761 case D3DRS_DIFFUSEMATERIALSOURCE :
2762 case D3DRS_SPECULARMATERIALSOURCE :
2763 case D3DRS_AMBIENTMATERIALSOURCE :
2764 case D3DRS_EMISSIVEMATERIALSOURCE :
2766 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2768 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2769 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2770 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2771 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2772 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2773 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2775 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2776 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2777 Parm = GL_AMBIENT_AND_DIFFUSE;
2781 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2783 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2785 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2792 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2794 This->tracking_color = NEEDS_TRACKING;
2795 This->tracking_parm = Parm;
2799 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2804 case D3DRS_LINEPATTERN :
2806 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2807 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2809 if (pattern->wRepeatFactor) {
2810 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2811 checkGLcall("glLineStipple(repeat, linepattern)");
2812 glEnable(GL_LINE_STIPPLE);
2813 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2815 glDisable(GL_LINE_STIPPLE);
2816 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2824 TRACE("ZBias value %f\n", *((float*)&Value));
2825 glPolygonOffset(0, -*((float*)&Value));
2826 checkGLcall("glPolygonOffset(0, -Value)");
2827 glEnable(GL_POLYGON_OFFSET_FILL);
2828 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2829 glEnable(GL_POLYGON_OFFSET_LINE);
2830 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2831 glEnable(GL_POLYGON_OFFSET_POINT);
2832 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2834 glDisable(GL_POLYGON_OFFSET_FILL);
2835 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2836 glDisable(GL_POLYGON_OFFSET_LINE);
2837 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2838 glDisable(GL_POLYGON_OFFSET_POINT);
2839 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2844 case D3DRS_NORMALIZENORMALS :
2846 glEnable(GL_NORMALIZE);
2847 checkGLcall("glEnable(GL_NORMALIZE);");
2849 glDisable(GL_NORMALIZE);
2850 checkGLcall("glDisable(GL_NORMALIZE);");
2854 case D3DRS_POINTSIZE :
2855 TRACE("Set point size to %f\n", *((float*)&Value));
2856 glPointSize(*((float*)&Value));
2857 checkGLcall("glPointSize(...);");
2860 case D3DRS_POINTSIZE_MIN :
2861 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2862 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2863 checkGLcall("glPointParameterfEXT(...);");
2865 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2869 case D3DRS_POINTSIZE_MAX :
2870 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2871 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2872 checkGLcall("glPointParameterfEXT(...);");
2874 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2878 case D3DRS_POINTSCALE_A :
2879 case D3DRS_POINTSCALE_B :
2880 case D3DRS_POINTSCALE_C :
2881 case D3DRS_POINTSCALEENABLE :
2883 /* If enabled, supply the parameters, otherwise fall back to defaults */
2884 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2885 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2886 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2887 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2888 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2890 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2891 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2892 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2894 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2897 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2898 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2899 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2900 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2902 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2908 case D3DRS_COLORWRITEENABLE :
2909 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2910 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2911 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2912 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2913 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2914 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2915 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2916 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2917 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2918 checkGLcall("glColorMask(...)");
2921 /* Unhandled yet...! */
2922 case D3DRS_LASTPIXEL :
2923 case D3DRS_ZVISIBLE :
2924 case D3DRS_EDGEANTIALIAS :
2925 case D3DRS_RANGEFOGENABLE :
2934 case D3DRS_FOGVERTEXMODE :
2935 case D3DRS_LOCALVIEWER :
2936 case D3DRS_SOFTWAREVERTEXPROCESSING :
2937 case D3DRS_POINTSPRITEENABLE :
2938 case D3DRS_MULTISAMPLEANTIALIAS :
2939 case D3DRS_MULTISAMPLEMASK :
2940 case D3DRS_PATCHEDGESTYLE :
2941 case D3DRS_PATCHSEGMENTS :
2942 case D3DRS_DEBUGMONITORTOKEN :
2943 case D3DRS_POSITIONORDER :
2944 case D3DRS_NORMALORDER :
2945 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2946 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2949 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2956 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2957 ICOM_THIS(IDirect3DDevice8Impl,iface);
2958 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2959 *pValue = This->StateBlock->renderstate[State];
2962 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2963 ICOM_THIS(IDirect3DDevice8Impl,iface);
2965 TRACE("(%p)\n", This);
2967 return IDirect3DDeviceImpl_BeginStateBlock(This);
2969 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2970 IDirect3DStateBlockImpl* pSB;
2971 ICOM_THIS(IDirect3DDevice8Impl,iface);
2974 TRACE("(%p)\n", This);
2976 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2977 *pToken = (DWORD) pSB;
2981 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2982 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2983 ICOM_THIS(IDirect3DDevice8Impl,iface);
2985 TRACE("(%p)\n", This);
2987 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2990 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2991 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2992 ICOM_THIS(IDirect3DDevice8Impl,iface);
2994 TRACE("(%p)\n", This);
2996 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2998 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2999 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3000 ICOM_THIS(IDirect3DDevice8Impl,iface);
3002 TRACE("(%p)\n", This);
3004 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3007 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3008 IDirect3DStateBlockImpl* pSB;
3009 ICOM_THIS(IDirect3DDevice8Impl,iface);
3012 TRACE("(%p) : for type %d\n", This, Type);
3014 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3015 *pToken = (DWORD) pSB;
3019 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3020 ICOM_THIS(IDirect3DDevice8Impl,iface);
3021 FIXME("(%p) : stub\n", This); return D3D_OK;
3023 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3024 ICOM_THIS(IDirect3DDevice8Impl,iface);
3025 FIXME("(%p) : stub\n", This); return D3D_OK;
3027 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3028 ICOM_THIS(IDirect3DDevice8Impl,iface);
3029 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3030 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3031 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3034 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3036 IDirect3DBaseTexture8 *oldTxt;
3037 BOOL reapplyStates = TRUE;
3038 DWORD oldTextureDimensions = -1;
3039 DWORD reapplyFlags = 0;
3041 ICOM_THIS(IDirect3DDevice8Impl,iface);
3042 D3DRESOURCETYPE textureType;
3044 oldTxt = This->UpdateStateBlock->textures[Stage];
3045 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3047 /* Reject invalid texture units */
3048 if (Stage >= GL_LIMITS(textures)) {
3049 TRACE("Attempt to access invalid texture rejected\n");
3050 return D3DERR_INVALIDCALL;
3053 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3054 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3055 This->UpdateStateBlock->textures[Stage] = pTexture;
3057 /* Handle recording of state blocks */
3058 if (This->isRecordingState) {
3059 TRACE("Recording... not performing anything\n");
3063 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3066 /* Make appropriate texture active */
3067 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3068 #if defined(GL_VERSION_1_3)
3069 glActiveTexture(GL_TEXTURE0 + Stage);
3071 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3073 checkGLcall("glActiveTextureARB");
3074 } else if (Stage>0) {
3075 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3078 /* Decrement the count of the previous texture */
3079 if (NULL != oldTxt) {
3080 IDirect3DBaseTexture8Impl_Release(oldTxt);
3083 if (NULL != pTexture) {
3084 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3086 /* Now setup the texture appropraitly */
3087 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3089 if (textureType == D3DRTYPE_TEXTURE) {
3090 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3091 TRACE("Skipping setting texture as old == new\n");
3092 reapplyStates = FALSE;
3094 /* Standard 2D texture */
3095 TRACE("Standard 2d texture\n");
3096 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3098 /* Load up the texture now */
3099 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3101 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3102 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3103 TRACE("Skipping setting texture as old == new\n");
3104 reapplyStates = FALSE;
3106 /* Standard 3D (volume) texture */
3107 TRACE("Standard 3d texture\n");
3108 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3110 /* Load up the texture now */
3111 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3113 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3114 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3115 TRACE("Skipping setting texture as old == new\n");
3116 reapplyStates = FALSE;
3118 /* Standard Cube texture */
3119 TRACE("Standard Cube texture\n");
3120 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3122 /* Load up the texture now */
3123 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3126 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3129 TRACE("Setting to no texture (ie default texture)\n");
3130 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3131 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3132 checkGLcall("glBindTexture");
3133 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3136 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3137 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3138 glDisable(oldTextureDimensions);
3139 checkGLcall("Disable oldTextureDimensions");
3140 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3141 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3142 checkGLcall("glEnable new texture dimensions");
3145 /* If Alpha arg1 is texture then handle the special case when there changes between a
3146 texture and no texture - See comments in set_tex_op */
3147 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3148 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3150 reapplyFlags |= REAPPLY_ALPHAOP;
3155 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3156 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3157 if (reapplyStates) {
3158 setupTextureStates(iface, Stage, reapplyFlags);
3166 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3167 ICOM_THIS(IDirect3DDevice8Impl,iface);
3168 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3169 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3173 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3174 ICOM_THIS(IDirect3DDevice8Impl,iface);
3176 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3178 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3180 /* Reject invalid texture units */
3181 if (Stage >= GL_LIMITS(textures)) {
3182 TRACE("Attempt to access invalid texture rejected\n");
3183 return D3DERR_INVALIDCALL;
3186 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3187 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3188 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3190 /* Handle recording of state blocks */
3191 if (This->isRecordingState) {
3192 TRACE("Recording... not performing anything\n");
3198 /* Make appropriate texture active */
3199 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3200 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3201 #if defined(GL_VERSION_1_3)
3202 glActiveTexture(GL_TEXTURE0 + Stage);
3203 vcheckGLcall("glActiveTexture");
3205 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3206 vcheckGLcall("glActiveTextureARB");
3208 } else if (Stage > 0) {
3209 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3214 case D3DTSS_MINFILTER :
3215 case D3DTSS_MIPFILTER :
3217 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3218 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3219 GLint realVal = GL_LINEAR;
3221 if (ValueMIN == D3DTEXF_POINT) {
3223 if (ValueMIP == D3DTEXF_POINT) {
3224 realVal = GL_NEAREST_MIPMAP_NEAREST;
3225 } else if (ValueMIP == D3DTEXF_LINEAR) {
3226 realVal = GL_NEAREST_MIPMAP_LINEAR;
3227 } else if (ValueMIP == D3DTEXF_NONE) {
3228 realVal = GL_NEAREST;
3230 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3231 realVal = GL_NEAREST_MIPMAP_LINEAR;
3233 } else if (ValueMIN == D3DTEXF_LINEAR) {
3235 if (ValueMIP == D3DTEXF_POINT) {
3236 realVal = GL_LINEAR_MIPMAP_NEAREST;
3237 } else if (ValueMIP == D3DTEXF_LINEAR) {
3238 realVal = GL_LINEAR_MIPMAP_LINEAR;
3239 } else if (ValueMIP == D3DTEXF_NONE) {
3240 realVal = GL_LINEAR;
3242 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3243 realVal = GL_LINEAR_MIPMAP_LINEAR;
3245 } else if (ValueMIN == D3DTEXF_NONE) {
3246 /* Doesn't really make sense - Windows just seems to disable
3247 mipmapping when this occurs */
3248 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3249 realVal = GL_LINEAR;
3252 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3253 realVal = GL_LINEAR_MIPMAP_LINEAR;
3256 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3257 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3258 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3262 case D3DTSS_MAXANISOTROPY :
3264 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3265 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3266 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3271 case D3DTSS_MAGFILTER :
3272 if (Value == D3DTEXF_POINT) {
3273 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3274 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3275 } else if (Value == D3DTEXF_LINEAR) {
3276 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3277 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3279 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3283 case D3DTSS_ALPHAOP :
3284 case D3DTSS_COLOROP :
3287 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3288 /* TODO: Disable by making this and all later levels disabled */
3289 glDisable(GL_TEXTURE_1D);
3290 checkGLcall("Disable GL_TEXTURE_1D");
3291 glDisable(GL_TEXTURE_2D);
3292 checkGLcall("Disable GL_TEXTURE_2D");
3293 glDisable(GL_TEXTURE_3D);
3294 checkGLcall("Disable GL_TEXTURE_3D");
3295 break; /* Don't bother setting the texture operations */
3297 /* Enable only the appropriate texture dimension */
3298 if (Type == D3DTSS_COLOROP) {
3299 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3300 glEnable(GL_TEXTURE_1D);
3301 checkGLcall("Enable GL_TEXTURE_1D");
3303 glDisable(GL_TEXTURE_1D);
3304 checkGLcall("Disable GL_TEXTURE_1D");
3306 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3307 glEnable(GL_TEXTURE_2D);
3308 checkGLcall("Enable GL_TEXTURE_2D");
3310 glDisable(GL_TEXTURE_2D);
3311 checkGLcall("Disable GL_TEXTURE_2D");
3313 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3314 glEnable(GL_TEXTURE_3D);
3315 checkGLcall("Enable GL_TEXTURE_3D");
3317 glDisable(GL_TEXTURE_3D);
3318 checkGLcall("Disable GL_TEXTURE_3D");
3320 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3321 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3322 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3324 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3325 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3329 /* Drop through... (Except disable case) */
3330 case D3DTSS_COLORARG0 :
3331 case D3DTSS_COLORARG1 :
3332 case D3DTSS_COLORARG2 :
3333 case D3DTSS_ALPHAARG0 :
3334 case D3DTSS_ALPHAARG1 :
3335 case D3DTSS_ALPHAARG2 :
3337 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3338 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3340 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3341 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3342 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3343 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3345 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3346 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3347 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3348 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3354 case D3DTSS_ADDRESSU :
3355 case D3DTSS_ADDRESSV :
3356 case D3DTSS_ADDRESSW :
3358 GLint wrapParm = GL_REPEAT;
3360 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3361 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3362 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3363 #if defined(GL_VERSION_1_4)
3364 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3365 #elif defined(GL_ARB_texture_mirrored_repeat)
3366 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3368 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3370 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3372 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3373 wrapParm = GL_REPEAT;
3377 case D3DTSS_ADDRESSU:
3378 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3379 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3380 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3382 case D3DTSS_ADDRESSV:
3383 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3384 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3385 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3387 case D3DTSS_ADDRESSW:
3388 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3389 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3390 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3393 break; /** stupic compilator */
3398 case D3DTSS_BORDERCOLOR :
3401 D3DCOLORTOGLFLOAT4(Value, col);
3402 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3403 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3404 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3408 case D3DTSS_TEXCOORDINDEX :
3410 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3412 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3413 one flag, you can still specify an index value, which the system uses to
3414 determine the texture wrapping mode.
3415 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3416 means use the vertex position (camera-space) as the input texture coordinates
3417 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3418 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3419 to the TEXCOORDINDEX value */
3422 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3424 switch (Value & 0xFFFF0000) {
3425 case D3DTSS_TCI_PASSTHRU:
3426 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3427 glDisable(GL_TEXTURE_GEN_S);
3428 glDisable(GL_TEXTURE_GEN_T);
3429 glDisable(GL_TEXTURE_GEN_R);
3430 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3433 case D3DTSS_TCI_CAMERASPACEPOSITION:
3434 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3435 as the input texture coordinates for this stage's texture transformation. This
3436 equates roughly to EYE_LINEAR */
3438 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3439 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3440 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3441 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3442 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3444 glMatrixMode(GL_MODELVIEW);
3447 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3448 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3449 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3450 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3453 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3454 glEnable(GL_TEXTURE_GEN_S);
3455 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3456 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3457 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3458 glEnable(GL_TEXTURE_GEN_T);
3459 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3460 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3461 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3462 glEnable(GL_TEXTURE_GEN_R);
3463 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3464 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3465 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3469 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3470 case D3DTSS_TCI_CAMERASPACENORMAL:
3472 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3473 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3474 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3475 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3476 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3478 glMatrixMode(GL_MODELVIEW);
3481 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3482 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3483 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3484 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3487 glEnable(GL_TEXTURE_GEN_S);
3488 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3489 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3490 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3491 glEnable(GL_TEXTURE_GEN_T);
3492 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3493 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3494 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3495 glEnable(GL_TEXTURE_GEN_R);
3496 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3497 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3498 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3503 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3504 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3507 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3508 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3509 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3510 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3511 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3513 glMatrixMode(GL_MODELVIEW);
3516 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3517 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3518 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3519 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3522 glEnable(GL_TEXTURE_GEN_S);
3523 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3524 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3525 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3526 glEnable(GL_TEXTURE_GEN_T);
3527 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3528 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3529 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3530 glEnable(GL_TEXTURE_GEN_R);
3531 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3532 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3533 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3538 /* Unhandled types: */
3541 /* ? disable GL_TEXTURE_GEN_n ? */
3542 glDisable(GL_TEXTURE_GEN_S);
3543 glDisable(GL_TEXTURE_GEN_T);
3544 glDisable(GL_TEXTURE_GEN_R);
3545 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3552 case D3DTSS_BUMPENVMAT00 :
3553 case D3DTSS_BUMPENVMAT01 :
3554 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3556 case D3DTSS_BUMPENVMAT10 :
3557 case D3DTSS_BUMPENVMAT11 :
3558 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3561 case D3DTSS_TEXTURETRANSFORMFLAGS :
3562 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3565 case D3DTSS_MIPMAPLODBIAS :
3566 case D3DTSS_MAXMIPLEVEL :
3567 case D3DTSS_BUMPENVLSCALE :
3568 case D3DTSS_BUMPENVLOFFSET :
3569 case D3DTSS_RESULTARG :
3571 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3572 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3579 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3580 ICOM_THIS(IDirect3DDevice8Impl,iface);
3581 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3584 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3585 ICOM_THIS(IDirect3DDevice8Impl,iface);
3586 FIXME("(%p) : stub\n", This);
3589 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3590 ICOM_THIS(IDirect3DDevice8Impl,iface);
3591 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3592 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3593 if (PaletteNumber >= MAX_PALETTES) {
3594 return D3DERR_INVALIDCALL;
3596 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3599 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3600 ICOM_THIS(IDirect3DDevice8Impl,iface);
3601 if (PaletteNumber >= MAX_PALETTES) {
3602 return D3DERR_INVALIDCALL;
3604 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3605 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3606 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3609 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3610 ICOM_THIS(IDirect3DDevice8Impl,iface);
3611 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3612 if (PaletteNumber >= MAX_PALETTES) {
3613 return D3DERR_INVALIDCALL;
3615 This->currentPalette = PaletteNumber;
3617 #if defined(GL_EXT_paletted_texture)
3618 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3622 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3623 GL_RGBA, /* internal format */
3624 256, /* table size */
3625 GL_RGBA, /* table format */
3626 GL_UNSIGNED_BYTE, /* table type */
3627 This->palettes[PaletteNumber]);
3628 checkGLcall("glColorTableEXT");
3633 /* Delayed palette handling ... waiting for software emulation into preload code */
3638 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3639 ICOM_THIS(IDirect3DDevice8Impl,iface);
3640 *PaletteNumber = This->currentPalette;
3641 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3644 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3646 ICOM_THIS(IDirect3DDevice8Impl,iface);
3647 This->StateBlock->streamIsUP = FALSE;
3649 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3650 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3654 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3655 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3657 IDirect3DIndexBuffer8 *pIB;
3658 D3DINDEXBUFFER_DESC IdxBufDsc;
3660 ICOM_THIS(IDirect3DDevice8Impl,iface);
3661 pIB = This->StateBlock->pIndexData;
3662 This->StateBlock->streamIsUP = FALSE;
3664 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3665 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3666 minIndex, NumVertices, startIndex, primCount);
3668 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3669 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3675 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3680 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3681 ICOM_THIS(IDirect3DDevice8Impl,iface);
3683 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3684 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3686 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3688 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3689 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3690 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3691 This->StateBlock->streamIsUP = TRUE;
3692 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3693 This->StateBlock->stream_stride[0] = 0;
3694 This->StateBlock->stream_source[0] = NULL;
3696 /*stream zero settings set to null at end */
3699 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3700 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3701 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3702 UINT VertexStreamZeroStride) {
3704 ICOM_THIS(IDirect3DDevice8Impl,iface);
3705 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),
3706 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3708 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3709 if (IndexDataFormat == D3DFMT_INDEX16) {
3715 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3716 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3717 This->StateBlock->streamIsUP = TRUE;
3718 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3719 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3721 /*stream zero settings set to null at end */
3722 This->StateBlock->stream_source[0] = NULL;
3723 This->StateBlock->stream_stride[0] = 0;
3724 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3728 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3729 ICOM_THIS(IDirect3DDevice8Impl,iface);
3730 FIXME("(%p) : stub\n", This); return D3D_OK;
3732 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3733 ICOM_THIS(IDirect3DDevice8Impl,iface);
3734 IDirect3DVertexShaderImpl* object;
3735 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3739 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3740 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3741 return D3DERR_INVALIDCALL;
3743 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3744 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3745 return D3DERR_OUTOFVIDEOMEMORY;
3748 /** Create the Vertex Shader */
3749 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3750 /** TODO: check FAILED(res) */
3752 /** Create and Bind the Vertex Shader Declaration */
3753 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3754 /** TODO: check FAILED(res) */
3756 VertexShaders[i] = object;
3757 VertexShaderDeclarations[i] = attached_decl;
3758 *pHandle = VS_HIGHESTFIXEDFXF + i;
3759 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3763 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3764 ICOM_THIS(IDirect3DDevice8Impl,iface);
3766 This->UpdateStateBlock->VertexShader = Handle;
3767 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3768 This->UpdateStateBlock->Set.vertexShader = TRUE;
3770 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3771 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3772 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3773 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3774 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3775 } else { /* use a fvf, so desactivate the vshader decl */
3776 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3777 This->UpdateStateBlock->vertexShaderDecl = NULL;
3778 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3779 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3781 /* Handle recording of state blocks */
3782 if (This->isRecordingState) {
3783 TRACE("Recording... not performing anything\n");
3787 * TODO: merge HAL shaders context switching from prototype
3791 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3792 ICOM_THIS(IDirect3DDevice8Impl,iface);
3793 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3794 *pHandle = This->StateBlock->VertexShader;
3798 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3799 ICOM_THIS(IDirect3DDevice8Impl,iface);
3800 IDirect3DVertexShaderImpl* object;
3801 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3803 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3804 return D3DERR_INVALIDCALL;
3808 * Delete Vertex Shader
3810 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3811 if (NULL == object) {
3812 return D3DERR_INVALIDCALL;
3814 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3815 /* TODO: check validity of object */
3816 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3817 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3818 HeapFree(GetProcessHeap(), 0, (void *)object);
3819 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3822 * Delete Vertex Shader Declaration
3824 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3825 if (NULL == attached_decl) {
3826 return D3DERR_INVALIDCALL;
3828 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3829 /* TODO: check validity of object */
3830 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3831 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3832 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3837 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3838 ICOM_THIS(IDirect3DDevice8Impl,iface);
3840 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3841 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3842 return D3DERR_INVALIDCALL;
3844 if (NULL == pConstantData) {
3845 return D3DERR_INVALIDCALL;
3847 if (ConstantCount > 1) {
3848 FLOAT* f = (FLOAT*)pConstantData;
3850 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3851 for (i = 0; i < ConstantCount; ++i) {
3852 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3856 FLOAT* f = (FLOAT*) pConstantData;
3857 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3859 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3860 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3863 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3864 ICOM_THIS(IDirect3DDevice8Impl,iface);
3866 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3867 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3868 return D3DERR_INVALIDCALL;
3870 if (NULL == pConstantData) {
3871 return D3DERR_INVALIDCALL;
3873 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3876 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3877 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3878 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3880 attached_decl = VERTEX_SHADER_DECL(Handle);
3881 if (NULL == attached_decl) {
3882 return D3DERR_INVALIDCALL;
3884 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3886 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3887 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3888 IDirect3DVertexShaderImpl* object;
3890 object = VERTEX_SHADER(Handle);
3891 if (NULL == object) {
3892 return D3DERR_INVALIDCALL;
3894 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3897 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3898 ICOM_THIS(IDirect3DDevice8Impl,iface);
3899 IDirect3DIndexBuffer8 *oldIdxs;
3901 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3902 oldIdxs = This->StateBlock->pIndexData;
3904 This->UpdateStateBlock->Changed.Indices = TRUE;
3905 This->UpdateStateBlock->Set.Indices = TRUE;
3906 This->UpdateStateBlock->pIndexData = pIndexData;
3907 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3909 /* Handle recording of state blocks */
3910 if (This->isRecordingState) {
3911 TRACE("Recording... not performing anything\n");
3915 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3916 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3919 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3920 ICOM_THIS(IDirect3DDevice8Impl,iface);
3921 FIXME("(%p) : stub\n", This);
3923 *ppIndexData = This->StateBlock->pIndexData;
3924 /* up ref count on ppindexdata */
3925 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3926 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3930 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3931 ICOM_THIS(IDirect3DDevice8Impl,iface);
3932 IDirect3DPixelShaderImpl* object;
3936 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3937 if (NULL == pFunction || NULL == pHandle) {
3938 return D3DERR_INVALIDCALL;
3940 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3941 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3942 return D3DERR_OUTOFVIDEOMEMORY;
3945 /** Create the Pixel Shader */
3946 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3947 if (SUCCEEDED(res)) {
3948 PixelShaders[i] = object;
3949 *pHandle = VS_HIGHESTFIXEDFXF + i;
3952 *pHandle = 0xFFFFFFFF;
3955 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3956 ICOM_THIS(IDirect3DDevice8Impl,iface);
3958 This->UpdateStateBlock->PixelShader = Handle;
3959 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3960 This->UpdateStateBlock->Set.pixelShader = TRUE;
3962 /* Handle recording of state blocks */
3963 if (This->isRecordingState) {
3964 TRACE_(d3d_shader)("Recording... not performing anything\n");
3968 /* FIXME: Quieten when not being used */
3970 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3972 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3977 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3978 ICOM_THIS(IDirect3DDevice8Impl,iface);
3979 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3980 *pHandle = This->StateBlock->PixelShader;
3984 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3985 ICOM_THIS(IDirect3DDevice8Impl,iface);
3986 IDirect3DPixelShaderImpl* object;
3988 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3989 return D3DERR_INVALIDCALL;
3991 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3992 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3993 /* TODO: check validity of object before free */
3994 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3995 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3996 HeapFree(GetProcessHeap(), 0, (void *)object);
3997 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4002 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4003 ICOM_THIS(IDirect3DDevice8Impl,iface);
4005 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4006 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4007 return D3DERR_INVALIDCALL;
4009 if (NULL == pConstantData) {
4010 return D3DERR_INVALIDCALL;
4012 if (ConstantCount > 1) {
4013 FLOAT* f = (FLOAT*)pConstantData;
4015 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4016 for (i = 0; i < ConstantCount; ++i) {
4017 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4021 FLOAT* f = (FLOAT*) pConstantData;
4022 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4024 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4025 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4028 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4029 ICOM_THIS(IDirect3DDevice8Impl,iface);
4031 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4032 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4033 return D3DERR_INVALIDCALL;
4035 if (NULL == pConstantData) {
4036 return D3DERR_INVALIDCALL;
4038 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4041 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4042 IDirect3DPixelShaderImpl* object;
4044 object = PIXEL_SHADER(Handle);
4045 if (NULL == object) {
4046 return D3DERR_INVALIDCALL;
4048 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4050 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4051 ICOM_THIS(IDirect3DDevice8Impl,iface);
4052 FIXME("(%p) : stub\n", This); return D3D_OK;
4054 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4055 ICOM_THIS(IDirect3DDevice8Impl,iface);
4056 FIXME("(%p) : stub\n", This); return D3D_OK;
4058 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4059 ICOM_THIS(IDirect3DDevice8Impl,iface);
4060 FIXME("(%p) : stub\n", This); return D3D_OK;
4063 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4064 IDirect3DVertexBuffer8 *oldSrc;
4065 ICOM_THIS(IDirect3DDevice8Impl,iface);
4067 oldSrc = This->StateBlock->stream_source[StreamNumber];
4068 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4070 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4071 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4072 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4073 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4075 /* Handle recording of state blocks */
4076 if (This->isRecordingState) {
4077 TRACE("Recording... not performing anything\n");
4081 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4082 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4085 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4086 ICOM_THIS(IDirect3DDevice8Impl,iface);
4087 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4088 *pStream = This->StateBlock->stream_source[StreamNumber];
4089 *pStride = This->StateBlock->stream_stride[StreamNumber];
4090 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4095 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4097 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4098 IDirect3DDevice8Impl_QueryInterface,
4099 IDirect3DDevice8Impl_AddRef,
4100 IDirect3DDevice8Impl_Release,
4101 IDirect3DDevice8Impl_TestCooperativeLevel,
4102 IDirect3DDevice8Impl_GetAvailableTextureMem,
4103 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4104 IDirect3DDevice8Impl_GetDirect3D,
4105 IDirect3DDevice8Impl_GetDeviceCaps,
4106 IDirect3DDevice8Impl_GetDisplayMode,
4107 IDirect3DDevice8Impl_GetCreationParameters,
4108 IDirect3DDevice8Impl_SetCursorProperties,
4109 IDirect3DDevice8Impl_SetCursorPosition,
4110 IDirect3DDevice8Impl_ShowCursor,
4111 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4112 IDirect3DDevice8Impl_Reset,
4113 IDirect3DDevice8Impl_Present,
4114 IDirect3DDevice8Impl_GetBackBuffer,
4115 IDirect3DDevice8Impl_GetRasterStatus,
4116 IDirect3DDevice8Impl_SetGammaRamp,
4117 IDirect3DDevice8Impl_GetGammaRamp,
4118 IDirect3DDevice8Impl_CreateTexture,
4119 IDirect3DDevice8Impl_CreateVolumeTexture,
4120 IDirect3DDevice8Impl_CreateCubeTexture,
4121 IDirect3DDevice8Impl_CreateVertexBuffer,
4122 IDirect3DDevice8Impl_CreateIndexBuffer,
4123 IDirect3DDevice8Impl_CreateRenderTarget,
4124 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4125 IDirect3DDevice8Impl_CreateImageSurface,
4126 IDirect3DDevice8Impl_CopyRects,
4127 IDirect3DDevice8Impl_UpdateTexture,
4128 IDirect3DDevice8Impl_GetFrontBuffer,
4129 IDirect3DDevice8Impl_SetRenderTarget,
4130 IDirect3DDevice8Impl_GetRenderTarget,
4131 IDirect3DDevice8Impl_GetDepthStencilSurface,
4132 IDirect3DDevice8Impl_BeginScene,
4133 IDirect3DDevice8Impl_EndScene,
4134 IDirect3DDevice8Impl_Clear,
4135 IDirect3DDevice8Impl_SetTransform,
4136 IDirect3DDevice8Impl_GetTransform,
4137 IDirect3DDevice8Impl_MultiplyTransform,
4138 IDirect3DDevice8Impl_SetViewport,
4139 IDirect3DDevice8Impl_GetViewport,
4140 IDirect3DDevice8Impl_SetMaterial,
4141 IDirect3DDevice8Impl_GetMaterial,
4142 IDirect3DDevice8Impl_SetLight,
4143 IDirect3DDevice8Impl_GetLight,
4144 IDirect3DDevice8Impl_LightEnable,
4145 IDirect3DDevice8Impl_GetLightEnable,
4146 IDirect3DDevice8Impl_SetClipPlane,
4147 IDirect3DDevice8Impl_GetClipPlane,
4148 IDirect3DDevice8Impl_SetRenderState,
4149 IDirect3DDevice8Impl_GetRenderState,
4150 IDirect3DDevice8Impl_BeginStateBlock,
4151 IDirect3DDevice8Impl_EndStateBlock,
4152 IDirect3DDevice8Impl_ApplyStateBlock,
4153 IDirect3DDevice8Impl_CaptureStateBlock,
4154 IDirect3DDevice8Impl_DeleteStateBlock,
4155 IDirect3DDevice8Impl_CreateStateBlock,
4156 IDirect3DDevice8Impl_SetClipStatus,
4157 IDirect3DDevice8Impl_GetClipStatus,
4158 IDirect3DDevice8Impl_GetTexture,
4159 IDirect3DDevice8Impl_SetTexture,
4160 IDirect3DDevice8Impl_GetTextureStageState,
4161 IDirect3DDevice8Impl_SetTextureStageState,
4162 IDirect3DDevice8Impl_ValidateDevice,
4163 IDirect3DDevice8Impl_GetInfo,
4164 IDirect3DDevice8Impl_SetPaletteEntries,
4165 IDirect3DDevice8Impl_GetPaletteEntries,
4166 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4167 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4168 IDirect3DDevice8Impl_DrawPrimitive,
4169 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4170 IDirect3DDevice8Impl_DrawPrimitiveUP,
4171 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4172 IDirect3DDevice8Impl_ProcessVertices,
4173 IDirect3DDevice8Impl_CreateVertexShader,
4174 IDirect3DDevice8Impl_SetVertexShader,
4175 IDirect3DDevice8Impl_GetVertexShader,
4176 IDirect3DDevice8Impl_DeleteVertexShader,
4177 IDirect3DDevice8Impl_SetVertexShaderConstant,
4178 IDirect3DDevice8Impl_GetVertexShaderConstant,
4179 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4180 IDirect3DDevice8Impl_GetVertexShaderFunction,
4181 IDirect3DDevice8Impl_SetStreamSource,
4182 IDirect3DDevice8Impl_GetStreamSource,
4183 IDirect3DDevice8Impl_SetIndices,
4184 IDirect3DDevice8Impl_GetIndices,
4185 IDirect3DDevice8Impl_CreatePixelShader,
4186 IDirect3DDevice8Impl_SetPixelShader,
4187 IDirect3DDevice8Impl_GetPixelShader,
4188 IDirect3DDevice8Impl_DeletePixelShader,
4189 IDirect3DDevice8Impl_SetPixelShaderConstant,
4190 IDirect3DDevice8Impl_GetPixelShaderConstant,
4191 IDirect3DDevice8Impl_GetPixelShaderFunction,
4192 IDirect3DDevice8Impl_DrawRectPatch,
4193 IDirect3DDevice8Impl_DrawTriPatch,
4194 IDirect3DDevice8Impl_DeletePatch
4197 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4199 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4200 ICOM_THIS(IDirect3DDevice8Impl,iface);
4205 if (This->glCtx != This->render_ctx) {
4206 glXDestroyContext(This->display, This->render_ctx);
4207 This->render_ctx = This->glCtx;
4210 if (This->win != This->drawable) {
4211 glXDestroyPbuffer(This->display, This->drawable);
4212 This->drawable = This->win;
4221 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4222 IDirect3DSurface8* RenderSurface,
4223 IDirect3DSurface8* StencilSurface) {
4225 HRESULT ret = D3DERR_INVALIDCALL;
4227 * Currently only active for GLX >= 1.3
4228 * for others versions we'll have to use GLXPixmaps
4230 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4231 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4232 * so only check OpenGL version
4234 #if defined(GL_VERSION_1_3)
4235 GLXFBConfig* cfgs = NULL;
4239 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4240 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4241 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4242 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4243 IDirect3DSurface8Impl* tmp;
4245 ICOM_THIS(IDirect3DDevice8Impl,iface);
4247 #define PUSH1(att) attribs[nAttribs++] = (att);
4248 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4250 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4251 PUSH2(GLX_X_RENDERABLE, TRUE);
4252 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4254 switch (BackBufferFormat) {
4257 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4258 PUSH2(GLX_BUFFER_SIZE, 8);
4259 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4263 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4264 PUSH2(GLX_RED_SIZE, 3);
4265 PUSH2(GLX_GREEN_SIZE, 3);
4266 PUSH2(GLX_BLUE_SIZE, 2);
4269 case D3DFMT_A1R5G5B5:
4270 PUSH2(GLX_ALPHA_SIZE, 1);
4271 case D3DFMT_X1R5G5B5:
4272 PUSH2(GLX_RED_SIZE, 5);
4273 PUSH2(GLX_GREEN_SIZE, 5);
4274 PUSH2(GLX_BLUE_SIZE, 5);
4278 PUSH2(GLX_RED_SIZE, 5);
4279 PUSH2(GLX_GREEN_SIZE, 6);
4280 PUSH2(GLX_BLUE_SIZE, 5);
4283 case D3DFMT_A4R4G4B4:
4284 PUSH2(GLX_ALPHA_SIZE, 4);
4285 case D3DFMT_X4R4G4B4:
4286 PUSH2(GLX_RED_SIZE, 4);
4287 PUSH2(GLX_GREEN_SIZE, 4);
4288 PUSH2(GLX_BLUE_SIZE, 4);
4291 case D3DFMT_A8R8G8B8:
4292 PUSH2(GLX_ALPHA_SIZE, 8);
4294 case D3DFMT_X8R8G8B8:
4295 PUSH2(GLX_RED_SIZE, 8);
4296 PUSH2(GLX_GREEN_SIZE, 8);
4297 PUSH2(GLX_BLUE_SIZE, 8);
4304 switch (StencilBufferFormat) {
4305 case D3DFMT_D16_LOCKABLE:
4307 PUSH2(GLX_DEPTH_SIZE, 16);
4311 PUSH2(GLX_DEPTH_SIZE, 15);
4315 PUSH2(GLX_DEPTH_SIZE, 24);
4318 case D3DFMT_D24X4S4:
4319 PUSH2(GLX_DEPTH_SIZE, 24);
4320 PUSH2(GLX_STENCIL_SIZE, 4);
4324 PUSH2(GLX_DEPTH_SIZE, 24);
4325 PUSH2(GLX_STENCIL_SIZE, 8);
4329 PUSH2(GLX_DEPTH_SIZE, 32);
4340 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4344 for (i = 0; i < nCfgs; ++i) {
4345 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4349 if (NULL != This->renderTarget) {
4352 vcheckGLcall("glFlush");
4355 /** very very usefull debug code */
4356 glXSwapBuffers(This->display, This->drawable);
4357 printf("Hit Enter to get next frame ...\n");
4361 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4362 vcheckGLcall("glIntegerv");
4363 glReadBuffer(GL_BACK);
4364 vcheckGLcall("glReadBuffer");
4367 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4369 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4372 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4374 This->renderTarget->myDesc.Height - j - 1,
4375 This->renderTarget->myDesc.Width,
4377 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4378 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4379 This->renderTarget->allocatedMemory + j * pitch);
4380 vcheckGLcall("glReadPixels");
4383 glReadBuffer(prev_read);
4384 vcheckGLcall("glReadBuffer");
4387 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4388 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4390 PUSH2(GLX_PBUFFER_WIDTH, Width);
4391 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4393 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4395 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4396 if (NULL == This->render_ctx) {
4397 ERR("cannot create glxContext\n");
4401 glXSwapBuffers(This->display, This->drawable);
4402 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4403 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4405 checkGLcall("glXMakeContextCurrent");
4408 tmp = This->renderTarget;
4409 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4410 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4411 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4413 tmp = This->stencilBufferTarget;
4414 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4415 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4416 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4421 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));