2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
35 /*#define GL_GLEXT_PROTOTYPES*/
36 /*#undef GLX_GLXEXT_LEGACY*/
37 #include "d3d8_private.h"
39 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
42 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
43 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
44 WINE_DECLARE_DEBUG_CHANNEL(fps);
46 IDirect3DVertexShaderImpl* VertexShaders[64];
47 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
48 IDirect3DPixelShaderImpl* PixelShaders[64];
51 #ifdef FRAME_DEBUGGING
53 BOOL isDumpingFrames = FALSE;
58 * Utility functions or macros
60 #define conv_mat(mat,gl_mat) \
62 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
63 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
64 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
65 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
66 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
69 /* Apply the current values to the specified texture stage */
70 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
71 ICOM_THIS(IDirect3DDevice8Impl,iface);
74 BOOL changeTexture = TRUE;
76 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
77 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
82 /* Performance: For texture states where multiples effect the outcome, only bother
83 applying the last one as it will pick up all the other values */
84 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
85 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
86 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
87 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
88 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
89 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
93 /* Performance: If the texture states only impact settings for the texture unit
94 (compared to the texture object) then there is no need to reapply them. The
95 only time they need applying is the first time, since we cheat and put the
96 values into the stateblock without applying.
97 Per-texture unit: texture function (eg. combine), ops and args
99 texture generation settings
100 Note: Due to some special conditions there may be a need to do particular ones
101 of these, which is what the Flags allows */
103 case D3DTSS_TEXCOORDINDEX:
104 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
108 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
116 /* Performance: Only change to this texture if we have to */
118 /* Make appropriate texture active */
119 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
120 #if defined(GL_VERSION_1_3)
121 glActiveTexture(GL_TEXTURE0 + Stage);
123 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
125 checkGLcall("glActiveTextureARB");
126 } else if (Stage > 0) {
127 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
129 changeTexture = FALSE;
132 /* Now apply the change */
133 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
137 /* Note the D3DRS value applies to all textures, but GL has one
138 * per texture, so apply it now ready to be used!
140 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
141 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
142 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
144 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
147 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
148 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
151 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
152 ICOM_THIS(IDirect3DDevice8Impl,iface);
154 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
155 glMatrixMode(GL_MODELVIEW);
157 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
160 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
161 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
162 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
163 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
164 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
165 checkGLcall("glLightfv");
168 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
169 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
170 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
171 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
172 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
173 checkGLcall("glLightfv");
176 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
177 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
178 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
179 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
180 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
181 checkGLcall("glLightfv");
183 /* Attenuation - Are these right? guessing... */
184 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
185 checkGLcall("glLightf");
186 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
187 checkGLcall("glLightf");
189 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
190 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
191 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
192 checkGLcall("glLightf");
194 switch (lightInfo->OriginalParms.Type) {
197 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
198 checkGLcall("glLightfv");
199 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
200 checkGLcall("glLightf");
206 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
207 checkGLcall("glLightfv");
209 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
214 checkGLcall("glLightf");
218 case D3DLIGHT_DIRECTIONAL:
220 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
221 checkGLcall("glLightfv");
222 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
223 checkGLcall("glLightf");
224 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
225 checkGLcall("glLightf");
229 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
232 /* Restore the modelview matrix */
236 /* Setup this textures matrix */
237 static void set_texture_matrix(float *smat, DWORD flags)
241 glMatrixMode(GL_TEXTURE);
243 if (flags == D3DTTFF_DISABLE) {
245 checkGLcall("glLoadIdentity()");
249 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
250 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
251 checkGLcall("glLoadIdentity()");
255 memcpy(mat, smat, 16*sizeof(float));
257 switch (flags & ~D3DTTFF_PROJECTED) {
258 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
259 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
260 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
263 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
265 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
266 mat[1] = mat[5] = mat[9] = mat[13] = 0;
269 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
270 mat[2] = mat[6] = mat[10] = mat[14] = 0;
274 checkGLcall("glLoadMatrixf(mat)");
277 /* IDirect3D IUnknown parts follow: */
278 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
280 ICOM_THIS(IDirect3DDevice8Impl,iface);
282 if (IsEqualGUID(riid, &IID_IUnknown)
283 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
284 IDirect3DDevice8Impl_AddRef(iface);
289 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
290 return E_NOINTERFACE;
293 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
294 ICOM_THIS(IDirect3DDevice8Impl,iface);
295 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
296 return ++(This->ref);
299 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
300 ICOM_THIS(IDirect3DDevice8Impl,iface);
301 ULONG ref = --This->ref;
302 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
304 IDirect3DDevice8Impl_CleanRender(iface);
305 HeapFree(GetProcessHeap(), 0, This);
310 /* IDirect3DDevice Interface follow: */
311 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
312 ICOM_THIS(IDirect3DDevice8Impl,iface);
313 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
317 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
318 ICOM_THIS(IDirect3DDevice8Impl,iface);
319 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
321 * pretend we have 32MB of any type of memory queried.
323 return (1024*1024*32);
326 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
327 ICOM_THIS(IDirect3DDevice8Impl,iface);
328 FIXME("(%p) : stub\n", This); return D3D_OK;
330 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
331 ICOM_THIS(IDirect3DDevice8Impl,iface);
332 TRACE("(%p) : returning %p\n", This, This->direct3d8);
335 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
337 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
340 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
341 ICOM_THIS(IDirect3DDevice8Impl,iface);
342 FIXME("(%p) : stub, calling idirect3d for now\n", This);
343 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
346 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
351 ICOM_THIS(IDirect3DDevice8Impl,iface);
352 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
353 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
354 pMode->RefreshRate = 85; /*FIXME: How to identify? */
356 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
357 bpp = GetDeviceCaps(hdc, BITSPIXEL);
361 case 8: pMode->Format = D3DFMT_R8G8B8; break;
362 case 16: pMode->Format = D3DFMT_R5G6B5; break;
363 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
364 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
366 FIXME("Unrecognized display mode format\n");
367 pMode->Format = D3DFMT_UNKNOWN;
370 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
371 pMode->Format, debug_d3dformat(pMode->Format));
374 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
375 ICOM_THIS(IDirect3DDevice8Impl,iface);
376 TRACE("(%p) copying to %p\n", This, pParameters);
377 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
380 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
381 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
382 ICOM_THIS(IDirect3DDevice8Impl,iface);
383 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
385 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
386 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
387 return D3DERR_INVALIDCALL;
389 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
390 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
391 return D3DERR_INVALIDCALL;
394 This->xHotSpot = XHotSpot;
395 This->yHotSpot = YHotSpot;
398 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
399 ICOM_THIS(IDirect3DDevice8Impl,iface);
400 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
401 This->xScreenSpace = XScreenSpace;
402 This->yScreenSpace = YScreenSpace;
405 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
406 ICOM_THIS(IDirect3DDevice8Impl,iface);
407 TRACE("(%p) : visible(%d)\n", This, bShow);
408 This->bCursorVisible = bShow;
411 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
412 IDirect3DSwapChain8Impl* object;
413 ICOM_THIS(IDirect3DDevice8Impl,iface);
414 FIXME("(%p) : stub\n", This);
416 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
417 if (NULL == object) {
418 return D3DERR_OUTOFVIDEOMEMORY;
420 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
423 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
424 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
425 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
427 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
428 (pPresentationParameters->BackBufferHeight == 0))) {
431 GetClientRect(This->win_handle, &Rect);
433 if (pPresentationParameters->BackBufferWidth == 0) {
434 pPresentationParameters->BackBufferWidth = Rect.right;
435 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
437 if (pPresentationParameters->BackBufferHeight == 0) {
438 pPresentationParameters->BackBufferHeight = Rect.bottom;
439 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
443 /* Save the presentation parms now filled in correctly */
444 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
446 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
447 pPresentationParameters->BackBufferWidth,
448 pPresentationParameters->BackBufferHeight,
449 pPresentationParameters->BackBufferFormat,
450 pPresentationParameters->MultiSampleType,
452 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
454 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
455 pPresentationParameters->BackBufferWidth,
456 pPresentationParameters->BackBufferHeight,
457 pPresentationParameters->BackBufferFormat,
458 pPresentationParameters->MultiSampleType,
460 (LPDIRECT3DSURFACE8*) &object->backBuffer);
462 if (pPresentationParameters->EnableAutoDepthStencil) {
463 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
464 pPresentationParameters->BackBufferWidth,
465 pPresentationParameters->BackBufferHeight,
466 pPresentationParameters->AutoDepthStencilFormat,
468 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
470 object->depthStencilBuffer = NULL;
473 *pSwapChain = (IDirect3DSwapChain8*) object;
476 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
477 ICOM_THIS(IDirect3DDevice8Impl,iface);
478 FIXME("(%p) : stub\n", This); return D3D_OK;
480 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
481 ICOM_THIS(IDirect3DDevice8Impl,iface);
482 TRACE("(%p) : complete stub!\n", This);
486 glXSwapBuffers(This->display, This->drawable);
487 /* Dont call checkGLcall, as glGetError is not applicable here */
488 TRACE("glXSwapBuffers called, Starting new frame\n");
493 static long prev_time, frames;
495 DWORD time = GetTickCount();
497 /* every 1.5 seconds */
498 if (time - prev_time > 1500) {
499 TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
505 #if defined(FRAME_DEBUGGING)
507 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
510 FIXME("Enabling D3D Trace\n");
511 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
512 #if defined(SHOW_FRAME_MAKEUP)
513 FIXME("Singe Frame snapshots Starting\n");
514 isDumpingFrames = TRUE;
515 glClear(GL_COLOR_BUFFER_BIT);
518 #if defined(SINGLE_FRAME_DEBUGGING)
520 #if defined(SHOW_FRAME_MAKEUP)
521 FIXME("Singe Frame snapshots Finishing\n");
522 isDumpingFrames = FALSE;
524 FIXME("Singe Frame trace complete\n");
525 DeleteFileA("C:\\D3DTRACE");
526 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
532 #if defined(SHOW_FRAME_MAKEUP)
533 FIXME("Singe Frame snapshots Finishing\n");
534 isDumpingFrames = FALSE;
536 FIXME("Disabling D3D Trace\n");
537 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
547 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
548 ICOM_THIS(IDirect3DDevice8Impl,iface);
549 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
550 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
552 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
553 FIXME("Only one backBuffer currently supported\n");
554 return D3DERR_INVALIDCALL;
557 /* Note inc ref on returned surface */
558 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
562 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
563 ICOM_THIS(IDirect3DDevice8Impl,iface);
564 FIXME("(%p) : stub\n", This);
567 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
569 ICOM_THIS(IDirect3DDevice8Impl,iface);
571 FIXME("(%p) : pRamp@%p\n", This, pRamp);
572 hDC = GetDC(This->win_handle);
573 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
574 ReleaseDC(This->win_handle, hDC);
577 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
579 ICOM_THIS(IDirect3DDevice8Impl,iface);
581 FIXME("(%p) : pRamp@%p\n", This, pRamp);
582 hDC = GetDC(This->win_handle);
583 GetDeviceGammaRamp(hDC, pRamp);
584 ReleaseDC(This->win_handle, hDC);
587 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
588 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
589 IDirect3DTexture8Impl *object;
594 ICOM_THIS(IDirect3DDevice8Impl,iface);
596 /* Allocate the storage for the device */
597 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, debug_d3dformat(Format), Pool);
598 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
599 object->lpVtbl = &Direct3DTexture8_Vtbl;
600 object->Device = This;
601 object->ResourceType = D3DRTYPE_TEXTURE;
603 object->width = Width;
604 object->height = Height;
605 object->levels = Levels;
606 object->usage = Usage;
607 object->format = Format;
609 /* Calculate levels for mip mapping */
614 while (tmpW > 1 && tmpH > 1) {
615 tmpW = max(1, tmpW / 2);
616 tmpH = max(1, tmpH / 2);
619 TRACE("Calculated levels = %d\n", object->levels);
622 /* Generate all the surfaces */
625 for (i = 0; i < object->levels; i++)
627 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
628 object->surfaces[i]->Container = (IUnknown*) object;
629 object->surfaces[i]->myDesc.Usage = Usage;
630 object->surfaces[i]->myDesc.Pool = Pool;
632 * As written in msdn in IDirect3DTexture8::LockRect
633 * Textures created in D3DPOOL_DEFAULT are not lockable.
635 if (D3DPOOL_DEFAULT == Pool) {
636 object->surfaces[i]->lockable = FALSE;
639 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
640 tmpW = max(1, tmpW / 2);
641 tmpH = max(1, tmpH / 2);
644 *ppTexture = (LPDIRECT3DTEXTURE8) object;
645 TRACE("(%p) : Created texture %p\n", This, object);
648 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
649 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
650 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
652 IDirect3DVolumeTexture8Impl *object;
658 ICOM_THIS(IDirect3DDevice8Impl,iface);
660 /* Allocate the storage for it */
661 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
662 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
663 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
664 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
665 object->Device = This;
668 object->width = Width;
669 object->height = Height;
670 object->depth = Depth;
671 object->levels = Levels;
672 object->usage = Usage;
673 object->format = Format;
675 /* Calculate levels for mip mapping */
681 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
682 tmpW = max(1, tmpW / 2);
683 tmpH = max(1, tmpH / 2);
684 tmpD = max(1, tmpD / 2);
687 TRACE("Calculated levels = %d\n", object->levels);
690 /* Generate all the surfaces */
695 for (i = 0; i < object->levels; i++)
697 IDirect3DVolume8Impl* volume;
699 /* Create the volume - No entry point for this seperately?? */
700 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
701 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
703 volume->lpVtbl = &Direct3DVolume8_Vtbl;
704 volume->Device = This;
705 volume->ResourceType = D3DRTYPE_VOLUME;
706 volume->Container = (IUnknown*) object;
709 volume->myDesc.Width = Width;
710 volume->myDesc.Height = Height;
711 volume->myDesc.Depth = Depth;
712 volume->myDesc.Format = Format;
713 volume->myDesc.Type = D3DRTYPE_VOLUME;
714 volume->myDesc.Pool = Pool;
715 volume->myDesc.Usage = Usage;
716 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
717 /* Note: Volume textures cannot be dxtn, hence no need to check here */
718 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
719 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
721 volume->lockable = TRUE;
722 volume->locked = FALSE;
723 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
724 volume->Dirty = FALSE;
725 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
727 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
728 This, Width, Height, Depth, Format, debug_d3dformat(Format),
729 volume, volume->allocatedMemory, volume->myDesc.Size);
731 tmpW = max(1, tmpW / 2);
732 tmpH = max(1, tmpH / 2);
733 tmpD = max(1, tmpD / 2);
736 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
737 TRACE("(%p) : Created volume texture %p\n", This, object);
740 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
741 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
743 IDirect3DCubeTexture8Impl *object;
744 ICOM_THIS(IDirect3DDevice8Impl,iface);
748 /* Allocate the storage for it */
749 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
750 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
751 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
753 object->Device = This;
754 object->ResourceType = D3DRTYPE_CUBETEXTURE;
756 object->edgeLength = EdgeLength;
757 object->levels = Levels;
758 object->usage = Usage;
759 object->format = Format;
761 /* Calculate levels for mip mapping */
766 tmpW = max(1, tmpW / 2);
769 TRACE("Calculated levels = %d\n", object->levels);
772 /* Generate all the surfaces */
774 for (i = 0; i < object->levels; i++) {
775 /* Create the 6 faces */
776 for (j = 0; j < 6; j++) {
777 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
778 object->surfaces[j][i]->Container = (IUnknown*) object;
779 object->surfaces[j][i]->myDesc.Usage = Usage;
780 object->surfaces[j][i]->myDesc.Pool = Pool;
782 * As written in msdn in IDirect3DCubeTexture8::LockRect
783 * Textures created in D3DPOOL_DEFAULT are not lockable.
785 if (D3DPOOL_DEFAULT == Pool) {
786 object->surfaces[j][i]->lockable = FALSE;
789 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
791 tmpW = max(1, tmpW / 2);
794 TRACE("(%p) : Iface@%p\n", This, object);
795 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
798 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
799 IDirect3DVertexBuffer8Impl *object;
801 ICOM_THIS(IDirect3DDevice8Impl,iface);
803 /* Allocate the storage for the device */
804 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
805 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
806 object->Device = This;
807 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
809 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
810 object->currentDesc.Usage = Usage;
811 object->currentDesc.Pool = Pool;
812 object->currentDesc.FVF = FVF;
813 object->currentDesc.Size = Size;
815 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
817 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
821 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
822 IDirect3DIndexBuffer8Impl *object;
824 ICOM_THIS(IDirect3DDevice8Impl,iface);
825 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
827 /* Allocate the storage for the device */
828 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
829 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
830 object->Device = This;
832 object->ResourceType = D3DRTYPE_INDEXBUFFER;
834 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
835 object->currentDesc.Usage = Usage;
836 object->currentDesc.Pool = Pool;
837 object->currentDesc.Format = Format;
838 object->currentDesc.Size = Length;
840 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
842 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
844 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
848 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
849 IDirect3DSurface8Impl *object;
850 ICOM_THIS(IDirect3DDevice8Impl,iface);
852 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
853 if (NULL == object) {
855 return D3DERR_OUTOFVIDEOMEMORY;
857 *ppSurface = (LPDIRECT3DSURFACE8) object;
858 object->lpVtbl = &Direct3DSurface8_Vtbl;
859 object->Device = This;
860 object->ResourceType = D3DRTYPE_SURFACE;
861 object->Container = (IUnknown*) This;
864 object->myDesc.Width = Width;
865 object->myDesc.Height = Height;
866 object->myDesc.Format = Format;
867 object->myDesc.Type = D3DRTYPE_SURFACE;
868 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
869 object->myDesc.Pool = D3DPOOL_DEFAULT;
870 object->myDesc.MultiSampleType = MultiSample;
871 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
872 if (Format == D3DFMT_DXT1) {
873 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
875 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
877 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
878 object->lockable = Lockable;
879 object->locked = FALSE;
880 memset(&object->lockedRect, 0, sizeof(RECT));
881 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
883 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), Lockable, *ppSurface, object->allocatedMemory, object->myDesc.Size);
886 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
887 IDirect3DSurface8Impl *object;
889 ICOM_THIS(IDirect3DDevice8Impl,iface);
891 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
892 if (NULL == object) {
894 return D3DERR_OUTOFVIDEOMEMORY;
896 *ppSurface = (LPDIRECT3DSURFACE8) object;
897 object->lpVtbl = &Direct3DSurface8_Vtbl;
898 object->Device = This;
899 object->ResourceType = D3DRTYPE_SURFACE;
900 object->Container = (IUnknown*) This;
903 object->myDesc.Width = Width;
904 object->myDesc.Height = Height;
905 object->myDesc.Format = Format;
906 object->myDesc.Type = D3DRTYPE_SURFACE;
907 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
908 object->myDesc.Pool = D3DPOOL_DEFAULT;
909 object->myDesc.MultiSampleType = MultiSample;
910 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
911 if (Format == D3DFMT_DXT1) {
912 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
914 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
916 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
917 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
918 object->locked = FALSE;
919 memset(&object->lockedRect, 0, sizeof(RECT));
920 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
922 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
925 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
926 IDirect3DSurface8Impl *object;
928 ICOM_THIS(IDirect3DDevice8Impl,iface);
930 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
931 *ppSurface = (LPDIRECT3DSURFACE8) object;
932 object->lpVtbl = &Direct3DSurface8_Vtbl;
933 object->Device = This;
934 object->ResourceType = D3DRTYPE_SURFACE;
935 object->Container = (IUnknown*) This;
938 object->myDesc.Width = Width;
939 object->myDesc.Height = Height;
940 object->myDesc.Format = Format;
941 object->myDesc.Type = D3DRTYPE_SURFACE;
942 object->myDesc.Usage = 0;
943 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
944 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
945 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
946 it is based around 4x4 pixel blocks it requires padding, so allocate enough
948 if (Format == D3DFMT_DXT1) {
949 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
950 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
951 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
952 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
954 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
956 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
957 object->lockable = TRUE;
958 object->locked = FALSE;
959 memset(&object->lockedRect, 0, sizeof(RECT));
960 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
962 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->myDesc.Size);
965 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
966 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
967 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
970 IDirect3DBaseTexture8* texture = NULL;
973 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
974 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
976 ICOM_THIS(IDirect3DDevice8Impl,iface);
977 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
978 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
980 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
981 a sample and doesnt seem to break anything as far as I can tell */
982 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
983 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
984 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
985 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
986 rc = D3DERR_INVALIDCALL;
988 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
989 TRACE("Converting dest to same format as source, since dest was unknown\n");
990 dst->myDesc.Format = src->myDesc.Format;
992 /* Convert container as well */
993 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
994 if (SUCCEEDED(rc) && NULL != texture) {
995 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
996 /** Releasing texture after GetContainer */
997 IDirect3DBaseTexture8_Release(texture);
1002 /* Quick if complete copy ... */
1003 if (SUCCEEDED(rc)) {
1004 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1006 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1008 D3DLOCKED_RECT lrSrc;
1009 D3DLOCKED_RECT lrDst;
1010 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1011 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1012 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1014 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1016 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1017 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1018 TRACE("Unlocked src and dst\n");
1022 FIXME("Wanted to copy all surfaces but size not compatible\n");
1023 rc = D3DERR_INVALIDCALL;
1029 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1031 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1034 /* Copy rect by rect */
1035 for (i = 0; i < cRects; i++) {
1036 CONST RECT* r = &pSourceRectsArray[i];
1037 CONST POINT* p = &pDestPointsArray[i];
1040 D3DLOCKED_RECT lrSrc;
1041 D3DLOCKED_RECT lrDst;
1044 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1045 if (src->myDesc.Format == D3DFMT_DXT1) {
1046 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1048 copyperline = ((r->right - r->left) * bytesPerPixel);
1050 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1051 dest_rect.left = p->x;
1052 dest_rect.top = p->y;
1053 dest_rect.right = p->x + (r->right - r->left);
1054 dest_rect.bottom= p->y + (r->bottom - r->top);
1055 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1056 TRACE("Locked src and dst\n");
1058 /* Find where to start */
1059 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1060 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1062 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1063 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1064 TRACE("Unlocked src and dst\n");
1067 FIXME("Wanted to copy partial surfaces not implemented\n");
1068 rc = D3DERR_INVALIDCALL;
1075 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1076 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1077 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1078 D3DRESOURCETYPE srcType;
1079 D3DRESOURCETYPE dstType;
1081 ICOM_THIS(IDirect3DDevice8Impl,iface);
1082 TRACE("(%p) : first try\n", This);
1084 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1085 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1087 if (srcType != dstType) {
1088 return D3DERR_INVALIDCALL;
1090 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1091 return D3DERR_INVALIDCALL;
1093 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1094 return D3DERR_INVALIDCALL;
1096 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1097 /** Only copy Dirty textures */
1098 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1099 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1100 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1103 for (i = skipLevels; i < srcLevelCnt; ++i) {
1107 case D3DRTYPE_TEXTURE:
1109 IDirect3DSurface8* srcSur = NULL;
1110 IDirect3DSurface8* dstSur = NULL;
1111 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1112 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1114 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1115 about dst with less levels than the source?) */
1116 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1118 IDirect3DSurface8Impl_Release(srcSur);
1119 IDirect3DSurface8Impl_Release(dstSur);
1122 case D3DRTYPE_VOLUMETEXTURE:
1124 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1127 case D3DRTYPE_CUBETEXTURE:
1129 IDirect3DSurface8* srcSur = NULL;
1130 IDirect3DSurface8* dstSur = NULL;
1131 for (j = 0; j < 5; ++j) {
1132 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1133 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1134 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1135 IDirect3DSurface8Impl_Release(srcSur);
1136 IDirect3DSurface8Impl_Release(dstSur);
1144 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1149 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1151 D3DLOCKED_RECT lockedRect;
1156 ICOM_THIS(IDirect3DDevice8Impl,iface);
1158 FIXME("(%p) : see if behavior correct\n", This);
1160 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1161 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1162 return D3DERR_INVALIDCALL;
1165 wantedRect.left = 0;
1167 wantedRect.right = This->PresentParms.BackBufferWidth;
1168 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1170 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1172 ERR("(%p) : cannot lock surface\n", This);
1173 return D3DERR_INVALIDCALL;
1179 vcheckGLcall("glFlush");
1180 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1181 vcheckGLcall("glIntegerv");
1182 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1183 vcheckGLcall("glIntegerv");
1185 glReadBuffer(GL_FRONT);
1186 vcheckGLcall("glReadBuffer");
1187 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1188 vcheckGLcall("glPixelStorei");
1192 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1193 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1194 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1195 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1196 vcheckGLcall("glReadPixels");
1199 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1200 vcheckGLcall("glPixelStorei");
1201 glReadBuffer(prev_read);
1202 vcheckGLcall("glReadBuffer");
1206 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1209 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1212 ICOM_THIS(IDirect3DDevice8Impl,iface);
1214 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1215 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1219 IDirect3DDevice8Impl_CleanRender(iface);
1221 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1222 IDirect3DSurface8Impl* tmp;
1224 TRACE("retoring SetRenderTarget defaults\n");
1226 tmp = This->renderTarget;
1227 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1228 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1229 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1231 tmp = This->stencilBufferTarget;
1232 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1233 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1234 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1239 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1241 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1246 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1247 ICOM_THIS(IDirect3DDevice8Impl,iface);
1249 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1251 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1252 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1257 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1258 ICOM_THIS(IDirect3DDevice8Impl,iface);
1260 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1262 /* Note inc ref on returned surface */
1263 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1264 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1269 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1270 ICOM_THIS(IDirect3DDevice8Impl,iface);
1271 TRACE("(%p) : stub\n", This);
1274 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1275 IDirect3DBaseTexture8* cont = NULL;
1277 ICOM_THIS(IDirect3DDevice8Impl,iface);
1278 TRACE("(%p)\n", This);
1283 checkGLcall("glFlush");
1285 /* Useful for debugging sometimes!
1286 printf("Hit Enter ...\n");
1289 if (This->frontBuffer != This->renderTarget) {
1292 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1293 vcheckGLcall("glIntegerv");
1294 glReadBuffer(GL_BACK);
1295 vcheckGLcall("glReadBuffer");
1298 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1300 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1303 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1305 This->renderTarget->myDesc.Height - j - 1,
1306 This->renderTarget->myDesc.Width,
1308 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1309 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1310 This->renderTarget->allocatedMemory + j * pitch);
1311 vcheckGLcall("glReadPixels");
1314 glReadBuffer(prev_read);
1315 vcheckGLcall("glReadBuffer");
1318 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1319 if (SUCCEEDED(hr) && NULL != cont) {
1320 /** always dirtify for now. we must find a better way to see that surface have been modified */
1321 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1322 IDirect3DBaseTexture8_PreLoad(cont);
1323 IDirect3DBaseTexture8Impl_Release(cont);
1331 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1332 ICOM_THIS(IDirect3DDevice8Impl,iface);
1334 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1335 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1336 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1337 GLbitfield glMask = 0;
1338 GLboolean old_ztest;
1339 GLfloat old_z_clear_value;
1340 GLint old_stencil_clear_value;
1341 GLfloat old_color_clear_value[4];
1343 CONST D3DRECT* curRect;
1345 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1346 Count, pRects, Flags, Z, Stencil);
1349 glEnable(GL_SCISSOR_TEST);
1350 checkGLcall("glEnable GL_SCISSOR_TEST");
1351 if (Count > 0 && pRects) {
1357 /* Only set the values up once, as they are not changing */
1358 if (Flags & D3DCLEAR_STENCIL) {
1359 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1360 glClearStencil(Stencil);
1361 checkGLcall("glClearStencil");
1362 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1363 glStencilMask(0xFFFFFFFF);
1366 if (Flags & D3DCLEAR_ZBUFFER) {
1367 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1368 glDepthMask(GL_TRUE);
1369 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1371 checkGLcall("glClearDepth");
1372 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1375 if (Flags & D3DCLEAR_TARGET) {
1376 TRACE("Clearing screen with glClear to color %lx\n", Color);
1377 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1378 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1379 ((Color >> 8) & 0xFF) / 255.0f,
1380 ((Color >> 0) & 0xFF) / 255.0f,
1381 ((Color >> 24) & 0xFF) / 255.0f);
1382 checkGLcall("glClearColor");
1384 /* Clear ALL colors! */
1385 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1386 glMask = glMask | GL_COLOR_BUFFER_BIT;
1389 /* Now process each rect in turn */
1390 for (i = 0; i < Count || i == 0; i++) {
1393 /* Note gl uses lower left, width/height */
1394 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1395 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1396 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1397 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1398 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1399 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1400 checkGLcall("glScissor");
1402 glScissor(This->StateBlock->viewport.X,
1403 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1404 This->StateBlock->viewport.Width,
1405 This->StateBlock->viewport.Height);
1406 checkGLcall("glScissor");
1409 /* Clear the selected rectangle (or full screen) */
1411 checkGLcall("glClear");
1413 /* Step to the next rectangle */
1414 if (curRect) curRect = curRect + sizeof(D3DRECT);
1417 /* Restore the old values (why..?) */
1418 if (Flags & D3DCLEAR_STENCIL) {
1419 glClearStencil(old_stencil_clear_value);
1420 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1422 if (Flags & D3DCLEAR_ZBUFFER) {
1423 glDepthMask(old_ztest);
1424 glClearDepth(old_z_clear_value);
1426 if (Flags & D3DCLEAR_TARGET) {
1427 glClearColor(old_color_clear_value[0],
1428 old_color_clear_value[1],
1429 old_color_clear_value[2],
1430 old_color_clear_value[3]);
1431 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1432 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1433 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1434 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1437 glDisable(GL_SCISSOR_TEST);
1438 checkGLcall("glDisable");
1443 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1444 ICOM_THIS(IDirect3DDevice8Impl,iface);
1447 /* Most of this routine, comments included copied from ddraw tree initially: */
1448 TRACE("(%p) : State=%d\n", This, d3dts);
1450 /* Handle recording of state blocks */
1451 if (This->isRecordingState) {
1452 TRACE("Recording... not performing anything\n");
1453 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1454 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1455 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1460 * if the new matrix is the same as the current one,
1461 * we cut off any further processing. this seems to be a reasonable
1462 * optimization because as was noticed, some apps (warcraft3 for example)
1463 * tend towards setting the same matrix repeatedly for some dumb reason.
1465 * From here on we assume that the new matrix is different, wherever it matters
1468 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1469 TRACE("The app is setting the same matrix over again\n");
1472 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1476 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1477 where ViewMat = Camera space, WorldMat = world space.
1479 In OpenGL, camera and world space is combined into GL_MODELVIEW
1480 matrix. The Projection matrix stay projection matrix.
1483 /* Capture the times we can just ignore the change */
1484 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1485 This->modelview_valid = FALSE;
1488 } else if (d3dts == D3DTS_PROJECTION) {
1489 This->proj_valid = FALSE;
1492 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1493 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1494 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1498 /* Chances are we really are going to have to change a matrix */
1501 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1502 if (d3dts < GL_LIMITS(textures)) {
1503 int tex = d3dts - D3DTS_TEXTURE0;
1504 #if defined(GL_VERSION_1_3)
1505 glActiveTexture(GL_TEXTURE0 + tex);
1507 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1509 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1512 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1514 PLIGHTINFOEL *lightChain = NULL;
1515 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1516 This->modelview_valid = FALSE;
1517 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1518 glMatrixMode(GL_MODELVIEW);
1519 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1521 glLoadMatrixf((float *)lpmatrix);
1522 checkGLcall("glLoadMatrixf(...)");
1524 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1525 * NOTE: We have to reset the positions even if the light/plane is not currently
1526 * enabled, since the call to enable it will not reset the position.
1527 * NOTE2: Apparently texture transforms do NOT need reapplying
1531 lightChain = This->StateBlock->lights;
1532 while (lightChain && lightChain->glIndex != -1) {
1533 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1534 checkGLcall("glLightfv posn");
1535 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1536 checkGLcall("glLightfv dirn");
1537 lightChain = lightChain->next;
1539 /* Reset Clipping Planes if clipping is enabled */
1540 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1541 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1542 checkGLcall("glClipPlane");
1546 } else { /* What was requested!?? */
1547 WARN("invalid matrix specified: %i\n", d3dts);
1551 /* Release lock, all done */
1556 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1557 ICOM_THIS(IDirect3DDevice8Impl,iface);
1558 TRACE("(%p) : for State %d\n", This, State);
1559 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1563 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1564 D3DMATRIX *mat = NULL;
1567 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1568 but works regardless of recording being on.
1569 If this is found to be wrong, change to StateBlock. */
1570 ICOM_THIS(IDirect3DDevice8Impl,iface);
1571 TRACE("(%p) : For state %u\n", This, State);
1573 if (State < HIGHEST_TRANSFORMSTATE)
1575 mat = &This->UpdateStateBlock->transforms[State];
1577 FIXME("Unhandled transform state!!\n");
1580 /* Copied from ddraw code: */
1581 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);
1582 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);
1583 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);
1584 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);
1586 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);
1587 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);
1588 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);
1589 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);
1591 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);
1592 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);
1593 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);
1594 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);
1596 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);
1597 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);
1598 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);
1599 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);
1601 /* Apply change via set transform - will reapply to eg. lights this way */
1602 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1605 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1606 ICOM_THIS(IDirect3DDevice8Impl,iface);
1608 TRACE("(%p)\n", This);
1609 This->UpdateStateBlock->Changed.viewport = TRUE;
1610 This->UpdateStateBlock->Set.viewport = TRUE;
1611 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1613 /* Handle recording of state blocks */
1614 if (This->isRecordingState) {
1615 TRACE("Recording... not performing anything\n");
1621 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1622 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1624 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1625 checkGLcall("glDepthRange");
1626 /* Note: GL requires lower left, DirectX supplies upper left */
1627 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1628 pViewport->Width, pViewport->Height);
1629 checkGLcall("glViewport");
1636 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1637 ICOM_THIS(IDirect3DDevice8Impl,iface);
1638 TRACE("(%p)\n", This);
1639 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1643 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1644 ICOM_THIS(IDirect3DDevice8Impl,iface);
1646 This->UpdateStateBlock->Changed.material = TRUE;
1647 This->UpdateStateBlock->Set.material = TRUE;
1648 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1650 /* Handle recording of state blocks */
1651 if (This->isRecordingState) {
1652 TRACE("Recording... not performing anything\n");
1657 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1658 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1659 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1660 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1661 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1663 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1664 checkGLcall("glMaterialfv");
1665 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1666 checkGLcall("glMaterialfv");
1668 /* Only change material color if specular is enabled, otherwise it is set to black */
1669 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1670 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1671 checkGLcall("glMaterialfv");
1673 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1674 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1675 checkGLcall("glMaterialfv");
1677 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1678 checkGLcall("glMaterialfv");
1679 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1680 checkGLcall("glMaterialf");
1685 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1686 ICOM_THIS(IDirect3DDevice8Impl,iface);
1687 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1688 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1689 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1690 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1691 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1692 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1696 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1697 you can reference any indexes you want as long as that number max are enabled are any
1698 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1699 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1700 but when recording, just build a chain pretty much of commands to be replayed. */
1702 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1704 PLIGHTINFOEL *object, *temp;
1706 ICOM_THIS(IDirect3DDevice8Impl,iface);
1707 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1709 /* If recording state block, just add to end of lights chain */
1710 if (This->isRecordingState) {
1711 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1712 if (NULL == object) {
1713 return D3DERR_OUTOFVIDEOMEMORY;
1715 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1716 object->OriginalIndex = Index;
1717 object->glIndex = -1;
1718 object->changed = TRUE;
1720 /* Add to the END of the chain of lights changes to be replayed */
1721 if (This->UpdateStateBlock->lights == NULL) {
1722 This->UpdateStateBlock->lights = object;
1724 temp = This->UpdateStateBlock->lights;
1725 while (temp->next != NULL) temp=temp->next;
1726 temp->next = object;
1728 TRACE("Recording... not performing anything more\n");
1732 /* Ok, not recording any longer so do real work */
1733 object = This->StateBlock->lights;
1734 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1736 /* If we didnt find it in the list of lights, time to add it */
1737 if (object == NULL) {
1738 PLIGHTINFOEL *insertAt,*prevPos;
1740 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1741 if (NULL == object) {
1742 return D3DERR_OUTOFVIDEOMEMORY;
1744 object->OriginalIndex = Index;
1745 object->glIndex = -1;
1747 /* Add it to the front of list with the idea that lights will be changed as needed
1748 BUT after any lights currently assigned GL indexes */
1749 insertAt = This->StateBlock->lights;
1751 while (insertAt != NULL && insertAt->glIndex != -1) {
1753 insertAt = insertAt->next;
1756 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1757 This->StateBlock->lights = object;
1758 } else if (insertAt == NULL) { /* End of list */
1759 prevPos->next = object;
1760 object->prev = prevPos;
1761 } else { /* Middle of chain */
1762 if (prevPos == NULL) {
1763 This->StateBlock->lights = object;
1765 prevPos->next = object;
1767 object->prev = prevPos;
1768 object->next = insertAt;
1769 insertAt->prev = object;
1773 /* Initialze the object */
1774 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,
1775 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1776 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1777 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1778 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1779 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1780 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1782 /* Save away the information */
1783 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1785 switch (pLight->Type) {
1786 case D3DLIGHT_POINT:
1788 object->lightPosn[0] = pLight->Position.x;
1789 object->lightPosn[1] = pLight->Position.y;
1790 object->lightPosn[2] = pLight->Position.z;
1791 object->lightPosn[3] = 1.0f;
1792 object->cutoff = 180.0f;
1798 object->lightPosn[0] = pLight->Position.x;
1799 object->lightPosn[1] = pLight->Position.y;
1800 object->lightPosn[2] = pLight->Position.z;
1801 object->lightPosn[3] = 1.0;
1804 object->lightDirn[0] = pLight->Direction.x;
1805 object->lightDirn[1] = pLight->Direction.y;
1806 object->lightDirn[2] = pLight->Direction.z;
1807 object->lightDirn[3] = 1.0;
1810 * opengl-ish and d3d-ish spot lights use too different models for the
1811 * light "intensity" as a function of the angle towards the main light direction,
1812 * so we only can approximate very roughly.
1813 * however spot lights are rather rarely used in games (if ever used at all).
1814 * furthermore if still used, probably nobody pays attention to such details.
1816 if (pLight->Falloff == 0) {
1819 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1821 if (rho < 0.0001) rho = 0.0001f;
1822 object->exponent = -0.3/log(cos(rho/2));
1823 object->cutoff = pLight->Phi*90/M_PI;
1828 case D3DLIGHT_DIRECTIONAL:
1830 object->lightPosn[0] = -pLight->Direction.x;
1831 object->lightPosn[1] = -pLight->Direction.y;
1832 object->lightPosn[2] = -pLight->Direction.z;
1833 object->lightPosn[3] = 0.0;
1834 object->exponent = 0.0f;
1835 object->cutoff = 180.0f;
1839 FIXME("Unrecognized light type %d\n", pLight->Type);
1842 /* Update the live definitions if the light is currently assigned a glIndex */
1843 if (object->glIndex != -1) {
1844 setup_light(iface, object->glIndex, object);
1848 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1849 PLIGHTINFOEL *lightInfo = NULL;
1850 ICOM_THIS(IDirect3DDevice8Impl,iface);
1851 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1853 /* Locate the light in the live lights */
1854 lightInfo = This->StateBlock->lights;
1855 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1857 if (lightInfo == NULL) {
1858 TRACE("Light information requested but light not defined\n");
1859 return D3DERR_INVALIDCALL;
1862 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1865 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1866 PLIGHTINFOEL *lightInfo = NULL;
1867 ICOM_THIS(IDirect3DDevice8Impl,iface);
1868 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1870 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1871 if (This->isRecordingState) {
1872 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1873 if (NULL == lightInfo) {
1874 return D3DERR_OUTOFVIDEOMEMORY;
1876 lightInfo->OriginalIndex = Index;
1877 lightInfo->glIndex = -1;
1878 lightInfo->enabledChanged = TRUE;
1880 /* Add to the END of the chain of lights changes to be replayed */
1881 if (This->UpdateStateBlock->lights == NULL) {
1882 This->UpdateStateBlock->lights = lightInfo;
1884 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1885 while (temp->next != NULL) temp=temp->next;
1886 temp->next = lightInfo;
1888 TRACE("Recording... not performing anything more\n");
1892 /* Not recording... So, locate the light in the live lights */
1893 lightInfo = This->StateBlock->lights;
1894 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1896 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1897 if (lightInfo == NULL) {
1898 D3DLIGHT8 lightParms;
1899 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1900 wait until someone confirms it seems to work! */
1901 TRACE("Light enabled requested but light not defined, so defining one!\n");
1902 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1903 lightParms.Diffuse.r = 1.0;
1904 lightParms.Diffuse.g = 1.0;
1905 lightParms.Diffuse.b = 1.0;
1906 lightParms.Diffuse.a = 0.0;
1907 lightParms.Specular.r = 0.0;
1908 lightParms.Specular.g = 0.0;
1909 lightParms.Specular.b = 0.0;
1910 lightParms.Specular.a = 0.0;
1911 lightParms.Ambient.r = 0.0;
1912 lightParms.Ambient.g = 0.0;
1913 lightParms.Ambient.b = 0.0;
1914 lightParms.Ambient.a = 0.0;
1915 lightParms.Position.x = 0.0;
1916 lightParms.Position.y = 0.0;
1917 lightParms.Position.z = 0.0;
1918 lightParms.Direction.x = 0.0;
1919 lightParms.Direction.y = 0.0;
1920 lightParms.Direction.z = 1.0;
1921 lightParms.Range = 0.0;
1922 lightParms.Falloff = 0.0;
1923 lightParms.Attenuation0 = 0.0;
1924 lightParms.Attenuation1 = 0.0;
1925 lightParms.Attenuation2 = 0.0;
1926 lightParms.Theta = 0.0;
1927 lightParms.Phi = 0.0;
1928 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1930 /* Search for it again! Should be fairly quick as near head of list */
1931 lightInfo = This->StateBlock->lights;
1932 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1933 if (lightInfo == NULL) {
1934 FIXME("Adding default lights has failed dismally\n");
1935 return D3DERR_INVALIDCALL;
1939 /* OK, we now have a light... */
1940 if (Enable == FALSE) {
1942 /* If we are disabling it, check it was enabled, and
1943 still only do something if it has assigned a glIndex (which it should have!) */
1944 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1945 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1947 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1948 checkGLcall("glDisable GL_LIGHT0+Index");
1951 TRACE("Nothing to do as light was not enabled\n");
1953 lightInfo->lightEnabled = FALSE;
1956 /* We are enabling it. If it is enabled, its really simple */
1957 if (lightInfo->lightEnabled == TRUE) {
1959 TRACE("Nothing to do as light was enabled\n");
1961 /* If it already has a glIndex, its still simple */
1962 } else if (lightInfo->glIndex != -1) {
1963 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1964 lightInfo->lightEnabled = TRUE;
1966 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1967 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1970 /* Otherwise got to find space - lights are ordered gl indexes first */
1972 PLIGHTINFOEL *bsf = NULL;
1973 PLIGHTINFOEL *pos = This->StateBlock->lights;
1974 PLIGHTINFOEL *prev = NULL;
1978 /* Try to minimize changes as much as possible */
1979 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1981 /* Try to remember which index can be replaced if necessary */
1982 if (bsf==NULL && pos->lightEnabled == FALSE) {
1983 /* Found a light we can replace, save as best replacement */
1987 /* Step to next space */
1993 /* If we have too many active lights, fail the call */
1994 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1995 FIXME("Program requests too many concurrent lights\n");
1996 return D3DERR_INVALIDCALL;
1998 /* If we have allocated all lights, but not all are enabled,
1999 reuse one which is not enabled */
2000 } else if (Index == This->maxConcurrentLights) {
2001 /* use bsf - Simply swap the new light and the BSF one */
2002 PLIGHTINFOEL *bsfNext = bsf->next;
2003 PLIGHTINFOEL *bsfPrev = bsf->prev;
2006 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2007 if (bsf->prev != NULL) {
2008 bsf->prev->next = lightInfo;
2010 This->StateBlock->lights = lightInfo;
2013 /* If not side by side, lots of chains to update */
2014 if (bsf->next != lightInfo) {
2015 lightInfo->prev->next = bsf;
2016 bsf->next->prev = lightInfo;
2017 bsf->next = lightInfo->next;
2018 bsf->prev = lightInfo->prev;
2019 lightInfo->next = bsfNext;
2020 lightInfo->prev = bsfPrev;
2024 bsf->prev = lightInfo;
2025 bsf->next = lightInfo->next;
2026 lightInfo->next = bsf;
2027 lightInfo->prev = bsfPrev;
2032 glIndex = bsf->glIndex;
2034 lightInfo->glIndex = glIndex;
2035 lightInfo->lightEnabled = TRUE;
2037 /* Finally set up the light in gl itself */
2038 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2040 setup_light(iface, glIndex, lightInfo);
2041 glEnable(GL_LIGHT0 + glIndex);
2042 checkGLcall("glEnable GL_LIGHT0 new setup");
2045 /* If we reached the end of the allocated lights, with space in the
2046 gl lights, setup a new light */
2047 } else if (pos->glIndex == -1) {
2049 /* We reached the end of the allocated gl lights, so already
2050 know the index of the next one! */
2052 lightInfo->glIndex = glIndex;
2053 lightInfo->lightEnabled = TRUE;
2055 /* In an ideal world, its already in the right place */
2056 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2057 /* No need to move it */
2059 /* Remove this light from the list */
2060 lightInfo->prev->next = lightInfo->next;
2061 if (lightInfo->next != NULL) {
2062 lightInfo->next->prev = lightInfo->prev;
2065 /* Add in at appropriate place (inbetween prev and pos) */
2066 lightInfo->prev = prev;
2067 lightInfo->next = pos;
2069 This->StateBlock->lights = lightInfo;
2071 prev->next = lightInfo;
2074 pos->prev = lightInfo;
2078 /* Finally set up the light in gl itself */
2079 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2081 setup_light(iface, glIndex, lightInfo);
2082 glEnable(GL_LIGHT0 + glIndex);
2083 checkGLcall("glEnable GL_LIGHT0 new setup");
2091 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2093 PLIGHTINFOEL *lightInfo = NULL;
2094 ICOM_THIS(IDirect3DDevice8Impl,iface);
2095 TRACE("(%p) : for idx(%ld)\n", This, Index);
2097 /* Locate the light in the live lights */
2098 lightInfo = This->StateBlock->lights;
2099 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2101 if (lightInfo == NULL) {
2102 TRACE("Light enabled state requested but light not defined\n");
2103 return D3DERR_INVALIDCALL;
2105 *pEnable = lightInfo->lightEnabled;
2108 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2109 ICOM_THIS(IDirect3DDevice8Impl,iface);
2110 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2112 /* Validate Index */
2113 if (Index >= GL_LIMITS(clipplanes)) {
2114 TRACE("Application has requested clipplane this device doesnt support\n");
2115 return D3DERR_INVALIDCALL;
2118 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2119 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2120 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2121 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2122 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2123 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2125 /* Handle recording of state blocks */
2126 if (This->isRecordingState) {
2127 TRACE("Recording... not performing anything\n");
2135 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2136 glMatrixMode(GL_MODELVIEW);
2138 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2140 TRACE("Clipplane [%f,%f,%f,%f]\n",
2141 This->UpdateStateBlock->clipplane[Index][0],
2142 This->UpdateStateBlock->clipplane[Index][1],
2143 This->UpdateStateBlock->clipplane[Index][2],
2144 This->UpdateStateBlock->clipplane[Index][3]);
2145 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2146 checkGLcall("glClipPlane");
2154 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2155 ICOM_THIS(IDirect3DDevice8Impl,iface);
2156 TRACE("(%p) : for idx %ld\n", This, Index);
2158 /* Validate Index */
2159 if (Index >= GL_LIMITS(clipplanes)) {
2160 TRACE("Application has requested clipplane this device doesnt support\n");
2161 return D3DERR_INVALIDCALL;
2164 pPlane[0] = This->StateBlock->clipplane[Index][0];
2165 pPlane[1] = This->StateBlock->clipplane[Index][1];
2166 pPlane[2] = This->StateBlock->clipplane[Index][2];
2167 pPlane[3] = This->StateBlock->clipplane[Index][3];
2170 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2171 ICOM_THIS(IDirect3DDevice8Impl,iface);
2172 DWORD OldValue = This->StateBlock->renderstate[State];
2174 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2175 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2176 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2177 This->UpdateStateBlock->renderstate[State] = Value;
2179 /* Handle recording of state blocks */
2180 if (This->isRecordingState) {
2181 TRACE("Recording... not performing anything\n");
2188 case D3DRS_FILLMODE :
2189 switch ((D3DFILLMODE) Value) {
2190 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2191 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2192 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2194 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2196 checkGLcall("glPolygonMode (fillmode)");
2199 case D3DRS_LIGHTING :
2201 glEnable(GL_LIGHTING);
2202 checkGLcall("glEnable GL_LIGHTING");
2204 glDisable(GL_LIGHTING);
2205 checkGLcall("glDisable GL_LIGHTING");
2209 case D3DRS_ZENABLE :
2210 switch ((D3DZBUFFERTYPE) Value) {
2212 glDisable(GL_DEPTH_TEST);
2213 checkGLcall("glDisable GL_DEPTH_TEST");
2216 glEnable(GL_DEPTH_TEST);
2217 checkGLcall("glEnable GL_DEPTH_TEST");
2222 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2226 case D3DRS_CULLMODE :
2228 /* If we are culling "back faces with clockwise vertices" then
2229 set front faces to be counter clockwise and enable culling
2231 switch ((D3DCULL) Value) {
2233 glDisable(GL_CULL_FACE);
2234 checkGLcall("glDisable GL_CULL_FACE");
2237 glEnable(GL_CULL_FACE);
2238 checkGLcall("glEnable GL_CULL_FACE");
2239 glFrontFace(GL_CCW);
2240 checkGLcall("glFrontFace GL_CCW");
2241 glCullFace(GL_BACK);
2244 glEnable(GL_CULL_FACE);
2245 checkGLcall("glEnable GL_CULL_FACE");
2247 checkGLcall("glFrontFace GL_CW");
2248 glCullFace(GL_BACK);
2251 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2255 case D3DRS_SHADEMODE :
2256 switch ((D3DSHADEMODE) Value) {
2258 glShadeModel(GL_FLAT);
2259 checkGLcall("glShadeModel");
2261 case D3DSHADE_GOURAUD:
2262 glShadeModel(GL_SMOOTH);
2263 checkGLcall("glShadeModel");
2265 case D3DSHADE_PHONG:
2266 FIXME("D3DSHADE_PHONG isnt supported?\n");
2269 return D3DERR_INVALIDCALL;
2271 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2275 case D3DRS_DITHERENABLE :
2277 glEnable(GL_DITHER);
2278 checkGLcall("glEnable GL_DITHER");
2280 glDisable(GL_DITHER);
2281 checkGLcall("glDisable GL_DITHER");
2285 case D3DRS_ZWRITEENABLE :
2288 checkGLcall("glDepthMask");
2291 checkGLcall("glDepthMask");
2297 int glParm = GL_LESS;
2299 switch ((D3DCMPFUNC) Value) {
2300 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2301 case D3DCMP_LESS: glParm=GL_LESS; break;
2302 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2303 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2304 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2305 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2306 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2307 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2309 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2311 glDepthFunc(glParm);
2312 checkGLcall("glDepthFunc");
2316 case D3DRS_AMBIENT :
2319 D3DCOLORTOGLFLOAT4(Value, col);
2320 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2321 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2322 checkGLcall("glLightModel for MODEL_AMBIENT");
2327 case D3DRS_ALPHABLENDENABLE :
2330 checkGLcall("glEnable GL_BLEND");
2332 glDisable(GL_BLEND);
2333 checkGLcall("glDisable GL_BLEND");
2337 case D3DRS_SRCBLEND :
2338 case D3DRS_DESTBLEND :
2340 int newVal = GL_ZERO;
2342 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2343 case D3DBLEND_ONE : newVal = GL_ONE; break;
2344 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2345 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2346 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2347 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2348 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2349 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2350 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2351 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2352 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2354 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2355 This->srcBlend = newVal;
2356 This->dstBlend = newVal;
2359 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2360 This->srcBlend = newVal;
2361 This->dstBlend = newVal;
2364 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2367 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2368 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2369 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2370 glBlendFunc(This->srcBlend, This->dstBlend);
2372 checkGLcall("glBlendFunc");
2376 case D3DRS_ALPHATESTENABLE :
2378 glEnable(GL_ALPHA_TEST);
2379 checkGLcall("glEnable GL_ALPHA_TEST");
2381 glDisable(GL_ALPHA_TEST);
2382 checkGLcall("glDisable GL_ALPHA_TEST");
2386 case D3DRS_ALPHAFUNC :
2388 int glParm = GL_LESS;
2389 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2391 switch ((D3DCMPFUNC) Value) {
2392 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2393 case D3DCMP_LESS: glParm = GL_LESS; break;
2394 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2395 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2396 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2397 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2398 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2399 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2401 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2403 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2404 glAlphaFunc(glParm, ref);
2405 This->alphafunc = glParm;
2406 checkGLcall("glAlphaFunc");
2410 case D3DRS_ALPHAREF :
2412 int glParm = This->alphafunc;
2415 ref = ((float) Value) / 255.0f;
2416 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2417 glAlphaFunc(glParm, ref);
2418 checkGLcall("glAlphaFunc");
2422 case D3DRS_CLIPPLANEENABLE :
2423 case D3DRS_CLIPPING :
2425 /* Ensure we only do the changed clip planes */
2426 DWORD enable = 0xFFFFFFFF;
2427 DWORD disable = 0x00000000;
2429 /* If enabling / disabling all */
2430 if (State == D3DRS_CLIPPING) {
2432 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2435 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2439 enable = Value & ~OldValue;
2440 disable = ~Value & OldValue;
2443 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2444 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2445 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2446 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2447 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2448 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2450 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2451 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2452 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2453 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2454 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2455 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2459 case D3DRS_BLENDOP :
2461 int glParm = GL_FUNC_ADD;
2463 switch ((D3DBLENDOP) Value) {
2464 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2465 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2466 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2467 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2468 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2470 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2472 TRACE("glBlendEquation(%x)\n", glParm);
2473 glBlendEquation(glParm);
2474 checkGLcall("glBlendEquation");
2478 case D3DRS_TEXTUREFACTOR :
2482 /* Note the texture color applies to all textures whereas
2483 GL_TEXTURE_ENV_COLOR applies to active only */
2485 D3DCOLORTOGLFLOAT4(Value, col);
2486 /* Set the default alpha blend color */
2487 glBlendColor(col[0], col[1], col[2], col[3]);
2488 checkGLcall("glBlendColor");
2490 /* And now the default texture color as well */
2491 for (i = 0; i < GL_LIMITS(textures); i++) {
2493 /* Note the D3DRS value applies to all textures, but GL has one
2494 per texture, so apply it now ready to be used! */
2495 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2496 #if defined(GL_VERSION_1_3)
2497 glActiveTexture(GL_TEXTURE0 + i);
2499 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2501 checkGLcall("Activate texture.. to update const color");
2503 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2506 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2507 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2512 case D3DRS_SPECULARENABLE :
2514 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2515 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2516 specular color. This is wrong:
2517 Separate specular color means the specular colour is maintained separately, whereas
2518 single color means it is merged in. However in both cases they are being used to
2520 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2521 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2525 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2526 checkGLcall("glMaterialfv");
2527 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2528 glEnable(GL_COLOR_SUM_EXT);
2530 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2532 checkGLcall("glEnable(GL_COLOR_SUM)");
2534 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2536 /* for the case of enabled lighting: */
2537 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2538 checkGLcall("glMaterialfv");
2540 /* for the case of disabled lighting: */
2541 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2542 glDisable(GL_COLOR_SUM_EXT);
2544 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2546 checkGLcall("glDisable(GL_COLOR_SUM)");
2551 case D3DRS_STENCILENABLE :
2553 glEnable(GL_STENCIL_TEST);
2554 checkGLcall("glEnable GL_STENCIL_TEST");
2556 glDisable(GL_STENCIL_TEST);
2557 checkGLcall("glDisable GL_STENCIL_TEST");
2561 case D3DRS_STENCILFUNC :
2563 int glParm = GL_ALWAYS;
2564 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2565 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2567 switch ((D3DCMPFUNC) Value) {
2568 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2569 case D3DCMP_LESS: glParm=GL_LESS; break;
2570 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2571 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2572 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2573 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2574 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2575 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2577 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2579 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2580 This->stencilfunc = glParm;
2581 glStencilFunc(glParm, ref, mask);
2582 checkGLcall("glStencilFunc");
2586 case D3DRS_STENCILREF :
2588 int glParm = This->stencilfunc;
2590 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2593 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2594 glStencilFunc(glParm, ref, mask);
2595 checkGLcall("glStencilFunc");
2599 case D3DRS_STENCILMASK :
2601 int glParm = This->stencilfunc;
2602 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2603 GLuint mask = Value;
2605 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2606 glStencilFunc(glParm, ref, mask);
2607 checkGLcall("glStencilFunc");
2611 case D3DRS_STENCILFAIL :
2617 fail = StencilOp(Value);
2618 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2619 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2620 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2621 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2623 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2624 glStencilOp(fail, zfail, zpass);
2625 checkGLcall("glStencilOp(fail, zfail, zpass);");
2628 case D3DRS_STENCILZFAIL :
2634 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2635 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2636 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2637 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2638 zfail = StencilOp(Value);
2640 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2641 glStencilOp(fail, zfail, zpass);
2642 checkGLcall("glStencilOp(fail, zfail, zpass);");
2645 case D3DRS_STENCILPASS :
2651 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2652 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2653 zpass = StencilOp(Value);
2654 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2655 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2657 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2658 glStencilOp(fail, zfail, zpass);
2659 checkGLcall("glStencilOp(fail, zfail, zpass);");
2663 case D3DRS_STENCILWRITEMASK :
2665 glStencilMask(Value);
2666 TRACE("glStencilMask(%lu)\n", Value);
2667 checkGLcall("glStencilMask");
2671 case D3DRS_FOGENABLE :
2673 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2675 checkGLcall("glEnable GL_FOG");
2678 checkGLcall("glDisable GL_FOG");
2683 case D3DRS_FOGCOLOR :
2686 D3DCOLORTOGLFLOAT4(Value, col);
2687 /* Set the default alpha blend color */
2688 glFogfv(GL_FOG_COLOR, &col[0]);
2689 checkGLcall("glFog GL_FOG_COLOR");
2693 case D3DRS_FOGTABLEMODE :
2696 case D3DFOG_NONE: /* I don't know what to do here */ break;
2697 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2698 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2699 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2701 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2706 case D3DRS_FOGSTART :
2708 float *f = (float*) &Value;
2709 glFogfv(GL_FOG_START, f);
2710 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2711 TRACE("Fog Start == %f\n", *f);
2717 float *f = (float*) &Value;
2718 glFogfv(GL_FOG_END, f);
2719 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2720 TRACE("Fog End == %f\n", *f);
2724 case D3DRS_FOGDENSITY :
2726 float *f = (float*) &Value;
2727 glFogfv(GL_FOG_DENSITY, f);
2728 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2732 case D3DRS_VERTEXBLEND :
2734 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2735 TRACE("Vertex Blending state to %ld\n", Value);
2739 case D3DRS_TWEENFACTOR :
2741 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2742 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2746 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2748 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2752 case D3DRS_COLORVERTEX :
2753 case D3DRS_DIFFUSEMATERIALSOURCE :
2754 case D3DRS_SPECULARMATERIALSOURCE :
2755 case D3DRS_AMBIENTMATERIALSOURCE :
2756 case D3DRS_EMISSIVEMATERIALSOURCE :
2758 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2760 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2761 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2762 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2763 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2764 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2765 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2767 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2768 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2769 Parm = GL_AMBIENT_AND_DIFFUSE;
2773 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2775 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2777 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2784 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2786 This->tracking_color = NEEDS_TRACKING;
2787 This->tracking_parm = Parm;
2791 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2796 case D3DRS_LINEPATTERN :
2798 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2799 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2801 if (pattern->wRepeatFactor) {
2802 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2803 checkGLcall("glLineStipple(repeat, linepattern)");
2804 glEnable(GL_LINE_STIPPLE);
2805 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2807 glDisable(GL_LINE_STIPPLE);
2808 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2816 TRACE("ZBias value %f\n", *((float*)&Value));
2817 glPolygonOffset(0, -*((float*)&Value));
2818 checkGLcall("glPolygonOffset(0, -Value)");
2819 glEnable(GL_POLYGON_OFFSET_FILL);
2820 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2821 glEnable(GL_POLYGON_OFFSET_LINE);
2822 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2823 glEnable(GL_POLYGON_OFFSET_POINT);
2824 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2826 glDisable(GL_POLYGON_OFFSET_FILL);
2827 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2828 glDisable(GL_POLYGON_OFFSET_LINE);
2829 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2830 glDisable(GL_POLYGON_OFFSET_POINT);
2831 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2836 case D3DRS_NORMALIZENORMALS :
2838 glEnable(GL_NORMALIZE);
2839 checkGLcall("glEnable(GL_NORMALIZE);");
2841 glDisable(GL_NORMALIZE);
2842 checkGLcall("glDisable(GL_NORMALIZE);");
2846 case D3DRS_POINTSIZE :
2847 TRACE("Set point size to %f\n", *((float*)&Value));
2848 glPointSize(*((float*)&Value));
2849 checkGLcall("glPointSize(...);");
2852 case D3DRS_POINTSIZE_MIN :
2853 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2854 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2855 checkGLcall("glPointParameterfEXT(...);");
2857 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2861 case D3DRS_POINTSIZE_MAX :
2862 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2863 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2864 checkGLcall("glPointParameterfEXT(...);");
2866 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2870 case D3DRS_POINTSCALE_A :
2871 case D3DRS_POINTSCALE_B :
2872 case D3DRS_POINTSCALE_C :
2873 case D3DRS_POINTSCALEENABLE :
2875 /* If enabled, supply the parameters, otherwise fall back to defaults */
2876 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2877 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2878 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2879 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2880 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2882 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2883 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2884 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2886 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2889 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
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, but not on either\n");
2900 case D3DRS_COLORWRITEENABLE :
2901 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2902 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2903 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2904 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2905 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2906 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2907 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2908 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2909 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2910 checkGLcall("glColorMask(...)");
2913 /* Unhandled yet...! */
2914 case D3DRS_LASTPIXEL :
2915 case D3DRS_ZVISIBLE :
2916 case D3DRS_EDGEANTIALIAS :
2917 case D3DRS_RANGEFOGENABLE :
2926 case D3DRS_FOGVERTEXMODE :
2927 case D3DRS_LOCALVIEWER :
2928 case D3DRS_SOFTWAREVERTEXPROCESSING :
2929 case D3DRS_POINTSPRITEENABLE :
2930 case D3DRS_MULTISAMPLEANTIALIAS :
2931 case D3DRS_MULTISAMPLEMASK :
2932 case D3DRS_PATCHEDGESTYLE :
2933 case D3DRS_PATCHSEGMENTS :
2934 case D3DRS_DEBUGMONITORTOKEN :
2935 case D3DRS_POSITIONORDER :
2936 case D3DRS_NORMALORDER :
2937 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2938 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2941 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2948 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2949 ICOM_THIS(IDirect3DDevice8Impl,iface);
2950 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2951 *pValue = This->StateBlock->renderstate[State];
2954 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2955 ICOM_THIS(IDirect3DDevice8Impl,iface);
2957 TRACE("(%p)\n", This);
2959 return IDirect3DDeviceImpl_BeginStateBlock(This);
2961 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2962 IDirect3DStateBlockImpl* pSB;
2963 ICOM_THIS(IDirect3DDevice8Impl,iface);
2966 TRACE("(%p)\n", This);
2968 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2969 *pToken = (DWORD) pSB;
2973 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2974 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2975 ICOM_THIS(IDirect3DDevice8Impl,iface);
2977 TRACE("(%p)\n", This);
2979 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2982 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2983 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2984 ICOM_THIS(IDirect3DDevice8Impl,iface);
2986 TRACE("(%p)\n", This);
2988 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2990 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2991 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2992 ICOM_THIS(IDirect3DDevice8Impl,iface);
2994 TRACE("(%p)\n", This);
2996 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2999 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3000 IDirect3DStateBlockImpl* pSB;
3001 ICOM_THIS(IDirect3DDevice8Impl,iface);
3004 TRACE("(%p) : for type %d\n", This, Type);
3006 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3007 *pToken = (DWORD) pSB;
3011 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3012 ICOM_THIS(IDirect3DDevice8Impl,iface);
3013 FIXME("(%p) : stub\n", This); return D3D_OK;
3015 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3016 ICOM_THIS(IDirect3DDevice8Impl,iface);
3017 FIXME("(%p) : stub\n", This); return D3D_OK;
3019 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3020 ICOM_THIS(IDirect3DDevice8Impl,iface);
3021 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3022 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3023 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3026 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3028 IDirect3DBaseTexture8 *oldTxt;
3029 BOOL reapplyStates = TRUE;
3030 DWORD oldTextureDimensions = -1;
3031 DWORD reapplyFlags = 0;
3033 ICOM_THIS(IDirect3DDevice8Impl,iface);
3034 D3DRESOURCETYPE textureType;
3036 oldTxt = This->UpdateStateBlock->textures[Stage];
3037 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3039 /* Reject invalid texture units */
3040 if (Stage >= GL_LIMITS(textures)) {
3041 TRACE("Attempt to access invalid texture rejected\n");
3042 return D3DERR_INVALIDCALL;
3045 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3046 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3047 This->UpdateStateBlock->textures[Stage] = pTexture;
3049 /* Handle recording of state blocks */
3050 if (This->isRecordingState) {
3051 TRACE("Recording... not performing anything\n");
3055 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3058 /* Make appropriate texture active */
3059 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3060 #if defined(GL_VERSION_1_3)
3061 glActiveTexture(GL_TEXTURE0 + Stage);
3063 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3065 checkGLcall("glActiveTextureARB");
3066 } else if (Stage>0) {
3067 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3070 /* Decrement the count of the previous texture */
3071 if (NULL != oldTxt) {
3072 IDirect3DBaseTexture8Impl_Release(oldTxt);
3075 if (NULL != pTexture) {
3076 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3078 /* Now setup the texture appropraitly */
3079 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3081 if (textureType == D3DRTYPE_TEXTURE) {
3082 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3083 TRACE("Skipping setting texture as old == new\n");
3084 reapplyStates = FALSE;
3086 /* Standard 2D texture */
3087 TRACE("Standard 2d texture\n");
3088 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3090 /* Load up the texture now */
3091 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3093 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3094 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3095 TRACE("Skipping setting texture as old == new\n");
3096 reapplyStates = FALSE;
3098 /* Standard 3D (volume) texture */
3099 TRACE("Standard 3d texture\n");
3100 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3102 /* Load up the texture now */
3103 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3105 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3106 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3107 TRACE("Skipping setting texture as old == new\n");
3108 reapplyStates = FALSE;
3110 /* Standard Cube texture */
3111 TRACE("Standard Cube texture\n");
3112 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3114 /* Load up the texture now */
3115 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3118 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3121 TRACE("Setting to no texture (ie default texture)\n");
3122 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3123 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3124 checkGLcall("glBindTexture");
3125 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3128 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3129 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3130 glDisable(oldTextureDimensions);
3131 checkGLcall("Disable oldTextureDimensions");
3132 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3133 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3134 checkGLcall("glEnable new texture dimensions");
3137 /* If Alpha arg1 is texture then handle the special case when there changes between a
3138 texture and no texture - See comments in set_tex_op */
3139 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3140 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3142 reapplyFlags |= REAPPLY_ALPHAOP;
3147 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3148 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3149 if (reapplyStates) {
3150 setupTextureStates(iface, Stage, reapplyFlags);
3158 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3159 ICOM_THIS(IDirect3DDevice8Impl,iface);
3160 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3161 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3165 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3166 ICOM_THIS(IDirect3DDevice8Impl,iface);
3168 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3170 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3172 /* Reject invalid texture units */
3173 if (Stage >= GL_LIMITS(textures)) {
3174 TRACE("Attempt to access invalid texture rejected\n");
3175 return D3DERR_INVALIDCALL;
3178 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3179 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3180 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3182 /* Handle recording of state blocks */
3183 if (This->isRecordingState) {
3184 TRACE("Recording... not performing anything\n");
3190 /* Make appropriate texture active */
3191 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3192 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3193 #if defined(GL_VERSION_1_3)
3194 glActiveTexture(GL_TEXTURE0 + Stage);
3195 vcheckGLcall("glActiveTexture");
3197 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3198 vcheckGLcall("glActiveTextureARB");
3200 } else if (Stage > 0) {
3201 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
3206 case D3DTSS_MINFILTER :
3207 case D3DTSS_MIPFILTER :
3209 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3210 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3211 GLint realVal = GL_LINEAR;
3213 if (ValueMIN == D3DTEXF_POINT) {
3215 if (ValueMIP == D3DTEXF_POINT) {
3216 realVal = GL_NEAREST_MIPMAP_NEAREST;
3217 } else if (ValueMIP == D3DTEXF_LINEAR) {
3218 realVal = GL_NEAREST_MIPMAP_LINEAR;
3219 } else if (ValueMIP == D3DTEXF_NONE) {
3220 realVal = GL_NEAREST;
3222 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3223 realVal = GL_NEAREST_MIPMAP_LINEAR;
3225 } else if (ValueMIN == D3DTEXF_LINEAR) {
3227 if (ValueMIP == D3DTEXF_POINT) {
3228 realVal = GL_LINEAR_MIPMAP_NEAREST;
3229 } else if (ValueMIP == D3DTEXF_LINEAR) {
3230 realVal = GL_LINEAR_MIPMAP_LINEAR;
3231 } else if (ValueMIP == D3DTEXF_NONE) {
3232 realVal = GL_LINEAR;
3234 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3235 realVal = GL_LINEAR_MIPMAP_LINEAR;
3237 } else if (ValueMIN == D3DTEXF_NONE) {
3238 /* Doesnt really make sense - Windows just seems to disable
3239 mipmapping when this occurs */
3240 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3241 realVal = GL_LINEAR;
3244 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3245 realVal = GL_LINEAR_MIPMAP_LINEAR;
3248 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3249 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3250 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
3254 case D3DTSS_MAXANISOTROPY :
3256 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3257 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3258 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3263 case D3DTSS_MAGFILTER :
3264 if (Value == D3DTEXF_POINT) {
3265 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3266 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
3267 } else if (Value == D3DTEXF_LINEAR) {
3268 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3269 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
3271 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
3275 case D3DTSS_ALPHAOP :
3276 case D3DTSS_COLOROP :
3279 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3280 /* TODO: Disable by making this and all later levels disabled */
3281 glDisable(GL_TEXTURE_1D);
3282 checkGLcall("Disable GL_TEXTURE_1D");
3283 glDisable(GL_TEXTURE_2D);
3284 checkGLcall("Disable GL_TEXTURE_2D");
3285 glDisable(GL_TEXTURE_3D);
3286 checkGLcall("Disable GL_TEXTURE_3D");
3287 break; /* Dont bother setting the texture operations */
3289 /* Enable only the appropriate texture dimension */
3290 if (Type == D3DTSS_COLOROP) {
3291 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3292 glEnable(GL_TEXTURE_1D);
3293 checkGLcall("Enable GL_TEXTURE_1D");
3295 glDisable(GL_TEXTURE_1D);
3296 checkGLcall("Disable GL_TEXTURE_1D");
3298 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3299 glEnable(GL_TEXTURE_2D);
3300 checkGLcall("Enable GL_TEXTURE_2D");
3302 glDisable(GL_TEXTURE_2D);
3303 checkGLcall("Disable GL_TEXTURE_2D");
3305 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3306 glEnable(GL_TEXTURE_3D);
3307 checkGLcall("Enable GL_TEXTURE_3D");
3309 glDisable(GL_TEXTURE_3D);
3310 checkGLcall("Disable GL_TEXTURE_3D");
3312 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3313 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3314 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3316 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3317 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3321 /* Drop through... (Except disable case) */
3322 case D3DTSS_COLORARG0 :
3323 case D3DTSS_COLORARG1 :
3324 case D3DTSS_COLORARG2 :
3325 case D3DTSS_ALPHAARG0 :
3326 case D3DTSS_ALPHAARG1 :
3327 case D3DTSS_ALPHAARG2 :
3329 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3330 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3332 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3333 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3334 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3335 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3337 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3338 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3339 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3340 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3346 case D3DTSS_ADDRESSU :
3347 case D3DTSS_ADDRESSV :
3348 case D3DTSS_ADDRESSW :
3350 GLint wrapParm = GL_REPEAT;
3352 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3353 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3354 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3355 #if defined(GL_VERSION_1_4)
3356 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3357 #elif defined(GL_ARB_texture_mirrored_repeat)
3358 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3360 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3362 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3364 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3365 wrapParm = GL_REPEAT;
3369 case D3DTSS_ADDRESSU:
3370 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3371 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3372 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3374 case D3DTSS_ADDRESSV:
3375 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3376 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3377 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3379 case D3DTSS_ADDRESSW:
3380 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3381 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3382 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3385 break; /** stupic compilator */
3390 case D3DTSS_BORDERCOLOR :
3393 D3DCOLORTOGLFLOAT4(Value, col);
3394 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3395 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3396 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3400 case D3DTSS_TEXCOORDINDEX :
3402 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3404 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3405 one flag, you can still specify an index value, which the system uses to
3406 determine the texture wrapping mode.
3407 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3408 means use the vertex position (camera-space) as the input texture coordinates
3409 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3410 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3411 to the TEXCOORDINDEX value */
3414 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3416 switch (Value & 0xFFFF0000) {
3417 case D3DTSS_TCI_PASSTHRU:
3418 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3419 glDisable(GL_TEXTURE_GEN_S);
3420 glDisable(GL_TEXTURE_GEN_T);
3421 glDisable(GL_TEXTURE_GEN_R);
3422 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3425 case D3DTSS_TCI_CAMERASPACEPOSITION:
3426 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3427 as the input texture coordinates for this stage's texture transformation. This
3428 equates roughly to EYE_LINEAR */
3430 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3431 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3432 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3433 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3434 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3436 glMatrixMode(GL_MODELVIEW);
3439 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3440 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3441 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3442 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3445 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3446 glEnable(GL_TEXTURE_GEN_S);
3447 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3448 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3449 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3450 glEnable(GL_TEXTURE_GEN_T);
3451 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3452 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3453 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3454 glEnable(GL_TEXTURE_GEN_R);
3455 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3456 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3457 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3461 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3462 case D3DTSS_TCI_CAMERASPACENORMAL:
3464 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3465 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3466 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3467 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3468 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3470 glMatrixMode(GL_MODELVIEW);
3473 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3474 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3475 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3476 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3479 glEnable(GL_TEXTURE_GEN_S);
3480 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3481 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3482 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3483 glEnable(GL_TEXTURE_GEN_T);
3484 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3485 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3486 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3487 glEnable(GL_TEXTURE_GEN_R);
3488 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3489 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3490 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3495 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3496 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3499 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3500 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3501 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3502 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3503 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3505 glMatrixMode(GL_MODELVIEW);
3508 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3509 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3510 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3511 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3514 glEnable(GL_TEXTURE_GEN_S);
3515 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3516 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3517 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3518 glEnable(GL_TEXTURE_GEN_T);
3519 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3520 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3521 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3522 glEnable(GL_TEXTURE_GEN_R);
3523 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3524 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3525 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3530 /* Unhandled types: */
3533 /* ? disable GL_TEXTURE_GEN_n ? */
3534 glDisable(GL_TEXTURE_GEN_S);
3535 glDisable(GL_TEXTURE_GEN_T);
3536 glDisable(GL_TEXTURE_GEN_R);
3537 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3544 case D3DTSS_BUMPENVMAT00 :
3545 case D3DTSS_BUMPENVMAT01 :
3546 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3548 case D3DTSS_BUMPENVMAT10 :
3549 case D3DTSS_BUMPENVMAT11 :
3550 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3553 case D3DTSS_TEXTURETRANSFORMFLAGS :
3554 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3557 case D3DTSS_MIPMAPLODBIAS :
3558 case D3DTSS_MAXMIPLEVEL :
3559 case D3DTSS_BUMPENVLSCALE :
3560 case D3DTSS_BUMPENVLOFFSET :
3561 case D3DTSS_RESULTARG :
3563 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3564 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3571 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3572 ICOM_THIS(IDirect3DDevice8Impl,iface);
3573 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3576 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3577 ICOM_THIS(IDirect3DDevice8Impl,iface);
3578 FIXME("(%p) : stub\n", This);
3581 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3582 ICOM_THIS(IDirect3DDevice8Impl,iface);
3583 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3584 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3585 if (PaletteNumber >= MAX_PALETTES) {
3586 return D3DERR_INVALIDCALL;
3588 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3591 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3592 ICOM_THIS(IDirect3DDevice8Impl,iface);
3593 if (PaletteNumber >= MAX_PALETTES) {
3594 return D3DERR_INVALIDCALL;
3596 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3597 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3598 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3601 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3602 ICOM_THIS(IDirect3DDevice8Impl,iface);
3603 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3604 if (PaletteNumber >= MAX_PALETTES) {
3605 return D3DERR_INVALIDCALL;
3607 This->currentPalette = PaletteNumber;
3609 #if defined(GL_EXT_paletted_texture)
3610 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3614 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3615 GL_RGBA, /* internal format */
3616 256, /* table size */
3617 GL_RGBA, /* table format */
3618 GL_UNSIGNED_BYTE, /* table type */
3619 This->palettes[PaletteNumber]);
3620 checkGLcall("glColorTableEXT");
3625 /* Delayed palette handling ... waiting for software emulation into preload code */
3630 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3631 ICOM_THIS(IDirect3DDevice8Impl,iface);
3632 *PaletteNumber = This->currentPalette;
3633 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3636 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3638 ICOM_THIS(IDirect3DDevice8Impl,iface);
3639 This->StateBlock->streamIsUP = FALSE;
3641 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3642 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3646 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3647 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3649 IDirect3DIndexBuffer8 *pIB;
3650 D3DINDEXBUFFER_DESC IdxBufDsc;
3652 ICOM_THIS(IDirect3DDevice8Impl,iface);
3653 pIB = This->StateBlock->pIndexData;
3654 This->StateBlock->streamIsUP = FALSE;
3656 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3657 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3658 minIndex, NumVertices, startIndex, primCount);
3660 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3661 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3667 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3672 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3673 ICOM_THIS(IDirect3DDevice8Impl,iface);
3675 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3676 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3678 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3680 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3681 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3682 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3683 This->StateBlock->streamIsUP = TRUE;
3684 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3685 This->StateBlock->stream_stride[0] = 0;
3686 This->StateBlock->stream_source[0] = NULL;
3688 /*stream zero settings set to null at end */
3691 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3692 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3693 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3694 UINT VertexStreamZeroStride) {
3696 ICOM_THIS(IDirect3DDevice8Impl,iface);
3697 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),
3698 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3700 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3701 if (IndexDataFormat == D3DFMT_INDEX16) {
3707 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3708 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3709 This->StateBlock->streamIsUP = TRUE;
3710 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3711 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3713 /*stream zero settings set to null at end */
3714 This->StateBlock->stream_source[0] = NULL;
3715 This->StateBlock->stream_stride[0] = 0;
3716 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3720 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3721 ICOM_THIS(IDirect3DDevice8Impl,iface);
3722 FIXME("(%p) : stub\n", This); return D3D_OK;
3724 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3725 ICOM_THIS(IDirect3DDevice8Impl,iface);
3726 IDirect3DVertexShaderImpl* object;
3727 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3731 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3732 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3733 return D3DERR_INVALIDCALL;
3735 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3736 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3737 return D3DERR_OUTOFVIDEOMEMORY;
3740 /** Create the Vertex Shader */
3741 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3742 /** TODO: check FAILED(res) */
3744 /** Create and Bind the Vertex Shader Declaration */
3745 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3746 /** TODO: check FAILED(res) */
3748 VertexShaders[i] = object;
3749 VertexShaderDeclarations[i] = attached_decl;
3750 *pHandle = VS_HIGHESTFIXEDFXF + i;
3751 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3755 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3756 ICOM_THIS(IDirect3DDevice8Impl,iface);
3758 This->UpdateStateBlock->VertexShader = Handle;
3759 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3760 This->UpdateStateBlock->Set.vertexShader = TRUE;
3762 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3763 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3764 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3765 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3766 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3767 } else { /* use a fvf, so desactivate the vshader decl */
3768 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3769 This->UpdateStateBlock->vertexShaderDecl = NULL;
3770 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3771 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3773 /* Handle recording of state blocks */
3774 if (This->isRecordingState) {
3775 TRACE("Recording... not performing anything\n");
3779 * TODO: merge HAL shaders context switching from prototype
3783 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3784 ICOM_THIS(IDirect3DDevice8Impl,iface);
3785 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3786 *pHandle = This->StateBlock->VertexShader;
3790 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3791 ICOM_THIS(IDirect3DDevice8Impl,iface);
3792 IDirect3DVertexShaderImpl* object;
3793 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3795 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3796 return D3DERR_INVALIDCALL;
3800 * Delete Vertex Shader
3802 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3803 if (NULL == object) {
3804 return D3DERR_INVALIDCALL;
3806 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3807 /* TODO: check validity of object */
3808 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3809 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3810 HeapFree(GetProcessHeap(), 0, (void *)object);
3811 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3814 * Delete Vertex Shader Declaration
3816 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3817 if (NULL == attached_decl) {
3818 return D3DERR_INVALIDCALL;
3820 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3821 /* TODO: check validity of object */
3822 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3823 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3824 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3829 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3830 ICOM_THIS(IDirect3DDevice8Impl,iface);
3832 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3833 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3834 return D3DERR_INVALIDCALL;
3836 if (NULL == pConstantData) {
3837 return D3DERR_INVALIDCALL;
3839 if (ConstantCount > 1) {
3840 FLOAT* f = (FLOAT*)pConstantData;
3842 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3843 for (i = 0; i < ConstantCount; ++i) {
3844 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3848 FLOAT* f = (FLOAT*) pConstantData;
3849 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3851 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3852 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3855 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3856 ICOM_THIS(IDirect3DDevice8Impl,iface);
3858 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3859 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3860 return D3DERR_INVALIDCALL;
3862 if (NULL == pConstantData) {
3863 return D3DERR_INVALIDCALL;
3865 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3868 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3869 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3870 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3872 attached_decl = VERTEX_SHADER_DECL(Handle);
3873 if (NULL == attached_decl) {
3874 return D3DERR_INVALIDCALL;
3876 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3878 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3879 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3880 IDirect3DVertexShaderImpl* object;
3882 object = VERTEX_SHADER(Handle);
3883 if (NULL == object) {
3884 return D3DERR_INVALIDCALL;
3886 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3889 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3890 ICOM_THIS(IDirect3DDevice8Impl,iface);
3891 IDirect3DIndexBuffer8 *oldIdxs;
3893 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3894 oldIdxs = This->StateBlock->pIndexData;
3896 This->UpdateStateBlock->Changed.Indices = TRUE;
3897 This->UpdateStateBlock->Set.Indices = TRUE;
3898 This->UpdateStateBlock->pIndexData = pIndexData;
3899 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3901 /* Handle recording of state blocks */
3902 if (This->isRecordingState) {
3903 TRACE("Recording... not performing anything\n");
3907 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3908 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3911 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3912 ICOM_THIS(IDirect3DDevice8Impl,iface);
3913 FIXME("(%p) : stub\n", This);
3915 *ppIndexData = This->StateBlock->pIndexData;
3916 /* up ref count on ppindexdata */
3917 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3918 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3922 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3923 ICOM_THIS(IDirect3DDevice8Impl,iface);
3924 IDirect3DPixelShaderImpl* object;
3928 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3929 if (NULL == pFunction || NULL == pHandle) {
3930 return D3DERR_INVALIDCALL;
3932 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3933 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3934 return D3DERR_OUTOFVIDEOMEMORY;
3937 /** Create the Pixel Shader */
3938 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3939 if (SUCCEEDED(res)) {
3940 PixelShaders[i] = object;
3941 *pHandle = VS_HIGHESTFIXEDFXF + i;
3944 *pHandle = 0xFFFFFFFF;
3947 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3948 ICOM_THIS(IDirect3DDevice8Impl,iface);
3950 This->UpdateStateBlock->PixelShader = Handle;
3951 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3952 This->UpdateStateBlock->Set.pixelShader = TRUE;
3954 /* Handle recording of state blocks */
3955 if (This->isRecordingState) {
3956 TRACE_(d3d_shader)("Recording... not performing anything\n");
3960 /* FIXME: Quieten when not being used */
3962 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3964 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3969 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3970 ICOM_THIS(IDirect3DDevice8Impl,iface);
3971 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3972 *pHandle = This->StateBlock->PixelShader;
3976 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3977 ICOM_THIS(IDirect3DDevice8Impl,iface);
3978 IDirect3DPixelShaderImpl* object;
3980 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3981 return D3DERR_INVALIDCALL;
3983 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3984 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3985 /* TODO: check validity of object before free */
3986 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3987 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3988 HeapFree(GetProcessHeap(), 0, (void *)object);
3989 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3994 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3995 ICOM_THIS(IDirect3DDevice8Impl,iface);
3997 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3998 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3999 return D3DERR_INVALIDCALL;
4001 if (NULL == pConstantData) {
4002 return D3DERR_INVALIDCALL;
4004 if (ConstantCount > 1) {
4005 FLOAT* f = (FLOAT*)pConstantData;
4007 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4008 for (i = 0; i < ConstantCount; ++i) {
4009 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4013 FLOAT* f = (FLOAT*) pConstantData;
4014 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4016 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4017 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4020 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4021 ICOM_THIS(IDirect3DDevice8Impl,iface);
4023 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4024 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4025 return D3DERR_INVALIDCALL;
4027 if (NULL == pConstantData) {
4028 return D3DERR_INVALIDCALL;
4030 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4033 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4034 IDirect3DPixelShaderImpl* object;
4036 object = PIXEL_SHADER(Handle);
4037 if (NULL == object) {
4038 return D3DERR_INVALIDCALL;
4040 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4042 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4043 ICOM_THIS(IDirect3DDevice8Impl,iface);
4044 FIXME("(%p) : stub\n", This); return D3D_OK;
4046 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4047 ICOM_THIS(IDirect3DDevice8Impl,iface);
4048 FIXME("(%p) : stub\n", This); return D3D_OK;
4050 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4051 ICOM_THIS(IDirect3DDevice8Impl,iface);
4052 FIXME("(%p) : stub\n", This); return D3D_OK;
4055 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4056 IDirect3DVertexBuffer8 *oldSrc;
4057 ICOM_THIS(IDirect3DDevice8Impl,iface);
4059 oldSrc = This->StateBlock->stream_source[StreamNumber];
4060 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4062 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4063 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4064 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4065 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4067 /* Handle recording of state blocks */
4068 if (This->isRecordingState) {
4069 TRACE("Recording... not performing anything\n");
4073 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4074 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4077 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4078 ICOM_THIS(IDirect3DDevice8Impl,iface);
4079 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4080 *pStream = This->StateBlock->stream_source[StreamNumber];
4081 *pStride = This->StateBlock->stream_stride[StreamNumber];
4082 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4087 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4089 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4090 IDirect3DDevice8Impl_QueryInterface,
4091 IDirect3DDevice8Impl_AddRef,
4092 IDirect3DDevice8Impl_Release,
4093 IDirect3DDevice8Impl_TestCooperativeLevel,
4094 IDirect3DDevice8Impl_GetAvailableTextureMem,
4095 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4096 IDirect3DDevice8Impl_GetDirect3D,
4097 IDirect3DDevice8Impl_GetDeviceCaps,
4098 IDirect3DDevice8Impl_GetDisplayMode,
4099 IDirect3DDevice8Impl_GetCreationParameters,
4100 IDirect3DDevice8Impl_SetCursorProperties,
4101 IDirect3DDevice8Impl_SetCursorPosition,
4102 IDirect3DDevice8Impl_ShowCursor,
4103 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4104 IDirect3DDevice8Impl_Reset,
4105 IDirect3DDevice8Impl_Present,
4106 IDirect3DDevice8Impl_GetBackBuffer,
4107 IDirect3DDevice8Impl_GetRasterStatus,
4108 IDirect3DDevice8Impl_SetGammaRamp,
4109 IDirect3DDevice8Impl_GetGammaRamp,
4110 IDirect3DDevice8Impl_CreateTexture,
4111 IDirect3DDevice8Impl_CreateVolumeTexture,
4112 IDirect3DDevice8Impl_CreateCubeTexture,
4113 IDirect3DDevice8Impl_CreateVertexBuffer,
4114 IDirect3DDevice8Impl_CreateIndexBuffer,
4115 IDirect3DDevice8Impl_CreateRenderTarget,
4116 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4117 IDirect3DDevice8Impl_CreateImageSurface,
4118 IDirect3DDevice8Impl_CopyRects,
4119 IDirect3DDevice8Impl_UpdateTexture,
4120 IDirect3DDevice8Impl_GetFrontBuffer,
4121 IDirect3DDevice8Impl_SetRenderTarget,
4122 IDirect3DDevice8Impl_GetRenderTarget,
4123 IDirect3DDevice8Impl_GetDepthStencilSurface,
4124 IDirect3DDevice8Impl_BeginScene,
4125 IDirect3DDevice8Impl_EndScene,
4126 IDirect3DDevice8Impl_Clear,
4127 IDirect3DDevice8Impl_SetTransform,
4128 IDirect3DDevice8Impl_GetTransform,
4129 IDirect3DDevice8Impl_MultiplyTransform,
4130 IDirect3DDevice8Impl_SetViewport,
4131 IDirect3DDevice8Impl_GetViewport,
4132 IDirect3DDevice8Impl_SetMaterial,
4133 IDirect3DDevice8Impl_GetMaterial,
4134 IDirect3DDevice8Impl_SetLight,
4135 IDirect3DDevice8Impl_GetLight,
4136 IDirect3DDevice8Impl_LightEnable,
4137 IDirect3DDevice8Impl_GetLightEnable,
4138 IDirect3DDevice8Impl_SetClipPlane,
4139 IDirect3DDevice8Impl_GetClipPlane,
4140 IDirect3DDevice8Impl_SetRenderState,
4141 IDirect3DDevice8Impl_GetRenderState,
4142 IDirect3DDevice8Impl_BeginStateBlock,
4143 IDirect3DDevice8Impl_EndStateBlock,
4144 IDirect3DDevice8Impl_ApplyStateBlock,
4145 IDirect3DDevice8Impl_CaptureStateBlock,
4146 IDirect3DDevice8Impl_DeleteStateBlock,
4147 IDirect3DDevice8Impl_CreateStateBlock,
4148 IDirect3DDevice8Impl_SetClipStatus,
4149 IDirect3DDevice8Impl_GetClipStatus,
4150 IDirect3DDevice8Impl_GetTexture,
4151 IDirect3DDevice8Impl_SetTexture,
4152 IDirect3DDevice8Impl_GetTextureStageState,
4153 IDirect3DDevice8Impl_SetTextureStageState,
4154 IDirect3DDevice8Impl_ValidateDevice,
4155 IDirect3DDevice8Impl_GetInfo,
4156 IDirect3DDevice8Impl_SetPaletteEntries,
4157 IDirect3DDevice8Impl_GetPaletteEntries,
4158 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4159 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4160 IDirect3DDevice8Impl_DrawPrimitive,
4161 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4162 IDirect3DDevice8Impl_DrawPrimitiveUP,
4163 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4164 IDirect3DDevice8Impl_ProcessVertices,
4165 IDirect3DDevice8Impl_CreateVertexShader,
4166 IDirect3DDevice8Impl_SetVertexShader,
4167 IDirect3DDevice8Impl_GetVertexShader,
4168 IDirect3DDevice8Impl_DeleteVertexShader,
4169 IDirect3DDevice8Impl_SetVertexShaderConstant,
4170 IDirect3DDevice8Impl_GetVertexShaderConstant,
4171 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4172 IDirect3DDevice8Impl_GetVertexShaderFunction,
4173 IDirect3DDevice8Impl_SetStreamSource,
4174 IDirect3DDevice8Impl_GetStreamSource,
4175 IDirect3DDevice8Impl_SetIndices,
4176 IDirect3DDevice8Impl_GetIndices,
4177 IDirect3DDevice8Impl_CreatePixelShader,
4178 IDirect3DDevice8Impl_SetPixelShader,
4179 IDirect3DDevice8Impl_GetPixelShader,
4180 IDirect3DDevice8Impl_DeletePixelShader,
4181 IDirect3DDevice8Impl_SetPixelShaderConstant,
4182 IDirect3DDevice8Impl_GetPixelShaderConstant,
4183 IDirect3DDevice8Impl_GetPixelShaderFunction,
4184 IDirect3DDevice8Impl_DrawRectPatch,
4185 IDirect3DDevice8Impl_DrawTriPatch,
4186 IDirect3DDevice8Impl_DeletePatch
4189 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4191 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4192 ICOM_THIS(IDirect3DDevice8Impl,iface);
4197 if (This->glCtx != This->render_ctx) {
4198 glXDestroyContext(This->display, This->render_ctx);
4199 This->render_ctx = This->glCtx;
4202 if (This->win != This->drawable) {
4203 glXDestroyPbuffer(This->display, This->drawable);
4204 This->drawable = This->win;
4213 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4214 IDirect3DSurface8* RenderSurface,
4215 IDirect3DSurface8* StencilSurface) {
4217 HRESULT ret = D3DERR_INVALIDCALL;
4219 * Currently only active for GLX >= 1.3
4220 * for others versions we'll have to use GLXPixmaps
4222 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4223 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4224 * so only check OpenGL version
4226 #if defined(GL_VERSION_1_3)
4227 GLXFBConfig* cfgs = NULL;
4231 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4232 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4233 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4234 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4235 IDirect3DSurface8Impl* tmp;
4237 ICOM_THIS(IDirect3DDevice8Impl,iface);
4239 #define PUSH1(att) attribs[nAttribs++] = (att);
4240 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4242 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
4243 PUSH2(GLX_X_RENDERABLE, TRUE);
4244 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4246 switch (BackBufferFormat) {
4249 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4250 PUSH2(GLX_BUFFER_SIZE, 8);
4251 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4255 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4256 PUSH2(GLX_RED_SIZE, 3);
4257 PUSH2(GLX_GREEN_SIZE, 3);
4258 PUSH2(GLX_BLUE_SIZE, 2);
4261 case D3DFMT_A1R5G5B5:
4262 PUSH2(GLX_ALPHA_SIZE, 1);
4263 case D3DFMT_X1R5G5B5:
4264 PUSH2(GLX_RED_SIZE, 5);
4265 PUSH2(GLX_GREEN_SIZE, 5);
4266 PUSH2(GLX_BLUE_SIZE, 5);
4270 PUSH2(GLX_RED_SIZE, 5);
4271 PUSH2(GLX_GREEN_SIZE, 6);
4272 PUSH2(GLX_BLUE_SIZE, 5);
4275 case D3DFMT_A4R4G4B4:
4276 PUSH2(GLX_ALPHA_SIZE, 4);
4277 case D3DFMT_X4R4G4B4:
4278 PUSH2(GLX_RED_SIZE, 4);
4279 PUSH2(GLX_GREEN_SIZE, 4);
4280 PUSH2(GLX_BLUE_SIZE, 4);
4283 case D3DFMT_A8R8G8B8:
4284 PUSH2(GLX_ALPHA_SIZE, 8);
4286 case D3DFMT_X8R8G8B8:
4287 PUSH2(GLX_RED_SIZE, 8);
4288 PUSH2(GLX_GREEN_SIZE, 8);
4289 PUSH2(GLX_BLUE_SIZE, 8);
4296 switch (StencilBufferFormat) {
4297 case D3DFMT_D16_LOCKABLE:
4299 PUSH2(GLX_DEPTH_SIZE, 16);
4303 PUSH2(GLX_DEPTH_SIZE, 15);
4307 PUSH2(GLX_DEPTH_SIZE, 24);
4310 case D3DFMT_D24X4S4:
4311 PUSH2(GLX_DEPTH_SIZE, 24);
4312 PUSH2(GLX_STENCIL_SIZE, 4);
4316 PUSH2(GLX_DEPTH_SIZE, 24);
4317 PUSH2(GLX_STENCIL_SIZE, 8);
4321 PUSH2(GLX_DEPTH_SIZE, 32);
4332 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4336 for (i = 0; i < nCfgs; ++i) {
4337 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4341 if (NULL != This->renderTarget) {
4344 vcheckGLcall("glFlush");
4347 /** very very usefull debug code */
4348 glXSwapBuffers(This->display, This->drawable);
4349 printf("Hit Enter to get next frame ...\n");
4353 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4354 vcheckGLcall("glIntegerv");
4355 glReadBuffer(GL_BACK);
4356 vcheckGLcall("glReadBuffer");
4359 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4361 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4364 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4366 This->renderTarget->myDesc.Height - j - 1,
4367 This->renderTarget->myDesc.Width,
4369 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4370 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4371 This->renderTarget->allocatedMemory + j * pitch);
4372 vcheckGLcall("glReadPixels");
4375 glReadBuffer(prev_read);
4376 vcheckGLcall("glReadBuffer");
4379 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4380 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4382 PUSH2(GLX_PBUFFER_WIDTH, Width);
4383 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4385 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4387 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4388 if (NULL == This->render_ctx) {
4389 ERR("cannot create glxContext\n");
4393 glXSwapBuffers(This->display, This->drawable);
4394 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4395 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4397 checkGLcall("glXMakeContextCurrent");
4400 tmp = This->renderTarget;
4401 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4402 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4403 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4405 tmp = This->stencilBufferTarget;
4406 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4407 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4408 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4413 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));