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];
3032 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3035 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3037 IDirect3DBaseTexture8 *oldTxt;
3038 BOOL reapplyStates = TRUE;
3039 DWORD oldTextureDimensions = -1;
3040 DWORD reapplyFlags = 0;
3042 ICOM_THIS(IDirect3DDevice8Impl,iface);
3043 D3DRESOURCETYPE textureType;
3045 oldTxt = This->UpdateStateBlock->textures[Stage];
3046 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3048 /* Reject invalid texture units */
3049 if (Stage >= GL_LIMITS(textures)) {
3050 TRACE("Attempt to access invalid texture rejected\n");
3051 return D3DERR_INVALIDCALL;
3054 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3055 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3056 This->UpdateStateBlock->textures[Stage] = pTexture;
3058 /* Handle recording of state blocks */
3059 if (This->isRecordingState) {
3060 TRACE("Recording... not performing anything\n");
3064 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3067 /* Make appropriate texture active */
3068 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3069 #if defined(GL_VERSION_1_3)
3070 glActiveTexture(GL_TEXTURE0 + Stage);
3072 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3074 checkGLcall("glActiveTextureARB");
3075 } else if (Stage>0) {
3076 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3079 /* Decrement the count of the previous texture */
3080 if (NULL != oldTxt) {
3081 IDirect3DBaseTexture8Impl_Release(oldTxt);
3084 if (NULL != pTexture) {
3085 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3087 /* Now setup the texture appropraitly */
3088 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3090 if (textureType == D3DRTYPE_TEXTURE) {
3091 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3092 TRACE("Skipping setting texture as old == new\n");
3093 reapplyStates = FALSE;
3095 /* Standard 2D texture */
3096 TRACE("Standard 2d texture\n");
3097 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3099 /* Load up the texture now */
3100 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3102 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3103 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3104 TRACE("Skipping setting texture as old == new\n");
3105 reapplyStates = FALSE;
3107 /* Standard 3D (volume) texture */
3108 TRACE("Standard 3d texture\n");
3109 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3111 /* Load up the texture now */
3112 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3114 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3115 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3116 TRACE("Skipping setting texture as old == new\n");
3117 reapplyStates = FALSE;
3119 /* Standard Cube texture */
3120 TRACE("Standard Cube texture\n");
3121 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3123 /* Load up the texture now */
3124 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3127 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3130 TRACE("Setting to no texture (ie default texture)\n");
3131 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3132 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3133 checkGLcall("glBindTexture");
3134 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3137 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3138 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3139 glDisable(oldTextureDimensions);
3140 checkGLcall("Disable oldTextureDimensions");
3141 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3142 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3143 checkGLcall("glEnable new texture dimensions");
3146 /* If Alpha arg1 is texture then handle the special case when there changes between a
3147 texture and no texture - See comments in set_tex_op */
3148 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3149 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3151 reapplyFlags |= REAPPLY_ALPHAOP;
3156 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3157 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3158 if (reapplyStates) {
3159 setupTextureStates(iface, Stage, reapplyFlags);
3167 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3168 ICOM_THIS(IDirect3DDevice8Impl,iface);
3169 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3170 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3174 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3175 ICOM_THIS(IDirect3DDevice8Impl,iface);
3177 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3179 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3181 /* Reject invalid texture units */
3182 if (Stage >= GL_LIMITS(textures)) {
3183 TRACE("Attempt to access invalid texture rejected\n");
3184 return D3DERR_INVALIDCALL;
3187 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3188 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3189 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3191 /* Handle recording of state blocks */
3192 if (This->isRecordingState) {
3193 TRACE("Recording... not performing anything\n");
3199 /* Make appropriate texture active */
3200 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3201 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3202 #if defined(GL_VERSION_1_3)
3203 glActiveTexture(GL_TEXTURE0 + Stage);
3204 vcheckGLcall("glActiveTexture");
3206 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3207 vcheckGLcall("glActiveTextureARB");
3209 } else if (Stage > 0) {
3210 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3215 case D3DTSS_MINFILTER :
3216 case D3DTSS_MIPFILTER :
3218 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3219 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3220 GLint realVal = GL_LINEAR;
3222 if (ValueMIN == D3DTEXF_POINT) {
3224 if (ValueMIP == D3DTEXF_POINT) {
3225 realVal = GL_NEAREST_MIPMAP_NEAREST;
3226 } else if (ValueMIP == D3DTEXF_LINEAR) {
3227 realVal = GL_NEAREST_MIPMAP_LINEAR;
3228 } else if (ValueMIP == D3DTEXF_NONE) {
3229 realVal = GL_NEAREST;
3231 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3232 realVal = GL_NEAREST_MIPMAP_LINEAR;
3234 } else if (ValueMIN == D3DTEXF_LINEAR) {
3236 if (ValueMIP == D3DTEXF_POINT) {
3237 realVal = GL_LINEAR_MIPMAP_NEAREST;
3238 } else if (ValueMIP == D3DTEXF_LINEAR) {
3239 realVal = GL_LINEAR_MIPMAP_LINEAR;
3240 } else if (ValueMIP == D3DTEXF_NONE) {
3241 realVal = GL_LINEAR;
3243 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3244 realVal = GL_LINEAR_MIPMAP_LINEAR;
3246 } else if (ValueMIN == D3DTEXF_NONE) {
3247 /* Doesn't really make sense - Windows just seems to disable
3248 mipmapping when this occurs */
3249 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3250 realVal = GL_LINEAR;
3253 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3254 realVal = GL_LINEAR_MIPMAP_LINEAR;
3257 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3258 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3259 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3263 case D3DTSS_MAXANISOTROPY :
3265 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3266 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3267 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3272 case D3DTSS_MAGFILTER :
3273 if (Value == D3DTEXF_POINT) {
3274 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3275 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3276 } else if (Value == D3DTEXF_LINEAR) {
3277 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3278 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3280 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3284 case D3DTSS_ALPHAOP :
3285 case D3DTSS_COLOROP :
3288 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3289 /* TODO: Disable by making this and all later levels disabled */
3290 glDisable(GL_TEXTURE_1D);
3291 checkGLcall("Disable GL_TEXTURE_1D");
3292 glDisable(GL_TEXTURE_2D);
3293 checkGLcall("Disable GL_TEXTURE_2D");
3294 glDisable(GL_TEXTURE_3D);
3295 checkGLcall("Disable GL_TEXTURE_3D");
3296 break; /* Don't bother setting the texture operations */
3298 /* Enable only the appropriate texture dimension */
3299 if (Type == D3DTSS_COLOROP) {
3300 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3301 glEnable(GL_TEXTURE_1D);
3302 checkGLcall("Enable GL_TEXTURE_1D");
3304 glDisable(GL_TEXTURE_1D);
3305 checkGLcall("Disable GL_TEXTURE_1D");
3307 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3308 glEnable(GL_TEXTURE_2D);
3309 checkGLcall("Enable GL_TEXTURE_2D");
3311 glDisable(GL_TEXTURE_2D);
3312 checkGLcall("Disable GL_TEXTURE_2D");
3314 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3315 glEnable(GL_TEXTURE_3D);
3316 checkGLcall("Enable GL_TEXTURE_3D");
3318 glDisable(GL_TEXTURE_3D);
3319 checkGLcall("Disable GL_TEXTURE_3D");
3321 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3322 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3323 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3325 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3326 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3330 /* Drop through... (Except disable case) */
3331 case D3DTSS_COLORARG0 :
3332 case D3DTSS_COLORARG1 :
3333 case D3DTSS_COLORARG2 :
3334 case D3DTSS_ALPHAARG0 :
3335 case D3DTSS_ALPHAARG1 :
3336 case D3DTSS_ALPHAARG2 :
3338 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3339 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3341 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3342 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3343 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3344 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3346 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3347 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3348 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3349 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3355 case D3DTSS_ADDRESSU :
3356 case D3DTSS_ADDRESSV :
3357 case D3DTSS_ADDRESSW :
3359 GLint wrapParm = GL_REPEAT;
3361 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3362 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3363 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3364 #if defined(GL_VERSION_1_4)
3365 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3366 #elif defined(GL_ARB_texture_mirrored_repeat)
3367 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3369 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3371 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3373 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3374 wrapParm = GL_REPEAT;
3378 case D3DTSS_ADDRESSU:
3379 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3380 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3381 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3383 case D3DTSS_ADDRESSV:
3384 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3385 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3386 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3388 case D3DTSS_ADDRESSW:
3389 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3390 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3391 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3394 break; /** stupic compilator */
3399 case D3DTSS_BORDERCOLOR :
3402 D3DCOLORTOGLFLOAT4(Value, col);
3403 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3404 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3405 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3409 case D3DTSS_TEXCOORDINDEX :
3411 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3413 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3414 one flag, you can still specify an index value, which the system uses to
3415 determine the texture wrapping mode.
3416 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3417 means use the vertex position (camera-space) as the input texture coordinates
3418 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3419 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3420 to the TEXCOORDINDEX value */
3423 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3425 switch (Value & 0xFFFF0000) {
3426 case D3DTSS_TCI_PASSTHRU:
3427 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3428 glDisable(GL_TEXTURE_GEN_S);
3429 glDisable(GL_TEXTURE_GEN_T);
3430 glDisable(GL_TEXTURE_GEN_R);
3431 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3434 case D3DTSS_TCI_CAMERASPACEPOSITION:
3435 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3436 as the input texture coordinates for this stage's texture transformation. This
3437 equates roughly to EYE_LINEAR */
3439 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3440 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3441 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3442 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3443 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3445 glMatrixMode(GL_MODELVIEW);
3448 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3449 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3450 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3451 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3454 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3455 glEnable(GL_TEXTURE_GEN_S);
3456 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3457 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3458 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3459 glEnable(GL_TEXTURE_GEN_T);
3460 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3461 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3462 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3463 glEnable(GL_TEXTURE_GEN_R);
3464 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3465 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3466 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3470 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3471 case D3DTSS_TCI_CAMERASPACENORMAL:
3473 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3474 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3475 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3476 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3477 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3479 glMatrixMode(GL_MODELVIEW);
3482 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3483 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3484 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3485 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3488 glEnable(GL_TEXTURE_GEN_S);
3489 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3490 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3491 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3492 glEnable(GL_TEXTURE_GEN_T);
3493 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3494 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3495 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3496 glEnable(GL_TEXTURE_GEN_R);
3497 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3498 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3499 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3504 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3505 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3508 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3509 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3510 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3511 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3512 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3514 glMatrixMode(GL_MODELVIEW);
3517 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3518 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3519 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3520 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3523 glEnable(GL_TEXTURE_GEN_S);
3524 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3525 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3526 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3527 glEnable(GL_TEXTURE_GEN_T);
3528 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3529 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3530 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3531 glEnable(GL_TEXTURE_GEN_R);
3532 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3533 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3534 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3539 /* Unhandled types: */
3542 /* ? disable GL_TEXTURE_GEN_n ? */
3543 glDisable(GL_TEXTURE_GEN_S);
3544 glDisable(GL_TEXTURE_GEN_T);
3545 glDisable(GL_TEXTURE_GEN_R);
3546 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3553 case D3DTSS_BUMPENVMAT00 :
3554 case D3DTSS_BUMPENVMAT01 :
3555 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3557 case D3DTSS_BUMPENVMAT10 :
3558 case D3DTSS_BUMPENVMAT11 :
3559 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3562 case D3DTSS_TEXTURETRANSFORMFLAGS :
3563 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3566 case D3DTSS_MIPMAPLODBIAS :
3567 case D3DTSS_MAXMIPLEVEL :
3568 case D3DTSS_BUMPENVLSCALE :
3569 case D3DTSS_BUMPENVLOFFSET :
3570 case D3DTSS_RESULTARG :
3572 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3573 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3580 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3581 ICOM_THIS(IDirect3DDevice8Impl,iface);
3582 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3585 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3586 ICOM_THIS(IDirect3DDevice8Impl,iface);
3587 FIXME("(%p) : stub\n", This);
3590 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3591 ICOM_THIS(IDirect3DDevice8Impl,iface);
3592 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3593 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3594 if (PaletteNumber >= MAX_PALETTES) {
3595 return D3DERR_INVALIDCALL;
3597 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3600 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3601 ICOM_THIS(IDirect3DDevice8Impl,iface);
3602 if (PaletteNumber >= MAX_PALETTES) {
3603 return D3DERR_INVALIDCALL;
3605 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3606 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3607 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3610 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3611 ICOM_THIS(IDirect3DDevice8Impl,iface);
3612 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3613 if (PaletteNumber >= MAX_PALETTES) {
3614 return D3DERR_INVALIDCALL;
3616 This->currentPalette = PaletteNumber;
3618 #if defined(GL_EXT_paletted_texture)
3619 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3623 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3624 GL_RGBA, /* internal format */
3625 256, /* table size */
3626 GL_RGBA, /* table format */
3627 GL_UNSIGNED_BYTE, /* table type */
3628 This->palettes[PaletteNumber]);
3629 checkGLcall("glColorTableEXT");
3634 /* Delayed palette handling ... waiting for software emulation into preload code */
3639 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3640 ICOM_THIS(IDirect3DDevice8Impl,iface);
3641 *PaletteNumber = This->currentPalette;
3642 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3645 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3647 ICOM_THIS(IDirect3DDevice8Impl,iface);
3648 This->StateBlock->streamIsUP = FALSE;
3650 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3651 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3655 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3656 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3658 IDirect3DIndexBuffer8 *pIB;
3659 D3DINDEXBUFFER_DESC IdxBufDsc;
3661 ICOM_THIS(IDirect3DDevice8Impl,iface);
3662 pIB = This->StateBlock->pIndexData;
3663 This->StateBlock->streamIsUP = FALSE;
3665 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3666 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3667 minIndex, NumVertices, startIndex, primCount);
3669 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3670 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3676 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3681 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3682 ICOM_THIS(IDirect3DDevice8Impl,iface);
3684 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3685 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3687 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3689 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3690 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3691 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3692 This->StateBlock->streamIsUP = TRUE;
3693 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3694 This->StateBlock->stream_stride[0] = 0;
3695 This->StateBlock->stream_source[0] = NULL;
3697 /*stream zero settings set to null at end */
3700 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3701 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3702 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3703 UINT VertexStreamZeroStride) {
3705 ICOM_THIS(IDirect3DDevice8Impl,iface);
3706 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),
3707 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3709 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3710 if (IndexDataFormat == D3DFMT_INDEX16) {
3716 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3717 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3718 This->StateBlock->streamIsUP = TRUE;
3719 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3720 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3722 /*stream zero settings set to null at end */
3723 This->StateBlock->stream_source[0] = NULL;
3724 This->StateBlock->stream_stride[0] = 0;
3725 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3729 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3730 ICOM_THIS(IDirect3DDevice8Impl,iface);
3731 FIXME("(%p) : stub\n", This); return D3D_OK;
3733 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3734 ICOM_THIS(IDirect3DDevice8Impl,iface);
3735 IDirect3DVertexShaderImpl* object;
3736 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3740 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3741 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3742 return D3DERR_INVALIDCALL;
3744 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3745 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3746 return D3DERR_OUTOFVIDEOMEMORY;
3749 /** Create the Vertex Shader */
3750 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3751 /** TODO: check FAILED(res) */
3753 /** Create and Bind the Vertex Shader Declaration */
3754 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3755 /** TODO: check FAILED(res) */
3757 VertexShaders[i] = object;
3758 VertexShaderDeclarations[i] = attached_decl;
3759 *pHandle = VS_HIGHESTFIXEDFXF + i;
3760 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3764 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3765 ICOM_THIS(IDirect3DDevice8Impl,iface);
3767 This->UpdateStateBlock->VertexShader = Handle;
3768 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3769 This->UpdateStateBlock->Set.vertexShader = TRUE;
3771 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3772 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3773 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3774 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3775 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3776 } else { /* use a fvf, so desactivate the vshader decl */
3777 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3778 This->UpdateStateBlock->vertexShaderDecl = NULL;
3779 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3780 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3782 /* Handle recording of state blocks */
3783 if (This->isRecordingState) {
3784 TRACE("Recording... not performing anything\n");
3788 * TODO: merge HAL shaders context switching from prototype
3792 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3793 ICOM_THIS(IDirect3DDevice8Impl,iface);
3794 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3795 *pHandle = This->StateBlock->VertexShader;
3799 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3800 ICOM_THIS(IDirect3DDevice8Impl,iface);
3801 IDirect3DVertexShaderImpl* object;
3802 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3804 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3805 return D3DERR_INVALIDCALL;
3809 * Delete Vertex Shader
3811 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3812 if (NULL == object) {
3813 return D3DERR_INVALIDCALL;
3815 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3816 /* TODO: check validity of object */
3817 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3818 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3819 HeapFree(GetProcessHeap(), 0, (void *)object);
3820 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3823 * Delete Vertex Shader Declaration
3825 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3826 if (NULL == attached_decl) {
3827 return D3DERR_INVALIDCALL;
3829 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3830 /* TODO: check validity of object */
3831 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3832 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3833 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3838 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3839 ICOM_THIS(IDirect3DDevice8Impl,iface);
3841 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3842 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3843 return D3DERR_INVALIDCALL;
3845 if (NULL == pConstantData) {
3846 return D3DERR_INVALIDCALL;
3848 if (ConstantCount > 1) {
3849 FLOAT* f = (FLOAT*)pConstantData;
3851 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3852 for (i = 0; i < ConstantCount; ++i) {
3853 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3857 FLOAT* f = (FLOAT*) pConstantData;
3858 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3860 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3861 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3864 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3865 ICOM_THIS(IDirect3DDevice8Impl,iface);
3867 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3868 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3869 return D3DERR_INVALIDCALL;
3871 if (NULL == pConstantData) {
3872 return D3DERR_INVALIDCALL;
3874 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3877 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3878 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3879 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3881 attached_decl = VERTEX_SHADER_DECL(Handle);
3882 if (NULL == attached_decl) {
3883 return D3DERR_INVALIDCALL;
3885 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3887 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3888 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3889 IDirect3DVertexShaderImpl* object;
3891 object = VERTEX_SHADER(Handle);
3892 if (NULL == object) {
3893 return D3DERR_INVALIDCALL;
3895 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3898 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3899 ICOM_THIS(IDirect3DDevice8Impl,iface);
3900 IDirect3DIndexBuffer8 *oldIdxs;
3902 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3903 oldIdxs = This->StateBlock->pIndexData;
3905 This->UpdateStateBlock->Changed.Indices = TRUE;
3906 This->UpdateStateBlock->Set.Indices = TRUE;
3907 This->UpdateStateBlock->pIndexData = pIndexData;
3908 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3910 /* Handle recording of state blocks */
3911 if (This->isRecordingState) {
3912 TRACE("Recording... not performing anything\n");
3916 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3917 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3920 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3921 ICOM_THIS(IDirect3DDevice8Impl,iface);
3922 FIXME("(%p) : stub\n", This);
3924 *ppIndexData = This->StateBlock->pIndexData;
3925 /* up ref count on ppindexdata */
3926 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3927 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3931 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3932 ICOM_THIS(IDirect3DDevice8Impl,iface);
3933 IDirect3DPixelShaderImpl* object;
3937 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3938 if (NULL == pFunction || NULL == pHandle) {
3939 return D3DERR_INVALIDCALL;
3941 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3942 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3943 return D3DERR_OUTOFVIDEOMEMORY;
3946 /** Create the Pixel Shader */
3947 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3948 if (SUCCEEDED(res)) {
3949 PixelShaders[i] = object;
3950 *pHandle = VS_HIGHESTFIXEDFXF + i;
3953 *pHandle = 0xFFFFFFFF;
3956 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3957 ICOM_THIS(IDirect3DDevice8Impl,iface);
3959 This->UpdateStateBlock->PixelShader = Handle;
3960 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3961 This->UpdateStateBlock->Set.pixelShader = TRUE;
3963 /* Handle recording of state blocks */
3964 if (This->isRecordingState) {
3965 TRACE_(d3d_shader)("Recording... not performing anything\n");
3969 /* FIXME: Quieten when not being used */
3971 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3973 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3978 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3979 ICOM_THIS(IDirect3DDevice8Impl,iface);
3980 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3981 *pHandle = This->StateBlock->PixelShader;
3985 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3986 ICOM_THIS(IDirect3DDevice8Impl,iface);
3987 IDirect3DPixelShaderImpl* object;
3989 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3990 return D3DERR_INVALIDCALL;
3992 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3993 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3994 /* TODO: check validity of object before free */
3995 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3996 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3997 HeapFree(GetProcessHeap(), 0, (void *)object);
3998 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4003 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4004 ICOM_THIS(IDirect3DDevice8Impl,iface);
4006 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4007 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4008 return D3DERR_INVALIDCALL;
4010 if (NULL == pConstantData) {
4011 return D3DERR_INVALIDCALL;
4013 if (ConstantCount > 1) {
4014 FLOAT* f = (FLOAT*)pConstantData;
4016 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4017 for (i = 0; i < ConstantCount; ++i) {
4018 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4022 FLOAT* f = (FLOAT*) pConstantData;
4023 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4025 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4026 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4029 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4030 ICOM_THIS(IDirect3DDevice8Impl,iface);
4032 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4033 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4034 return D3DERR_INVALIDCALL;
4036 if (NULL == pConstantData) {
4037 return D3DERR_INVALIDCALL;
4039 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4042 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4043 IDirect3DPixelShaderImpl* object;
4045 object = PIXEL_SHADER(Handle);
4046 if (NULL == object) {
4047 return D3DERR_INVALIDCALL;
4049 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4051 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4052 ICOM_THIS(IDirect3DDevice8Impl,iface);
4053 FIXME("(%p) : stub\n", This); return D3D_OK;
4055 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4056 ICOM_THIS(IDirect3DDevice8Impl,iface);
4057 FIXME("(%p) : stub\n", This); return D3D_OK;
4059 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4060 ICOM_THIS(IDirect3DDevice8Impl,iface);
4061 FIXME("(%p) : stub\n", This); return D3D_OK;
4064 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4065 IDirect3DVertexBuffer8 *oldSrc;
4066 ICOM_THIS(IDirect3DDevice8Impl,iface);
4068 oldSrc = This->StateBlock->stream_source[StreamNumber];
4069 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4071 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4072 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4073 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4074 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4076 /* Handle recording of state blocks */
4077 if (This->isRecordingState) {
4078 TRACE("Recording... not performing anything\n");
4082 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4083 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4086 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4087 ICOM_THIS(IDirect3DDevice8Impl,iface);
4088 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4089 *pStream = This->StateBlock->stream_source[StreamNumber];
4090 *pStride = This->StateBlock->stream_stride[StreamNumber];
4091 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4096 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4098 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4099 IDirect3DDevice8Impl_QueryInterface,
4100 IDirect3DDevice8Impl_AddRef,
4101 IDirect3DDevice8Impl_Release,
4102 IDirect3DDevice8Impl_TestCooperativeLevel,
4103 IDirect3DDevice8Impl_GetAvailableTextureMem,
4104 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4105 IDirect3DDevice8Impl_GetDirect3D,
4106 IDirect3DDevice8Impl_GetDeviceCaps,
4107 IDirect3DDevice8Impl_GetDisplayMode,
4108 IDirect3DDevice8Impl_GetCreationParameters,
4109 IDirect3DDevice8Impl_SetCursorProperties,
4110 IDirect3DDevice8Impl_SetCursorPosition,
4111 IDirect3DDevice8Impl_ShowCursor,
4112 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4113 IDirect3DDevice8Impl_Reset,
4114 IDirect3DDevice8Impl_Present,
4115 IDirect3DDevice8Impl_GetBackBuffer,
4116 IDirect3DDevice8Impl_GetRasterStatus,
4117 IDirect3DDevice8Impl_SetGammaRamp,
4118 IDirect3DDevice8Impl_GetGammaRamp,
4119 IDirect3DDevice8Impl_CreateTexture,
4120 IDirect3DDevice8Impl_CreateVolumeTexture,
4121 IDirect3DDevice8Impl_CreateCubeTexture,
4122 IDirect3DDevice8Impl_CreateVertexBuffer,
4123 IDirect3DDevice8Impl_CreateIndexBuffer,
4124 IDirect3DDevice8Impl_CreateRenderTarget,
4125 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4126 IDirect3DDevice8Impl_CreateImageSurface,
4127 IDirect3DDevice8Impl_CopyRects,
4128 IDirect3DDevice8Impl_UpdateTexture,
4129 IDirect3DDevice8Impl_GetFrontBuffer,
4130 IDirect3DDevice8Impl_SetRenderTarget,
4131 IDirect3DDevice8Impl_GetRenderTarget,
4132 IDirect3DDevice8Impl_GetDepthStencilSurface,
4133 IDirect3DDevice8Impl_BeginScene,
4134 IDirect3DDevice8Impl_EndScene,
4135 IDirect3DDevice8Impl_Clear,
4136 IDirect3DDevice8Impl_SetTransform,
4137 IDirect3DDevice8Impl_GetTransform,
4138 IDirect3DDevice8Impl_MultiplyTransform,
4139 IDirect3DDevice8Impl_SetViewport,
4140 IDirect3DDevice8Impl_GetViewport,
4141 IDirect3DDevice8Impl_SetMaterial,
4142 IDirect3DDevice8Impl_GetMaterial,
4143 IDirect3DDevice8Impl_SetLight,
4144 IDirect3DDevice8Impl_GetLight,
4145 IDirect3DDevice8Impl_LightEnable,
4146 IDirect3DDevice8Impl_GetLightEnable,
4147 IDirect3DDevice8Impl_SetClipPlane,
4148 IDirect3DDevice8Impl_GetClipPlane,
4149 IDirect3DDevice8Impl_SetRenderState,
4150 IDirect3DDevice8Impl_GetRenderState,
4151 IDirect3DDevice8Impl_BeginStateBlock,
4152 IDirect3DDevice8Impl_EndStateBlock,
4153 IDirect3DDevice8Impl_ApplyStateBlock,
4154 IDirect3DDevice8Impl_CaptureStateBlock,
4155 IDirect3DDevice8Impl_DeleteStateBlock,
4156 IDirect3DDevice8Impl_CreateStateBlock,
4157 IDirect3DDevice8Impl_SetClipStatus,
4158 IDirect3DDevice8Impl_GetClipStatus,
4159 IDirect3DDevice8Impl_GetTexture,
4160 IDirect3DDevice8Impl_SetTexture,
4161 IDirect3DDevice8Impl_GetTextureStageState,
4162 IDirect3DDevice8Impl_SetTextureStageState,
4163 IDirect3DDevice8Impl_ValidateDevice,
4164 IDirect3DDevice8Impl_GetInfo,
4165 IDirect3DDevice8Impl_SetPaletteEntries,
4166 IDirect3DDevice8Impl_GetPaletteEntries,
4167 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4168 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4169 IDirect3DDevice8Impl_DrawPrimitive,
4170 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4171 IDirect3DDevice8Impl_DrawPrimitiveUP,
4172 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4173 IDirect3DDevice8Impl_ProcessVertices,
4174 IDirect3DDevice8Impl_CreateVertexShader,
4175 IDirect3DDevice8Impl_SetVertexShader,
4176 IDirect3DDevice8Impl_GetVertexShader,
4177 IDirect3DDevice8Impl_DeleteVertexShader,
4178 IDirect3DDevice8Impl_SetVertexShaderConstant,
4179 IDirect3DDevice8Impl_GetVertexShaderConstant,
4180 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4181 IDirect3DDevice8Impl_GetVertexShaderFunction,
4182 IDirect3DDevice8Impl_SetStreamSource,
4183 IDirect3DDevice8Impl_GetStreamSource,
4184 IDirect3DDevice8Impl_SetIndices,
4185 IDirect3DDevice8Impl_GetIndices,
4186 IDirect3DDevice8Impl_CreatePixelShader,
4187 IDirect3DDevice8Impl_SetPixelShader,
4188 IDirect3DDevice8Impl_GetPixelShader,
4189 IDirect3DDevice8Impl_DeletePixelShader,
4190 IDirect3DDevice8Impl_SetPixelShaderConstant,
4191 IDirect3DDevice8Impl_GetPixelShaderConstant,
4192 IDirect3DDevice8Impl_GetPixelShaderFunction,
4193 IDirect3DDevice8Impl_DrawRectPatch,
4194 IDirect3DDevice8Impl_DrawTriPatch,
4195 IDirect3DDevice8Impl_DeletePatch
4198 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4200 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4201 ICOM_THIS(IDirect3DDevice8Impl,iface);
4206 if (This->glCtx != This->render_ctx) {
4207 glXDestroyContext(This->display, This->render_ctx);
4208 This->render_ctx = This->glCtx;
4211 if (This->win != This->drawable) {
4212 glXDestroyPbuffer(This->display, This->drawable);
4213 This->drawable = This->win;
4222 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4223 IDirect3DSurface8* RenderSurface,
4224 IDirect3DSurface8* StencilSurface) {
4226 HRESULT ret = D3DERR_INVALIDCALL;
4228 * Currently only active for GLX >= 1.3
4229 * for others versions we'll have to use GLXPixmaps
4231 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4232 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4233 * so only check OpenGL version
4235 #if defined(GL_VERSION_1_3)
4236 GLXFBConfig* cfgs = NULL;
4240 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4241 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4242 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4243 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4244 IDirect3DSurface8Impl* tmp;
4246 ICOM_THIS(IDirect3DDevice8Impl,iface);
4248 #define PUSH1(att) attribs[nAttribs++] = (att);
4249 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4251 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4252 PUSH2(GLX_X_RENDERABLE, TRUE);
4253 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4255 switch (BackBufferFormat) {
4258 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4259 PUSH2(GLX_BUFFER_SIZE, 8);
4260 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4264 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4265 PUSH2(GLX_RED_SIZE, 3);
4266 PUSH2(GLX_GREEN_SIZE, 3);
4267 PUSH2(GLX_BLUE_SIZE, 2);
4270 case D3DFMT_A1R5G5B5:
4271 PUSH2(GLX_ALPHA_SIZE, 1);
4272 case D3DFMT_X1R5G5B5:
4273 PUSH2(GLX_RED_SIZE, 5);
4274 PUSH2(GLX_GREEN_SIZE, 5);
4275 PUSH2(GLX_BLUE_SIZE, 5);
4279 PUSH2(GLX_RED_SIZE, 5);
4280 PUSH2(GLX_GREEN_SIZE, 6);
4281 PUSH2(GLX_BLUE_SIZE, 5);
4284 case D3DFMT_A4R4G4B4:
4285 PUSH2(GLX_ALPHA_SIZE, 4);
4286 case D3DFMT_X4R4G4B4:
4287 PUSH2(GLX_RED_SIZE, 4);
4288 PUSH2(GLX_GREEN_SIZE, 4);
4289 PUSH2(GLX_BLUE_SIZE, 4);
4292 case D3DFMT_A8R8G8B8:
4293 PUSH2(GLX_ALPHA_SIZE, 8);
4295 case D3DFMT_X8R8G8B8:
4296 PUSH2(GLX_RED_SIZE, 8);
4297 PUSH2(GLX_GREEN_SIZE, 8);
4298 PUSH2(GLX_BLUE_SIZE, 8);
4305 switch (StencilBufferFormat) {
4306 case D3DFMT_D16_LOCKABLE:
4308 PUSH2(GLX_DEPTH_SIZE, 16);
4312 PUSH2(GLX_DEPTH_SIZE, 15);
4316 PUSH2(GLX_DEPTH_SIZE, 24);
4319 case D3DFMT_D24X4S4:
4320 PUSH2(GLX_DEPTH_SIZE, 24);
4321 PUSH2(GLX_STENCIL_SIZE, 4);
4325 PUSH2(GLX_DEPTH_SIZE, 24);
4326 PUSH2(GLX_STENCIL_SIZE, 8);
4330 PUSH2(GLX_DEPTH_SIZE, 32);
4341 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4345 for (i = 0; i < nCfgs; ++i) {
4346 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4350 if (NULL != This->renderTarget) {
4353 vcheckGLcall("glFlush");
4356 /** very very usefull debug code */
4357 glXSwapBuffers(This->display, This->drawable);
4358 printf("Hit Enter to get next frame ...\n");
4362 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4363 vcheckGLcall("glIntegerv");
4364 glReadBuffer(GL_BACK);
4365 vcheckGLcall("glReadBuffer");
4368 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4370 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4373 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4375 This->renderTarget->myDesc.Height - j - 1,
4376 This->renderTarget->myDesc.Width,
4378 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4379 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4380 This->renderTarget->allocatedMemory + j * pitch);
4381 vcheckGLcall("glReadPixels");
4384 glReadBuffer(prev_read);
4385 vcheckGLcall("glReadBuffer");
4388 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4389 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4391 PUSH2(GLX_PBUFFER_WIDTH, Width);
4392 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4394 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4396 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4397 if (NULL == This->render_ctx) {
4398 ERR("cannot create glxContext\n");
4402 glXSwapBuffers(This->display, This->drawable);
4403 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4404 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4406 checkGLcall("glXMakeContextCurrent");
4409 tmp = This->renderTarget;
4410 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4411 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4412 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4414 tmp = This->stencilBufferTarget;
4415 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4416 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4417 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4422 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));