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 /* Uncomment the next line to get extra traces, important but impact speed */
43 /* #define EXTRA_TRACES */
45 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
46 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
47 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
49 IDirect3DVertexShaderImpl* VertexShaders[64];
50 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
51 IDirect3DPixelShaderImpl* PixelShaders[64];
54 #ifdef FRAME_DEBUGGING
56 BOOL isDumpingFrames = FALSE;
61 * Utility functions or macros
63 #define conv_mat(mat,gl_mat) \
65 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
66 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
68 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
69 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
72 /* Apply the current values to the specified texture stage */
73 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
74 ICOM_THIS(IDirect3DDevice8Impl,iface);
77 BOOL changeTexture = TRUE;
79 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
80 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
85 /* Performance: For texture states where multiples effect the outcome, only bother
86 applying the last one as it will pick up all the other values */
87 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
88 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
89 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
90 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
91 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
92 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
96 /* Performance: If the texture states only impact settings for the texture unit
97 (compared to the texture object) then there is no need to reapply them. The
98 only time they need applying is the first time, since we cheat and put the
99 values into the stateblock without applying.
100 Per-texture unit: texture function (eg. combine), ops and args
102 texture generation settings
103 Note: Due to some special conditions there may be a need to do particular ones
104 of these, which is what the Flags allows */
106 case D3DTSS_TEXCOORDINDEX:
107 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
111 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
119 /* Performance: Only change to this texture if we have to */
121 /* Make appropriate texture active */
122 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
123 #if defined(GL_VERSION_1_3)
124 glActiveTexture(GL_TEXTURE0 + Stage);
125 checkGLcall("glActiveTexture");
127 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
128 checkGLcall("glActiveTextureARB");
130 } else if (Stage > 0) {
131 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
133 changeTexture = FALSE;
136 /* Now apply the change */
137 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
141 /* Note the D3DRS value applies to all textures, but GL has one
142 * per texture, so apply it now ready to be used!
144 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
145 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
146 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
148 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
151 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
152 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
155 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
156 ICOM_THIS(IDirect3DDevice8Impl,iface);
158 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
159 glMatrixMode(GL_MODELVIEW);
161 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
164 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
165 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
166 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
167 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
168 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
169 checkGLcall("glLightfv");
172 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
173 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
174 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
175 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
176 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
177 checkGLcall("glLightfv");
180 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
181 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
182 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
183 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
184 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
185 checkGLcall("glLightfv");
187 /* Attenuation - Are these right? guessing... */
188 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
189 checkGLcall("glLightf");
190 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
191 checkGLcall("glLightf");
193 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
194 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
195 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
196 checkGLcall("glLightf");
198 switch (lightInfo->OriginalParms.Type) {
201 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
202 checkGLcall("glLightfv");
203 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
204 checkGLcall("glLightf");
210 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
211 checkGLcall("glLightfv");
213 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
214 checkGLcall("glLightfv");
215 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
216 checkGLcall("glLightf");
217 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
218 checkGLcall("glLightf");
222 case D3DLIGHT_DIRECTIONAL:
224 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
225 checkGLcall("glLightfv");
226 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
227 checkGLcall("glLightf");
228 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
229 checkGLcall("glLightf");
233 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
236 /* Restore the modelview matrix */
240 /* Setup this textures matrix */
241 static void set_texture_matrix(float *smat, DWORD flags)
245 glMatrixMode(GL_TEXTURE);
247 if (flags == D3DTTFF_DISABLE) {
249 checkGLcall("glLoadIdentity()");
253 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
254 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
255 checkGLcall("glLoadIdentity()");
259 memcpy(mat, smat, 16*sizeof(float));
261 switch (flags & ~D3DTTFF_PROJECTED) {
262 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
263 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
264 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
267 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
269 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
270 mat[1] = mat[5] = mat[9] = mat[13] = 0;
273 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
274 mat[2] = mat[6] = mat[10] = mat[14] = 0;
278 checkGLcall("glLoadMatrixf(mat)");
281 /* IDirect3D IUnknown parts follow: */
282 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
284 ICOM_THIS(IDirect3DDevice8Impl,iface);
286 if (IsEqualGUID(riid, &IID_IUnknown)
287 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
288 IDirect3DDevice8Impl_AddRef(iface);
293 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
294 return E_NOINTERFACE;
297 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
298 ICOM_THIS(IDirect3DDevice8Impl,iface);
299 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
300 return ++(This->ref);
303 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
304 ICOM_THIS(IDirect3DDevice8Impl,iface);
305 ULONG ref = --This->ref;
306 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
308 IDirect3DDevice8Impl_CleanRender(iface);
309 HeapFree(GetProcessHeap(), 0, This);
314 /* IDirect3DDevice Interface follow: */
315 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
316 ICOM_THIS(IDirect3DDevice8Impl,iface);
317 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
321 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
322 ICOM_THIS(IDirect3DDevice8Impl,iface);
323 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
325 * pretend we have 32MB of any type of memory queried.
327 return (1024*1024*32);
330 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
331 ICOM_THIS(IDirect3DDevice8Impl,iface);
332 FIXME("(%p) : stub\n", This); return D3D_OK;
334 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
335 ICOM_THIS(IDirect3DDevice8Impl,iface);
336 TRACE("(%p) : returning %p\n", This, This->direct3d8);
339 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
341 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
344 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
345 ICOM_THIS(IDirect3DDevice8Impl,iface);
346 FIXME("(%p) : stub, calling idirect3d for now\n", This);
347 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
350 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
355 ICOM_THIS(IDirect3DDevice8Impl,iface);
356 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
357 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
358 pMode->RefreshRate = 85; /*FIXME: How to identify? */
360 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
361 bpp = GetDeviceCaps(hdc, BITSPIXEL);
365 case 8: pMode->Format = D3DFMT_R8G8B8; break;
366 case 16: pMode->Format = D3DFMT_R5G6B5; break;
367 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
368 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
370 FIXME("Unrecognized display mode format\n");
371 pMode->Format = D3DFMT_UNKNOWN;
374 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
375 pMode->Format, debug_d3dformat(pMode->Format));
378 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
379 ICOM_THIS(IDirect3DDevice8Impl,iface);
380 TRACE("(%p) copying to %p\n", This, pParameters);
381 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
384 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
385 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
386 ICOM_THIS(IDirect3DDevice8Impl,iface);
387 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
389 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
390 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
391 return D3DERR_INVALIDCALL;
393 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
394 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
395 return D3DERR_INVALIDCALL;
398 This->xHotSpot = XHotSpot;
399 This->yHotSpot = YHotSpot;
402 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
403 ICOM_THIS(IDirect3DDevice8Impl,iface);
404 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
405 This->xScreenSpace = XScreenSpace;
406 This->yScreenSpace = YScreenSpace;
409 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
410 ICOM_THIS(IDirect3DDevice8Impl,iface);
411 TRACE("(%p) : visible(%d)\n", This, bShow);
412 This->bCursorVisible = bShow;
415 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
416 IDirect3DSwapChain8Impl* object;
417 ICOM_THIS(IDirect3DDevice8Impl,iface);
418 FIXME("(%p) : stub\n", This);
420 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
421 if (NULL == object) {
422 return D3DERR_OUTOFVIDEOMEMORY;
424 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
427 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
428 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
429 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
431 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
432 (pPresentationParameters->BackBufferHeight == 0))) {
435 GetClientRect(This->win_handle, &Rect);
437 if (pPresentationParameters->BackBufferWidth == 0) {
438 pPresentationParameters->BackBufferWidth = Rect.right;
439 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
441 if (pPresentationParameters->BackBufferHeight == 0) {
442 pPresentationParameters->BackBufferHeight = Rect.bottom;
443 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
447 /* Save the presentation parms now filled in correctly */
448 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
450 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
451 pPresentationParameters->BackBufferWidth,
452 pPresentationParameters->BackBufferHeight,
453 pPresentationParameters->BackBufferFormat,
454 pPresentationParameters->MultiSampleType,
456 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
458 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
459 pPresentationParameters->BackBufferWidth,
460 pPresentationParameters->BackBufferHeight,
461 pPresentationParameters->BackBufferFormat,
462 pPresentationParameters->MultiSampleType,
464 (LPDIRECT3DSURFACE8*) &object->backBuffer);
466 if (pPresentationParameters->EnableAutoDepthStencil) {
467 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
468 pPresentationParameters->BackBufferWidth,
469 pPresentationParameters->BackBufferHeight,
470 pPresentationParameters->AutoDepthStencilFormat,
472 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
474 object->depthStencilBuffer = NULL;
477 *pSwapChain = (IDirect3DSwapChain8*) object;
480 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
481 ICOM_THIS(IDirect3DDevice8Impl,iface);
482 FIXME("(%p) : stub\n", This); return D3D_OK;
484 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
485 CONST RECT* pSourceRect, CONST RECT* pDestRect,
486 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
487 ICOM_THIS(IDirect3DDevice8Impl,iface);
488 TRACE("(%p) : complete stub!\n", This);
492 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
495 glXSwapBuffers(This->display, This->drawable);
496 /* Don't call checkGLcall, as glGetError is not applicable here */
497 TRACE("glXSwapBuffers called, Starting new frame\n");
500 if (TRACE_ON(d3d_fps))
502 static long prev_time, frames;
504 DWORD time = GetTickCount();
506 /* every 1.5 seconds */
507 if (time - prev_time > 1500) {
508 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
514 #if defined(FRAME_DEBUGGING)
516 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
519 FIXME("Enabling D3D Trace\n");
520 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
521 #if defined(SHOW_FRAME_MAKEUP)
522 FIXME("Singe Frame snapshots Starting\n");
523 isDumpingFrames = TRUE;
524 glClear(GL_COLOR_BUFFER_BIT);
527 #if defined(SINGLE_FRAME_DEBUGGING)
529 #if defined(SHOW_FRAME_MAKEUP)
530 FIXME("Singe Frame snapshots Finishing\n");
531 isDumpingFrames = FALSE;
533 FIXME("Singe Frame trace complete\n");
534 DeleteFileA("C:\\D3DTRACE");
535 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
541 #if defined(SHOW_FRAME_MAKEUP)
542 FIXME("Singe Frame snapshots Finishing\n");
543 isDumpingFrames = FALSE;
545 FIXME("Disabling D3D Trace\n");
546 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
553 /* Although this is not strictly required, a simple demo showed this does occur
554 on (at least non-debug) d3d */
555 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
556 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
561 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
562 ICOM_THIS(IDirect3DDevice8Impl,iface);
563 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
564 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
566 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
567 FIXME("Only one backBuffer currently supported\n");
568 return D3DERR_INVALIDCALL;
571 /* Note inc ref on returned surface */
572 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
576 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
577 ICOM_THIS(IDirect3DDevice8Impl,iface);
578 FIXME("(%p) : stub\n", This);
581 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
583 ICOM_THIS(IDirect3DDevice8Impl,iface);
585 FIXME("(%p) : pRamp@%p\n", This, pRamp);
586 hDC = GetDC(This->win_handle);
587 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
588 ReleaseDC(This->win_handle, hDC);
591 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
593 ICOM_THIS(IDirect3DDevice8Impl,iface);
595 FIXME("(%p) : pRamp@%p\n", This, pRamp);
596 hDC = GetDC(This->win_handle);
597 GetDeviceGammaRamp(hDC, pRamp);
598 ReleaseDC(This->win_handle, hDC);
601 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
602 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
603 IDirect3DTexture8Impl *object;
608 ICOM_THIS(IDirect3DDevice8Impl,iface);
610 /* Allocate the storage for the device */
611 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);
612 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
613 object->lpVtbl = &Direct3DTexture8_Vtbl;
614 object->Device = This;
615 object->ResourceType = D3DRTYPE_TEXTURE;
617 object->width = Width;
618 object->height = Height;
619 object->levels = Levels;
620 object->usage = Usage;
621 object->format = Format;
623 /* Calculate levels for mip mapping */
628 while (tmpW > 1 && tmpH > 1) {
629 tmpW = max(1, tmpW / 2);
630 tmpH = max(1, tmpH / 2);
633 TRACE("Calculated levels = %d\n", object->levels);
636 /* Generate all the surfaces */
639 for (i = 0; i < object->levels; i++)
641 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
642 object->surfaces[i]->Container = (IUnknown*) object;
643 object->surfaces[i]->myDesc.Usage = Usage;
644 object->surfaces[i]->myDesc.Pool = Pool;
646 * As written in msdn in IDirect3DTexture8::LockRect
647 * Textures created in D3DPOOL_DEFAULT are not lockable.
649 if (D3DPOOL_DEFAULT == Pool) {
650 object->surfaces[i]->lockable = FALSE;
653 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
654 tmpW = max(1, tmpW / 2);
655 tmpH = max(1, tmpH / 2);
658 *ppTexture = (LPDIRECT3DTEXTURE8) object;
659 TRACE("(%p) : Created texture %p\n", This, object);
662 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
663 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
664 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
666 IDirect3DVolumeTexture8Impl *object;
672 ICOM_THIS(IDirect3DDevice8Impl,iface);
674 /* Allocate the storage for it */
675 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));
676 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
677 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
678 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
679 object->Device = This;
682 object->width = Width;
683 object->height = Height;
684 object->depth = Depth;
685 object->levels = Levels;
686 object->usage = Usage;
687 object->format = Format;
689 /* Calculate levels for mip mapping */
695 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
696 tmpW = max(1, tmpW / 2);
697 tmpH = max(1, tmpH / 2);
698 tmpD = max(1, tmpD / 2);
701 TRACE("Calculated levels = %d\n", object->levels);
704 /* Generate all the surfaces */
709 for (i = 0; i < object->levels; i++)
711 IDirect3DVolume8Impl* volume;
713 /* Create the volume - No entry point for this seperately?? */
714 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
715 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
717 volume->lpVtbl = &Direct3DVolume8_Vtbl;
718 volume->Device = This;
719 volume->ResourceType = D3DRTYPE_VOLUME;
720 volume->Container = (IUnknown*) object;
723 volume->myDesc.Width = Width;
724 volume->myDesc.Height = Height;
725 volume->myDesc.Depth = Depth;
726 volume->myDesc.Format = Format;
727 volume->myDesc.Type = D3DRTYPE_VOLUME;
728 volume->myDesc.Pool = Pool;
729 volume->myDesc.Usage = Usage;
730 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
731 /* Note: Volume textures cannot be dxtn, hence no need to check here */
732 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
733 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
735 volume->lockable = TRUE;
736 volume->locked = FALSE;
737 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
738 volume->Dirty = FALSE;
739 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
741 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
742 This, Width, Height, Depth, Format, debug_d3dformat(Format),
743 volume, volume->allocatedMemory, volume->myDesc.Size);
745 tmpW = max(1, tmpW / 2);
746 tmpH = max(1, tmpH / 2);
747 tmpD = max(1, tmpD / 2);
750 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
751 TRACE("(%p) : Created volume texture %p\n", This, object);
754 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
755 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
757 IDirect3DCubeTexture8Impl *object;
758 ICOM_THIS(IDirect3DDevice8Impl,iface);
762 /* Allocate the storage for it */
763 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));
764 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
765 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
767 object->Device = This;
768 object->ResourceType = D3DRTYPE_CUBETEXTURE;
770 object->edgeLength = EdgeLength;
771 object->levels = Levels;
772 object->usage = Usage;
773 object->format = Format;
775 /* Calculate levels for mip mapping */
780 tmpW = max(1, tmpW / 2);
783 TRACE("Calculated levels = %d\n", object->levels);
786 /* Generate all the surfaces */
788 for (i = 0; i < object->levels; i++) {
789 /* Create the 6 faces */
790 for (j = 0; j < 6; j++) {
791 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
792 object->surfaces[j][i]->Container = (IUnknown*) object;
793 object->surfaces[j][i]->myDesc.Usage = Usage;
794 object->surfaces[j][i]->myDesc.Pool = Pool;
796 * As written in msdn in IDirect3DCubeTexture8::LockRect
797 * Textures created in D3DPOOL_DEFAULT are not lockable.
799 if (D3DPOOL_DEFAULT == Pool) {
800 object->surfaces[j][i]->lockable = FALSE;
803 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
805 tmpW = max(1, tmpW / 2);
808 TRACE("(%p) : Iface@%p\n", This, object);
809 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
812 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
813 IDirect3DVertexBuffer8Impl *object;
815 ICOM_THIS(IDirect3DDevice8Impl,iface);
817 /* Allocate the storage for the device */
818 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
819 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
820 object->Device = This;
821 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
823 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
824 object->currentDesc.Usage = Usage;
825 object->currentDesc.Pool = Pool;
826 object->currentDesc.FVF = FVF;
827 object->currentDesc.Size = Size;
829 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
831 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
835 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
836 IDirect3DIndexBuffer8Impl *object;
838 ICOM_THIS(IDirect3DDevice8Impl,iface);
839 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
841 /* Allocate the storage for the device */
842 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
843 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
844 object->Device = This;
846 object->ResourceType = D3DRTYPE_INDEXBUFFER;
848 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
849 object->currentDesc.Usage = Usage;
850 object->currentDesc.Pool = Pool;
851 object->currentDesc.Format = Format;
852 object->currentDesc.Size = Length;
854 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
856 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
858 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
862 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
863 IDirect3DSurface8Impl *object;
864 ICOM_THIS(IDirect3DDevice8Impl,iface);
866 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
867 if (NULL == object) {
869 return D3DERR_OUTOFVIDEOMEMORY;
871 *ppSurface = (LPDIRECT3DSURFACE8) object;
872 object->lpVtbl = &Direct3DSurface8_Vtbl;
873 object->Device = This;
874 object->ResourceType = D3DRTYPE_SURFACE;
875 object->Container = (IUnknown*) This;
878 object->myDesc.Width = Width;
879 object->myDesc.Height = Height;
880 object->myDesc.Format = Format;
881 object->myDesc.Type = D3DRTYPE_SURFACE;
882 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
883 object->myDesc.Pool = D3DPOOL_DEFAULT;
884 object->myDesc.MultiSampleType = MultiSample;
885 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
886 if (Format == D3DFMT_DXT1) {
887 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
889 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
891 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
892 object->lockable = Lockable;
893 object->locked = FALSE;
894 memset(&object->lockedRect, 0, sizeof(RECT));
895 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
897 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);
900 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
901 IDirect3DSurface8Impl *object;
903 ICOM_THIS(IDirect3DDevice8Impl,iface);
905 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
906 if (NULL == object) {
908 return D3DERR_OUTOFVIDEOMEMORY;
910 *ppSurface = (LPDIRECT3DSURFACE8) object;
911 object->lpVtbl = &Direct3DSurface8_Vtbl;
912 object->Device = This;
913 object->ResourceType = D3DRTYPE_SURFACE;
914 object->Container = (IUnknown*) This;
917 object->myDesc.Width = Width;
918 object->myDesc.Height = Height;
919 object->myDesc.Format = Format;
920 object->myDesc.Type = D3DRTYPE_SURFACE;
921 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
922 object->myDesc.Pool = D3DPOOL_DEFAULT;
923 object->myDesc.MultiSampleType = MultiSample;
924 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
925 if (Format == D3DFMT_DXT1) {
926 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
928 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
930 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
931 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
932 object->locked = FALSE;
933 memset(&object->lockedRect, 0, sizeof(RECT));
934 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
936 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);
939 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
940 IDirect3DSurface8Impl *object;
942 ICOM_THIS(IDirect3DDevice8Impl,iface);
944 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
945 *ppSurface = (LPDIRECT3DSURFACE8) object;
946 object->lpVtbl = &Direct3DSurface8_Vtbl;
947 object->Device = This;
948 object->ResourceType = D3DRTYPE_SURFACE;
949 object->Container = (IUnknown*) This;
952 object->myDesc.Width = Width;
953 object->myDesc.Height = Height;
954 object->myDesc.Format = Format;
955 object->myDesc.Type = D3DRTYPE_SURFACE;
956 object->myDesc.Usage = 0;
957 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
958 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
959 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
960 it is based around 4x4 pixel blocks it requires padding, so allocate enough
962 if (Format == D3DFMT_DXT1) {
963 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
964 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
965 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
966 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
968 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
970 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
971 object->lockable = TRUE;
972 object->locked = FALSE;
973 memset(&object->lockedRect, 0, sizeof(RECT));
974 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
976 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);
979 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
980 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
981 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
984 IDirect3DBaseTexture8* texture = NULL;
987 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
988 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
990 ICOM_THIS(IDirect3DDevice8Impl,iface);
991 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
992 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
994 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
995 a sample and doesn't seem to break anything as far as I can tell */
996 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
997 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
998 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
999 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1000 rc = D3DERR_INVALIDCALL;
1002 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1003 TRACE("Converting dest to same format as source, since dest was unknown\n");
1004 dst->myDesc.Format = src->myDesc.Format;
1006 /* Convert container as well */
1007 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1008 if (SUCCEEDED(rc) && NULL != texture) {
1009 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1010 /** Releasing texture after GetContainer */
1011 IDirect3DBaseTexture8_Release(texture);
1016 /* Quick if complete copy ... */
1017 if (SUCCEEDED(rc)) {
1018 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1020 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1022 D3DLOCKED_RECT lrSrc;
1023 D3DLOCKED_RECT lrDst;
1024 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1025 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1026 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1028 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1030 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1031 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1032 TRACE("Unlocked src and dst\n");
1036 FIXME("Wanted to copy all surfaces but size not compatible\n");
1037 rc = D3DERR_INVALIDCALL;
1043 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1045 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1048 /* Copy rect by rect */
1049 for (i = 0; i < cRects; i++) {
1050 CONST RECT* r = &pSourceRectsArray[i];
1051 CONST POINT* p = &pDestPointsArray[i];
1054 D3DLOCKED_RECT lrSrc;
1055 D3DLOCKED_RECT lrDst;
1058 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1059 if (src->myDesc.Format == D3DFMT_DXT1) {
1060 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1062 copyperline = ((r->right - r->left) * bytesPerPixel);
1064 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1065 dest_rect.left = p->x;
1066 dest_rect.top = p->y;
1067 dest_rect.right = p->x + (r->right - r->left);
1068 dest_rect.bottom= p->y + (r->bottom - r->top);
1069 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1070 TRACE("Locked src and dst\n");
1072 /* Find where to start */
1073 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1074 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1076 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1077 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1078 TRACE("Unlocked src and dst\n");
1081 FIXME("Wanted to copy partial surfaces not implemented\n");
1082 rc = D3DERR_INVALIDCALL;
1089 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1090 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1091 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1092 D3DRESOURCETYPE srcType;
1093 D3DRESOURCETYPE dstType;
1095 ICOM_THIS(IDirect3DDevice8Impl,iface);
1096 TRACE("(%p) : first try\n", This);
1098 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1099 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1101 if (srcType != dstType) {
1102 return D3DERR_INVALIDCALL;
1104 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1105 return D3DERR_INVALIDCALL;
1107 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1108 return D3DERR_INVALIDCALL;
1110 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1111 /** Only copy Dirty textures */
1112 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1113 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1114 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1117 for (i = skipLevels; i < srcLevelCnt; ++i) {
1121 case D3DRTYPE_TEXTURE:
1123 IDirect3DSurface8* srcSur = NULL;
1124 IDirect3DSurface8* dstSur = NULL;
1125 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1126 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1128 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1129 about dst with less levels than the source?) */
1130 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1132 IDirect3DSurface8Impl_Release(srcSur);
1133 IDirect3DSurface8Impl_Release(dstSur);
1136 case D3DRTYPE_VOLUMETEXTURE:
1138 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1141 case D3DRTYPE_CUBETEXTURE:
1143 IDirect3DSurface8* srcSur = NULL;
1144 IDirect3DSurface8* dstSur = NULL;
1145 for (j = 0; j < 5; ++j) {
1146 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1147 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1148 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1149 IDirect3DSurface8Impl_Release(srcSur);
1150 IDirect3DSurface8Impl_Release(dstSur);
1158 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1163 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1165 D3DLOCKED_RECT lockedRect;
1170 ICOM_THIS(IDirect3DDevice8Impl,iface);
1172 FIXME("(%p) : see if behavior correct\n", This);
1174 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1175 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1176 return D3DERR_INVALIDCALL;
1179 wantedRect.left = 0;
1181 wantedRect.right = This->PresentParms.BackBufferWidth;
1182 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1184 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1186 ERR("(%p) : cannot lock surface\n", This);
1187 return D3DERR_INVALIDCALL;
1193 vcheckGLcall("glFlush");
1194 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1195 vcheckGLcall("glIntegerv");
1196 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1197 vcheckGLcall("glIntegerv");
1199 glReadBuffer(GL_FRONT);
1200 vcheckGLcall("glReadBuffer");
1201 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1202 vcheckGLcall("glPixelStorei");
1206 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1207 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1208 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1209 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1210 vcheckGLcall("glReadPixels");
1213 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1214 vcheckGLcall("glPixelStorei");
1215 glReadBuffer(prev_read);
1216 vcheckGLcall("glReadBuffer");
1220 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1223 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1224 HRESULT hr = D3D_OK;
1225 D3DVIEWPORT8 viewport;
1227 ICOM_THIS(IDirect3DDevice8Impl,iface);
1229 /* If pRenderTarget == NULL, it seems to default to back buffer */
1230 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1232 /* For ease of code later on, handle a null depth as leave alone
1233 - Have not tested real d3d for this case but doing this avoids
1234 numerous null pointer checks */
1235 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1237 /* If we are trying to set what we already have, dont bother */
1238 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1239 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1241 /* Otherwise, set the render target up */
1242 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1243 IDirect3DDevice8Impl_CleanRender(iface);
1244 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1247 if (SUCCEEDED(hr)) {
1248 /* Finally, reset the viewport as the MSDN states. */
1249 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1250 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1253 viewport.MaxZ = 1.0f;
1254 viewport.MinZ = 0.0f;
1255 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1261 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1262 ICOM_THIS(IDirect3DDevice8Impl,iface);
1264 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1266 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1267 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1272 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1273 ICOM_THIS(IDirect3DDevice8Impl,iface);
1275 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1277 /* Note inc ref on returned surface */
1278 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1279 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1284 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1285 ICOM_THIS(IDirect3DDevice8Impl,iface);
1286 TRACE("(%p) : stub\n", This);
1290 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1291 IDirect3DBaseTexture8* cont = NULL;
1293 ICOM_THIS(IDirect3DDevice8Impl,iface);
1294 TRACE("(%p)\n", This);
1299 checkGLcall("glFlush");
1301 #if 0 /* Useful for debugging sometimes! */
1302 printf("Hit Enter ...\n");
1306 if (This->frontBuffer != This->renderTarget) {
1309 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1310 vcheckGLcall("glIntegerv");
1311 glReadBuffer(GL_BACK);
1312 vcheckGLcall("glReadBuffer");
1315 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1317 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1320 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1322 This->renderTarget->myDesc.Height - j - 1,
1323 This->renderTarget->myDesc.Width,
1325 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1326 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1327 This->renderTarget->allocatedMemory + j * pitch);
1328 vcheckGLcall("glReadPixels");
1331 glReadBuffer(prev_read);
1332 vcheckGLcall("glReadBuffer");
1335 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1336 if (SUCCEEDED(hr) && NULL != cont) {
1337 /** always dirtify for now. we must find a better way to see that surface have been modified */
1338 This->renderTarget->inPBuffer = TRUE;
1339 This->renderTarget->inTexture = FALSE;
1340 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1341 IDirect3DBaseTexture8_PreLoad(cont);
1342 This->renderTarget->inPBuffer = FALSE;
1343 IDirect3DBaseTexture8Impl_Release(cont);
1351 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1352 ICOM_THIS(IDirect3DDevice8Impl,iface);
1354 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1355 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1356 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1357 GLbitfield glMask = 0;
1358 GLboolean old_ztest;
1359 GLfloat old_z_clear_value;
1360 GLint old_stencil_clear_value;
1361 GLfloat old_color_clear_value[4];
1363 CONST D3DRECT* curRect;
1365 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1366 Count, pRects, Flags, Z, Stencil);
1369 glEnable(GL_SCISSOR_TEST);
1370 checkGLcall("glEnable GL_SCISSOR_TEST");
1371 if (Count > 0 && pRects) {
1377 /* Only set the values up once, as they are not changing */
1378 if (Flags & D3DCLEAR_STENCIL) {
1379 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1380 glClearStencil(Stencil);
1381 checkGLcall("glClearStencil");
1382 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1383 glStencilMask(0xFFFFFFFF);
1386 if (Flags & D3DCLEAR_ZBUFFER) {
1387 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1388 glDepthMask(GL_TRUE);
1389 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1391 checkGLcall("glClearDepth");
1392 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1395 if (Flags & D3DCLEAR_TARGET) {
1396 TRACE("Clearing screen with glClear to color %lx\n", Color);
1397 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1398 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1399 ((Color >> 8) & 0xFF) / 255.0f,
1400 ((Color >> 0) & 0xFF) / 255.0f,
1401 ((Color >> 24) & 0xFF) / 255.0f);
1402 checkGLcall("glClearColor");
1404 /* Clear ALL colors! */
1405 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1406 glMask = glMask | GL_COLOR_BUFFER_BIT;
1409 /* Now process each rect in turn */
1410 for (i = 0; i < Count || i == 0; i++) {
1413 /* Note gl uses lower left, width/height */
1414 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1415 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1416 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1417 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1418 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1419 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1420 checkGLcall("glScissor");
1422 glScissor(This->StateBlock->viewport.X,
1423 (This->PresentParms.BackBufferHeight - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1424 This->StateBlock->viewport.Width,
1425 This->StateBlock->viewport.Height);
1426 checkGLcall("glScissor");
1429 /* Clear the selected rectangle (or full screen) */
1431 checkGLcall("glClear");
1433 /* Step to the next rectangle */
1434 if (curRect) curRect = curRect + sizeof(D3DRECT);
1437 /* Restore the old values (why..?) */
1438 if (Flags & D3DCLEAR_STENCIL) {
1439 glClearStencil(old_stencil_clear_value);
1440 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1442 if (Flags & D3DCLEAR_ZBUFFER) {
1443 glDepthMask(old_ztest);
1444 glClearDepth(old_z_clear_value);
1446 if (Flags & D3DCLEAR_TARGET) {
1447 glClearColor(old_color_clear_value[0],
1448 old_color_clear_value[1],
1449 old_color_clear_value[2],
1450 old_color_clear_value[3]);
1451 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1452 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1453 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1454 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1457 glDisable(GL_SCISSOR_TEST);
1458 checkGLcall("glDisable");
1463 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1464 ICOM_THIS(IDirect3DDevice8Impl,iface);
1467 /* Most of this routine, comments included copied from ddraw tree initially: */
1468 TRACE("(%p) : State=%d\n", This, d3dts);
1470 /* Handle recording of state blocks */
1471 if (This->isRecordingState) {
1472 TRACE("Recording... not performing anything\n");
1473 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1474 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1475 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1480 * if the new matrix is the same as the current one,
1481 * we cut off any further processing. this seems to be a reasonable
1482 * optimization because as was noticed, some apps (warcraft3 for example)
1483 * tend towards setting the same matrix repeatedly for some dumb reason.
1485 * From here on we assume that the new matrix is different, wherever it matters
1488 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1489 TRACE("The app is setting the same matrix over again\n");
1492 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1496 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1497 where ViewMat = Camera space, WorldMat = world space.
1499 In OpenGL, camera and world space is combined into GL_MODELVIEW
1500 matrix. The Projection matrix stay projection matrix.
1503 /* Capture the times we can just ignore the change */
1504 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1505 This->modelview_valid = FALSE;
1508 } else if (d3dts == D3DTS_PROJECTION) {
1509 This->proj_valid = FALSE;
1512 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1513 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1514 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1518 /* Chances are we really are going to have to change a matrix */
1521 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1522 if (d3dts < GL_LIMITS(textures)) {
1523 int tex = d3dts - D3DTS_TEXTURE0;
1524 #if defined(GL_VERSION_1_3)
1525 glActiveTexture(GL_TEXTURE0 + tex);
1526 checkGLcall("glActiveTexture");
1528 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1529 checkGLcall("glActiveTextureARB");
1531 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1534 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1536 PLIGHTINFOEL *lightChain = NULL;
1537 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1538 This->modelview_valid = FALSE;
1539 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1540 glMatrixMode(GL_MODELVIEW);
1541 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1543 glLoadMatrixf((float *)lpmatrix);
1544 checkGLcall("glLoadMatrixf(...)");
1546 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1547 * NOTE: We have to reset the positions even if the light/plane is not currently
1548 * enabled, since the call to enable it will not reset the position.
1549 * NOTE2: Apparently texture transforms do NOT need reapplying
1553 lightChain = This->StateBlock->lights;
1554 while (lightChain && lightChain->glIndex != -1) {
1555 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1556 checkGLcall("glLightfv posn");
1557 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1558 checkGLcall("glLightfv dirn");
1559 lightChain = lightChain->next;
1561 /* Reset Clipping Planes if clipping is enabled */
1562 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1563 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1564 checkGLcall("glClipPlane");
1568 } else { /* What was requested!?? */
1569 WARN("invalid matrix specified: %i\n", d3dts);
1573 /* Release lock, all done */
1578 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1579 ICOM_THIS(IDirect3DDevice8Impl,iface);
1580 TRACE("(%p) : for State %d\n", This, State);
1581 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1585 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1586 D3DMATRIX *mat = NULL;
1589 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1590 but works regardless of recording being on.
1591 If this is found to be wrong, change to StateBlock. */
1592 ICOM_THIS(IDirect3DDevice8Impl,iface);
1593 TRACE("(%p) : For state %u\n", This, State);
1595 if (State < HIGHEST_TRANSFORMSTATE)
1597 mat = &This->UpdateStateBlock->transforms[State];
1599 FIXME("Unhandled transform state!!\n");
1602 /* Copied from ddraw code: */
1603 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);
1604 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);
1605 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);
1606 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);
1608 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);
1609 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);
1610 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);
1611 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);
1613 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);
1614 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);
1615 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);
1616 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);
1618 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);
1619 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);
1620 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);
1621 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);
1623 /* Apply change via set transform - will reapply to eg. lights this way */
1624 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1627 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1628 ICOM_THIS(IDirect3DDevice8Impl,iface);
1630 TRACE("(%p)\n", This);
1631 This->UpdateStateBlock->Changed.viewport = TRUE;
1632 This->UpdateStateBlock->Set.viewport = TRUE;
1633 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1635 /* Handle recording of state blocks */
1636 if (This->isRecordingState) {
1637 TRACE("Recording... not performing anything\n");
1643 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1644 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1646 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1647 checkGLcall("glDepthRange");
1648 /* Note: GL requires lower left, DirectX supplies upper left */
1649 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1650 pViewport->Width, pViewport->Height);
1651 checkGLcall("glViewport");
1658 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1659 ICOM_THIS(IDirect3DDevice8Impl,iface);
1660 TRACE("(%p)\n", This);
1661 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1665 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1666 ICOM_THIS(IDirect3DDevice8Impl,iface);
1668 This->UpdateStateBlock->Changed.material = TRUE;
1669 This->UpdateStateBlock->Set.material = TRUE;
1670 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1672 /* Handle recording of state blocks */
1673 if (This->isRecordingState) {
1674 TRACE("Recording... not performing anything\n");
1679 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1680 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1681 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1682 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1683 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1685 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1686 checkGLcall("glMaterialfv");
1687 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1688 checkGLcall("glMaterialfv");
1690 /* Only change material color if specular is enabled, otherwise it is set to black */
1691 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1692 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1693 checkGLcall("glMaterialfv");
1695 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1696 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1697 checkGLcall("glMaterialfv");
1699 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1700 checkGLcall("glMaterialfv");
1701 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1702 checkGLcall("glMaterialf");
1707 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1708 ICOM_THIS(IDirect3DDevice8Impl,iface);
1709 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1710 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1711 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1712 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1713 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1714 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1718 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1719 you can reference any indexes you want as long as that number max are enabled are any
1720 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1721 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1722 but when recording, just build a chain pretty much of commands to be replayed. */
1724 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1726 PLIGHTINFOEL *object, *temp;
1728 ICOM_THIS(IDirect3DDevice8Impl,iface);
1729 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1731 /* If recording state block, just add to end of lights chain */
1732 if (This->isRecordingState) {
1733 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1734 if (NULL == object) {
1735 return D3DERR_OUTOFVIDEOMEMORY;
1737 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1738 object->OriginalIndex = Index;
1739 object->glIndex = -1;
1740 object->changed = TRUE;
1742 /* Add to the END of the chain of lights changes to be replayed */
1743 if (This->UpdateStateBlock->lights == NULL) {
1744 This->UpdateStateBlock->lights = object;
1746 temp = This->UpdateStateBlock->lights;
1747 while (temp->next != NULL) temp=temp->next;
1748 temp->next = object;
1750 TRACE("Recording... not performing anything more\n");
1754 /* Ok, not recording any longer so do real work */
1755 object = This->StateBlock->lights;
1756 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1758 /* If we didn't find it in the list of lights, time to add it */
1759 if (object == NULL) {
1760 PLIGHTINFOEL *insertAt,*prevPos;
1762 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1763 if (NULL == object) {
1764 return D3DERR_OUTOFVIDEOMEMORY;
1766 object->OriginalIndex = Index;
1767 object->glIndex = -1;
1769 /* Add it to the front of list with the idea that lights will be changed as needed
1770 BUT after any lights currently assigned GL indexes */
1771 insertAt = This->StateBlock->lights;
1773 while (insertAt != NULL && insertAt->glIndex != -1) {
1775 insertAt = insertAt->next;
1778 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1779 This->StateBlock->lights = object;
1780 } else if (insertAt == NULL) { /* End of list */
1781 prevPos->next = object;
1782 object->prev = prevPos;
1783 } else { /* Middle of chain */
1784 if (prevPos == NULL) {
1785 This->StateBlock->lights = object;
1787 prevPos->next = object;
1789 object->prev = prevPos;
1790 object->next = insertAt;
1791 insertAt->prev = object;
1795 /* Initialze the object */
1796 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,
1797 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1798 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1799 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1800 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1801 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1802 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1804 /* Save away the information */
1805 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1807 switch (pLight->Type) {
1808 case D3DLIGHT_POINT:
1810 object->lightPosn[0] = pLight->Position.x;
1811 object->lightPosn[1] = pLight->Position.y;
1812 object->lightPosn[2] = pLight->Position.z;
1813 object->lightPosn[3] = 1.0f;
1814 object->cutoff = 180.0f;
1818 case D3DLIGHT_DIRECTIONAL:
1820 object->lightPosn[0] = -pLight->Direction.x;
1821 object->lightPosn[1] = -pLight->Direction.y;
1822 object->lightPosn[2] = -pLight->Direction.z;
1823 object->lightPosn[3] = 0.0;
1824 object->exponent = 0.0f;
1825 object->cutoff = 180.0f;
1830 object->lightPosn[0] = pLight->Position.x;
1831 object->lightPosn[1] = pLight->Position.y;
1832 object->lightPosn[2] = pLight->Position.z;
1833 object->lightPosn[3] = 1.0;
1836 object->lightDirn[0] = pLight->Direction.x;
1837 object->lightDirn[1] = pLight->Direction.y;
1838 object->lightDirn[2] = pLight->Direction.z;
1839 object->lightDirn[3] = 1.0;
1842 * opengl-ish and d3d-ish spot lights use too different models for the
1843 * light "intensity" as a function of the angle towards the main light direction,
1844 * so we only can approximate very roughly.
1845 * however spot lights are rather rarely used in games (if ever used at all).
1846 * furthermore if still used, probably nobody pays attention to such details.
1848 if (pLight->Falloff == 0) {
1851 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1853 if (rho < 0.0001) rho = 0.0001f;
1854 object->exponent = -0.3/log(cos(rho/2));
1855 object->cutoff = pLight->Phi*90/M_PI;
1861 FIXME("Unrecognized light type %d\n", pLight->Type);
1864 /* Update the live definitions if the light is currently assigned a glIndex */
1865 if (object->glIndex != -1) {
1866 setup_light(iface, object->glIndex, object);
1870 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1871 PLIGHTINFOEL *lightInfo = NULL;
1872 ICOM_THIS(IDirect3DDevice8Impl,iface);
1873 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1875 /* Locate the light in the live lights */
1876 lightInfo = This->StateBlock->lights;
1877 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1879 if (lightInfo == NULL) {
1880 TRACE("Light information requested but light not defined\n");
1881 return D3DERR_INVALIDCALL;
1884 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1887 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1888 PLIGHTINFOEL *lightInfo = NULL;
1889 ICOM_THIS(IDirect3DDevice8Impl,iface);
1890 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1892 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1893 if (This->isRecordingState) {
1894 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1895 if (NULL == lightInfo) {
1896 return D3DERR_OUTOFVIDEOMEMORY;
1898 lightInfo->OriginalIndex = Index;
1899 lightInfo->glIndex = -1;
1900 lightInfo->enabledChanged = TRUE;
1902 /* Add to the END of the chain of lights changes to be replayed */
1903 if (This->UpdateStateBlock->lights == NULL) {
1904 This->UpdateStateBlock->lights = lightInfo;
1906 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1907 while (temp->next != NULL) temp=temp->next;
1908 temp->next = lightInfo;
1910 TRACE("Recording... not performing anything more\n");
1914 /* Not recording... So, locate the light in the live lights */
1915 lightInfo = This->StateBlock->lights;
1916 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1918 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1919 if (lightInfo == NULL) {
1920 D3DLIGHT8 lightParms;
1921 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1922 wait until someone confirms it seems to work! */
1923 TRACE("Light enabled requested but light not defined, so defining one!\n");
1924 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1925 lightParms.Diffuse.r = 1.0;
1926 lightParms.Diffuse.g = 1.0;
1927 lightParms.Diffuse.b = 1.0;
1928 lightParms.Diffuse.a = 0.0;
1929 lightParms.Specular.r = 0.0;
1930 lightParms.Specular.g = 0.0;
1931 lightParms.Specular.b = 0.0;
1932 lightParms.Specular.a = 0.0;
1933 lightParms.Ambient.r = 0.0;
1934 lightParms.Ambient.g = 0.0;
1935 lightParms.Ambient.b = 0.0;
1936 lightParms.Ambient.a = 0.0;
1937 lightParms.Position.x = 0.0;
1938 lightParms.Position.y = 0.0;
1939 lightParms.Position.z = 0.0;
1940 lightParms.Direction.x = 0.0;
1941 lightParms.Direction.y = 0.0;
1942 lightParms.Direction.z = 1.0;
1943 lightParms.Range = 0.0;
1944 lightParms.Falloff = 0.0;
1945 lightParms.Attenuation0 = 0.0;
1946 lightParms.Attenuation1 = 0.0;
1947 lightParms.Attenuation2 = 0.0;
1948 lightParms.Theta = 0.0;
1949 lightParms.Phi = 0.0;
1950 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1952 /* Search for it again! Should be fairly quick as near head of list */
1953 lightInfo = This->StateBlock->lights;
1954 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1955 if (lightInfo == NULL) {
1956 FIXME("Adding default lights has failed dismally\n");
1957 return D3DERR_INVALIDCALL;
1961 /* OK, we now have a light... */
1962 if (Enable == FALSE) {
1964 /* If we are disabling it, check it was enabled, and
1965 still only do something if it has assigned a glIndex (which it should have!) */
1966 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1967 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1969 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1970 checkGLcall("glDisable GL_LIGHT0+Index");
1973 TRACE("Nothing to do as light was not enabled\n");
1975 lightInfo->lightEnabled = FALSE;
1978 /* We are enabling it. If it is enabled, its really simple */
1979 if (lightInfo->lightEnabled == TRUE) {
1981 TRACE("Nothing to do as light was enabled\n");
1983 /* If it already has a glIndex, its still simple */
1984 } else if (lightInfo->glIndex != -1) {
1985 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1986 lightInfo->lightEnabled = TRUE;
1988 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1989 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1992 /* Otherwise got to find space - lights are ordered gl indexes first */
1994 PLIGHTINFOEL *bsf = NULL;
1995 PLIGHTINFOEL *pos = This->StateBlock->lights;
1996 PLIGHTINFOEL *prev = NULL;
2000 /* Try to minimize changes as much as possible */
2001 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2003 /* Try to remember which index can be replaced if necessary */
2004 if (bsf==NULL && pos->lightEnabled == FALSE) {
2005 /* Found a light we can replace, save as best replacement */
2009 /* Step to next space */
2015 /* If we have too many active lights, fail the call */
2016 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2017 FIXME("Program requests too many concurrent lights\n");
2018 return D3DERR_INVALIDCALL;
2020 /* If we have allocated all lights, but not all are enabled,
2021 reuse one which is not enabled */
2022 } else if (Index == This->maxConcurrentLights) {
2023 /* use bsf - Simply swap the new light and the BSF one */
2024 PLIGHTINFOEL *bsfNext = bsf->next;
2025 PLIGHTINFOEL *bsfPrev = bsf->prev;
2028 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2029 if (bsf->prev != NULL) {
2030 bsf->prev->next = lightInfo;
2032 This->StateBlock->lights = lightInfo;
2035 /* If not side by side, lots of chains to update */
2036 if (bsf->next != lightInfo) {
2037 lightInfo->prev->next = bsf;
2038 bsf->next->prev = lightInfo;
2039 bsf->next = lightInfo->next;
2040 bsf->prev = lightInfo->prev;
2041 lightInfo->next = bsfNext;
2042 lightInfo->prev = bsfPrev;
2046 bsf->prev = lightInfo;
2047 bsf->next = lightInfo->next;
2048 lightInfo->next = bsf;
2049 lightInfo->prev = bsfPrev;
2054 glIndex = bsf->glIndex;
2056 lightInfo->glIndex = glIndex;
2057 lightInfo->lightEnabled = TRUE;
2059 /* Finally set up the light in gl itself */
2060 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2062 setup_light(iface, glIndex, lightInfo);
2063 glEnable(GL_LIGHT0 + glIndex);
2064 checkGLcall("glEnable GL_LIGHT0 new setup");
2067 /* If we reached the end of the allocated lights, with space in the
2068 gl lights, setup a new light */
2069 } else if (pos->glIndex == -1) {
2071 /* We reached the end of the allocated gl lights, so already
2072 know the index of the next one! */
2074 lightInfo->glIndex = glIndex;
2075 lightInfo->lightEnabled = TRUE;
2077 /* In an ideal world, its already in the right place */
2078 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2079 /* No need to move it */
2081 /* Remove this light from the list */
2082 lightInfo->prev->next = lightInfo->next;
2083 if (lightInfo->next != NULL) {
2084 lightInfo->next->prev = lightInfo->prev;
2087 /* Add in at appropriate place (inbetween prev and pos) */
2088 lightInfo->prev = prev;
2089 lightInfo->next = pos;
2091 This->StateBlock->lights = lightInfo;
2093 prev->next = lightInfo;
2096 pos->prev = lightInfo;
2100 /* Finally set up the light in gl itself */
2101 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2103 setup_light(iface, glIndex, lightInfo);
2104 glEnable(GL_LIGHT0 + glIndex);
2105 checkGLcall("glEnable GL_LIGHT0 new setup");
2113 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2115 PLIGHTINFOEL *lightInfo = NULL;
2116 ICOM_THIS(IDirect3DDevice8Impl,iface);
2117 TRACE("(%p) : for idx(%ld)\n", This, Index);
2119 /* Locate the light in the live lights */
2120 lightInfo = This->StateBlock->lights;
2121 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2123 if (lightInfo == NULL) {
2124 TRACE("Light enabled state requested but light not defined\n");
2125 return D3DERR_INVALIDCALL;
2127 *pEnable = lightInfo->lightEnabled;
2130 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2131 ICOM_THIS(IDirect3DDevice8Impl,iface);
2132 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2134 /* Validate Index */
2135 if (Index >= GL_LIMITS(clipplanes)) {
2136 TRACE("Application has requested clipplane this device doesn't support\n");
2137 return D3DERR_INVALIDCALL;
2140 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2141 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2142 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2143 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2144 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2145 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2147 /* Handle recording of state blocks */
2148 if (This->isRecordingState) {
2149 TRACE("Recording... not performing anything\n");
2157 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2158 glMatrixMode(GL_MODELVIEW);
2160 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2162 TRACE("Clipplane [%f,%f,%f,%f]\n",
2163 This->UpdateStateBlock->clipplane[Index][0],
2164 This->UpdateStateBlock->clipplane[Index][1],
2165 This->UpdateStateBlock->clipplane[Index][2],
2166 This->UpdateStateBlock->clipplane[Index][3]);
2167 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2168 checkGLcall("glClipPlane");
2176 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2177 ICOM_THIS(IDirect3DDevice8Impl,iface);
2178 TRACE("(%p) : for idx %ld\n", This, Index);
2180 /* Validate Index */
2181 if (Index >= GL_LIMITS(clipplanes)) {
2182 TRACE("Application has requested clipplane this device doesn't support\n");
2183 return D3DERR_INVALIDCALL;
2186 pPlane[0] = This->StateBlock->clipplane[Index][0];
2187 pPlane[1] = This->StateBlock->clipplane[Index][1];
2188 pPlane[2] = This->StateBlock->clipplane[Index][2];
2189 pPlane[3] = This->StateBlock->clipplane[Index][3];
2192 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2197 ICOM_THIS(IDirect3DDevice8Impl,iface);
2198 DWORD OldValue = This->StateBlock->renderstate[State];
2200 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2201 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2202 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2203 This->UpdateStateBlock->renderstate[State] = Value;
2205 /* Handle recording of state blocks */
2206 if (This->isRecordingState) {
2207 TRACE("Recording... not performing anything\n");
2214 case D3DRS_FILLMODE :
2215 switch ((D3DFILLMODE) Value) {
2216 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2217 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2218 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2220 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2222 checkGLcall("glPolygonMode (fillmode)");
2225 case D3DRS_LIGHTING :
2227 glEnable(GL_LIGHTING);
2228 checkGLcall("glEnable GL_LIGHTING");
2230 glDisable(GL_LIGHTING);
2231 checkGLcall("glDisable GL_LIGHTING");
2235 case D3DRS_ZENABLE :
2236 switch ((D3DZBUFFERTYPE) Value) {
2238 glDisable(GL_DEPTH_TEST);
2239 checkGLcall("glDisable GL_DEPTH_TEST");
2242 glEnable(GL_DEPTH_TEST);
2243 checkGLcall("glEnable GL_DEPTH_TEST");
2248 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
2252 case D3DRS_CULLMODE :
2254 /* If we are culling "back faces with clockwise vertices" then
2255 set front faces to be counter clockwise and enable culling
2257 switch ((D3DCULL) Value) {
2259 glDisable(GL_CULL_FACE);
2260 checkGLcall("glDisable GL_CULL_FACE");
2263 glEnable(GL_CULL_FACE);
2264 checkGLcall("glEnable GL_CULL_FACE");
2265 if (This->renderUpsideDown) {
2267 checkGLcall("glFrontFace GL_CW");
2269 glFrontFace(GL_CCW);
2270 checkGLcall("glFrontFace GL_CCW");
2272 glCullFace(GL_BACK);
2275 glEnable(GL_CULL_FACE);
2276 checkGLcall("glEnable GL_CULL_FACE");
2277 if (This->renderUpsideDown) {
2278 glFrontFace(GL_CCW);
2279 checkGLcall("glFrontFace GL_CCW");
2282 checkGLcall("glFrontFace GL_CW");
2284 glCullFace(GL_BACK);
2287 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2291 case D3DRS_SHADEMODE :
2292 switch ((D3DSHADEMODE) Value) {
2294 glShadeModel(GL_FLAT);
2295 checkGLcall("glShadeModel");
2297 case D3DSHADE_GOURAUD:
2298 glShadeModel(GL_SMOOTH);
2299 checkGLcall("glShadeModel");
2301 case D3DSHADE_PHONG:
2302 FIXME("D3DSHADE_PHONG isn't supported?\n");
2305 return D3DERR_INVALIDCALL;
2307 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2311 case D3DRS_DITHERENABLE :
2313 glEnable(GL_DITHER);
2314 checkGLcall("glEnable GL_DITHER");
2316 glDisable(GL_DITHER);
2317 checkGLcall("glDisable GL_DITHER");
2321 case D3DRS_ZWRITEENABLE :
2324 checkGLcall("glDepthMask");
2327 checkGLcall("glDepthMask");
2333 int glParm = GL_LESS;
2335 switch ((D3DCMPFUNC) Value) {
2336 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2337 case D3DCMP_LESS: glParm=GL_LESS; break;
2338 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2339 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2340 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2341 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2342 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2343 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2345 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2347 glDepthFunc(glParm);
2348 checkGLcall("glDepthFunc");
2352 case D3DRS_AMBIENT :
2355 D3DCOLORTOGLFLOAT4(Value, col);
2356 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2357 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2358 checkGLcall("glLightModel for MODEL_AMBIENT");
2363 case D3DRS_ALPHABLENDENABLE :
2366 checkGLcall("glEnable GL_BLEND");
2368 glDisable(GL_BLEND);
2369 checkGLcall("glDisable GL_BLEND");
2373 case D3DRS_SRCBLEND :
2374 case D3DRS_DESTBLEND :
2376 int newVal = GL_ZERO;
2378 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2379 case D3DBLEND_ONE : newVal = GL_ONE; break;
2380 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2381 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2382 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2383 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2384 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2385 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2386 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2387 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2388 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2390 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2391 This->srcBlend = newVal;
2392 This->dstBlend = newVal;
2395 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2396 This->srcBlend = newVal;
2397 This->dstBlend = newVal;
2400 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2403 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2404 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2405 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2406 glBlendFunc(This->srcBlend, This->dstBlend);
2408 checkGLcall("glBlendFunc");
2412 case D3DRS_ALPHATESTENABLE :
2414 glEnable(GL_ALPHA_TEST);
2415 checkGLcall("glEnable GL_ALPHA_TEST");
2417 glDisable(GL_ALPHA_TEST);
2418 checkGLcall("glDisable GL_ALPHA_TEST");
2422 case D3DRS_ALPHAFUNC :
2424 int glParm = GL_LESS;
2425 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2427 switch ((D3DCMPFUNC) Value) {
2428 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2429 case D3DCMP_LESS: glParm = GL_LESS; break;
2430 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2431 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2432 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2433 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2434 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2435 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2437 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2439 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2440 glAlphaFunc(glParm, ref);
2441 This->alphafunc = glParm;
2442 checkGLcall("glAlphaFunc");
2446 case D3DRS_ALPHAREF :
2448 int glParm = This->alphafunc;
2451 ref = ((float) Value) / 255.0f;
2452 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2453 glAlphaFunc(glParm, ref);
2454 checkGLcall("glAlphaFunc");
2458 case D3DRS_CLIPPLANEENABLE :
2459 case D3DRS_CLIPPING :
2461 /* Ensure we only do the changed clip planes */
2462 DWORD enable = 0xFFFFFFFF;
2463 DWORD disable = 0x00000000;
2465 /* If enabling / disabling all */
2466 if (State == D3DRS_CLIPPING) {
2468 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2471 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2475 enable = Value & ~OldValue;
2476 disable = ~Value & OldValue;
2479 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2480 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2481 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2482 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2483 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2484 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2486 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2487 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2488 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2489 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2490 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2491 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2495 case D3DRS_BLENDOP :
2497 int glParm = GL_FUNC_ADD;
2499 switch ((D3DBLENDOP) Value) {
2500 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2501 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2502 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2503 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2504 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2506 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2508 TRACE("glBlendEquation(%x)\n", glParm);
2509 glBlendEquation(glParm);
2510 checkGLcall("glBlendEquation");
2514 case D3DRS_TEXTUREFACTOR :
2518 /* Note the texture color applies to all textures whereas
2519 GL_TEXTURE_ENV_COLOR applies to active only */
2521 D3DCOLORTOGLFLOAT4(Value, col);
2522 /* Set the default alpha blend color */
2523 glBlendColor(col[0], col[1], col[2], col[3]);
2524 checkGLcall("glBlendColor");
2526 /* And now the default texture color as well */
2527 for (i = 0; i < GL_LIMITS(textures); i++) {
2529 /* Note the D3DRS value applies to all textures, but GL has one
2530 per texture, so apply it now ready to be used! */
2531 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2532 #if defined(GL_VERSION_1_3)
2533 glActiveTexture(GL_TEXTURE0 + i);
2535 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2537 checkGLcall("Activate texture.. to update const color");
2539 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2542 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2543 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2548 case D3DRS_SPECULARENABLE :
2550 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2551 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2552 specular color. This is wrong:
2553 Separate specular color means the specular colour is maintained separately, whereas
2554 single color means it is merged in. However in both cases they are being used to
2556 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2557 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2561 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2562 checkGLcall("glMaterialfv");
2563 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2564 glEnable(GL_COLOR_SUM_EXT);
2566 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2568 checkGLcall("glEnable(GL_COLOR_SUM)");
2570 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2572 /* for the case of enabled lighting: */
2573 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2574 checkGLcall("glMaterialfv");
2576 /* for the case of disabled lighting: */
2577 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2578 glDisable(GL_COLOR_SUM_EXT);
2580 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2582 checkGLcall("glDisable(GL_COLOR_SUM)");
2587 case D3DRS_STENCILENABLE :
2589 glEnable(GL_STENCIL_TEST);
2590 checkGLcall("glEnable GL_STENCIL_TEST");
2592 glDisable(GL_STENCIL_TEST);
2593 checkGLcall("glDisable GL_STENCIL_TEST");
2597 case D3DRS_STENCILFUNC :
2599 int glParm = GL_ALWAYS;
2600 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2601 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2603 switch ((D3DCMPFUNC) Value) {
2604 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2605 case D3DCMP_LESS: glParm=GL_LESS; break;
2606 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2607 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2608 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2609 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2610 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2611 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2613 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2615 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2616 This->stencilfunc = glParm;
2617 glStencilFunc(glParm, ref, mask);
2618 checkGLcall("glStencilFunc");
2622 case D3DRS_STENCILREF :
2624 int glParm = This->stencilfunc;
2626 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2629 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2630 glStencilFunc(glParm, ref, mask);
2631 checkGLcall("glStencilFunc");
2635 case D3DRS_STENCILMASK :
2637 int glParm = This->stencilfunc;
2638 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2639 GLuint mask = Value;
2641 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2642 glStencilFunc(glParm, ref, mask);
2643 checkGLcall("glStencilFunc");
2647 case D3DRS_STENCILFAIL :
2653 fail = StencilOp(Value);
2654 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2655 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2656 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2657 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2659 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2660 glStencilOp(fail, zfail, zpass);
2661 checkGLcall("glStencilOp(fail, zfail, zpass);");
2664 case D3DRS_STENCILZFAIL :
2670 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2671 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2672 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2673 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2674 zfail = StencilOp(Value);
2676 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2677 glStencilOp(fail, zfail, zpass);
2678 checkGLcall("glStencilOp(fail, zfail, zpass);");
2681 case D3DRS_STENCILPASS :
2687 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2688 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2689 zpass = StencilOp(Value);
2690 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2691 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2693 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2694 glStencilOp(fail, zfail, zpass);
2695 checkGLcall("glStencilOp(fail, zfail, zpass);");
2699 case D3DRS_STENCILWRITEMASK :
2701 glStencilMask(Value);
2702 TRACE("glStencilMask(%lu)\n", Value);
2703 checkGLcall("glStencilMask");
2707 case D3DRS_FOGENABLE :
2709 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2711 checkGLcall("glEnable GL_FOG");
2714 checkGLcall("glDisable GL_FOG");
2719 case D3DRS_RANGEFOGENABLE :
2722 TRACE("Enabled RANGEFOG");
2724 TRACE("Disabled RANGEFOG");
2729 case D3DRS_FOGCOLOR :
2732 D3DCOLORTOGLFLOAT4(Value, col);
2733 /* Set the default alpha blend color */
2734 glFogfv(GL_FOG_COLOR, &col[0]);
2735 checkGLcall("glFog GL_FOG_COLOR");
2739 case D3DRS_FOGTABLEMODE :
2741 glHint(GL_FOG_HINT, GL_NICEST);
2743 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2744 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2745 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2746 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2748 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2750 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2751 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2756 case D3DRS_FOGVERTEXMODE :
2758 glHint(GL_FOG_HINT, GL_FASTEST);
2760 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2761 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2762 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2763 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2765 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2767 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2768 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2773 case D3DRS_FOGSTART :
2776 glFogfv(GL_FOG_START, &tmpvalue.f);
2777 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2778 TRACE("Fog Start == %f\n", tmpvalue.f);
2785 glFogfv(GL_FOG_END, &tmpvalue.f);
2786 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2787 TRACE("Fog End == %f\n", tmpvalue.f);
2791 case D3DRS_FOGDENSITY :
2794 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2795 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2799 case D3DRS_VERTEXBLEND :
2801 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2802 TRACE("Vertex Blending state to %ld\n", Value);
2806 case D3DRS_TWEENFACTOR :
2809 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2810 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2814 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2816 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2820 case D3DRS_COLORVERTEX :
2821 case D3DRS_DIFFUSEMATERIALSOURCE :
2822 case D3DRS_SPECULARMATERIALSOURCE :
2823 case D3DRS_AMBIENTMATERIALSOURCE :
2824 case D3DRS_EMISSIVEMATERIALSOURCE :
2826 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2828 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2829 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2830 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2831 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2832 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2833 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2835 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2836 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2837 Parm = GL_AMBIENT_AND_DIFFUSE;
2841 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2843 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2845 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2852 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2854 This->tracking_color = NEEDS_TRACKING;
2855 This->tracking_parm = Parm;
2859 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2864 case D3DRS_LINEPATTERN :
2870 tmppattern.d = Value;
2872 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2874 if (tmppattern.lp.wRepeatFactor) {
2875 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2876 checkGLcall("glLineStipple(repeat, linepattern)");
2877 glEnable(GL_LINE_STIPPLE);
2878 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2880 glDisable(GL_LINE_STIPPLE);
2881 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2890 TRACE("ZBias value %f\n", tmpvalue.f);
2891 glPolygonOffset(0, -tmpvalue.f);
2892 checkGLcall("glPolygonOffset(0, -Value)");
2893 glEnable(GL_POLYGON_OFFSET_FILL);
2894 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2895 glEnable(GL_POLYGON_OFFSET_LINE);
2896 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2897 glEnable(GL_POLYGON_OFFSET_POINT);
2898 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2900 glDisable(GL_POLYGON_OFFSET_FILL);
2901 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2902 glDisable(GL_POLYGON_OFFSET_LINE);
2903 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2904 glDisable(GL_POLYGON_OFFSET_POINT);
2905 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2910 case D3DRS_NORMALIZENORMALS :
2912 glEnable(GL_NORMALIZE);
2913 checkGLcall("glEnable(GL_NORMALIZE);");
2915 glDisable(GL_NORMALIZE);
2916 checkGLcall("glDisable(GL_NORMALIZE);");
2920 case D3DRS_POINTSIZE :
2922 TRACE("Set point size to %f\n", tmpvalue.f);
2923 glPointSize(tmpvalue.f);
2924 checkGLcall("glPointSize(...);");
2927 case D3DRS_POINTSIZE_MIN :
2928 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2930 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2931 checkGLcall("glPointParameterfEXT(...);");
2933 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2937 case D3DRS_POINTSIZE_MAX :
2938 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2940 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2941 checkGLcall("glPointParameterfEXT(...);");
2943 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2947 case D3DRS_POINTSCALE_A :
2948 case D3DRS_POINTSCALE_B :
2949 case D3DRS_POINTSCALE_C :
2950 case D3DRS_POINTSCALEENABLE :
2952 /* If enabled, supply the parameters, otherwise fall back to defaults */
2953 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2954 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2955 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2956 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2957 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2959 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2960 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2961 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2963 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2966 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2967 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2968 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2969 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2971 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2977 case D3DRS_COLORWRITEENABLE :
2978 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2979 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2980 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2981 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2982 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2983 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2984 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2985 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2986 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2987 checkGLcall("glColorMask(...)");
2990 /* Unhandled yet...! */
2991 case D3DRS_LASTPIXEL :
2992 case D3DRS_ZVISIBLE :
2993 case D3DRS_EDGEANTIALIAS :
3002 case D3DRS_LOCALVIEWER :
3003 case D3DRS_SOFTWAREVERTEXPROCESSING :
3004 case D3DRS_POINTSPRITEENABLE :
3005 case D3DRS_MULTISAMPLEANTIALIAS :
3006 case D3DRS_MULTISAMPLEMASK :
3007 case D3DRS_PATCHEDGESTYLE :
3008 case D3DRS_PATCHSEGMENTS :
3009 case D3DRS_DEBUGMONITORTOKEN :
3010 case D3DRS_POSITIONORDER :
3011 case D3DRS_NORMALORDER :
3012 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3013 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3016 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3023 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3024 ICOM_THIS(IDirect3DDevice8Impl,iface);
3025 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3026 *pValue = This->StateBlock->renderstate[State];
3029 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3030 ICOM_THIS(IDirect3DDevice8Impl,iface);
3032 TRACE("(%p)\n", This);
3034 return IDirect3DDeviceImpl_BeginStateBlock(This);
3036 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3037 IDirect3DStateBlockImpl* pSB;
3038 ICOM_THIS(IDirect3DDevice8Impl,iface);
3041 TRACE("(%p)\n", This);
3043 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3044 *pToken = (DWORD) pSB;
3048 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3049 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3050 ICOM_THIS(IDirect3DDevice8Impl,iface);
3052 TRACE("(%p)\n", This);
3054 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3057 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3058 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3059 ICOM_THIS(IDirect3DDevice8Impl,iface);
3061 TRACE("(%p)\n", This);
3063 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3065 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3066 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3067 ICOM_THIS(IDirect3DDevice8Impl,iface);
3069 TRACE("(%p)\n", This);
3071 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3074 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3075 IDirect3DStateBlockImpl* pSB;
3076 ICOM_THIS(IDirect3DDevice8Impl,iface);
3079 TRACE("(%p) : for type %d\n", This, Type);
3081 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3082 *pToken = (DWORD) pSB;
3086 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3087 ICOM_THIS(IDirect3DDevice8Impl,iface);
3088 FIXME("(%p) : stub\n", This); return D3D_OK;
3090 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3091 ICOM_THIS(IDirect3DDevice8Impl,iface);
3092 FIXME("(%p) : stub\n", This); return D3D_OK;
3094 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3095 ICOM_THIS(IDirect3DDevice8Impl,iface);
3096 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3097 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3099 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3102 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3104 IDirect3DBaseTexture8 *oldTxt;
3105 BOOL reapplyStates = TRUE;
3106 DWORD oldTextureDimensions = -1;
3107 DWORD reapplyFlags = 0;
3109 ICOM_THIS(IDirect3DDevice8Impl,iface);
3110 D3DRESOURCETYPE textureType;
3112 oldTxt = This->UpdateStateBlock->textures[Stage];
3113 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3115 /* Reject invalid texture units */
3116 if (Stage >= GL_LIMITS(textures)) {
3117 TRACE("Attempt to access invalid texture rejected\n");
3118 return D3DERR_INVALIDCALL;
3121 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3122 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3123 This->UpdateStateBlock->textures[Stage] = pTexture;
3125 /* Handle recording of state blocks */
3126 if (This->isRecordingState) {
3127 TRACE("Recording... not performing anything\n");
3131 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3134 /* Make appropriate texture active */
3135 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3136 #if defined(GL_VERSION_1_3)
3137 glActiveTexture(GL_TEXTURE0 + Stage);
3138 checkGLcall("glActiveTexture");
3140 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3141 checkGLcall("glActiveTextureARB");
3143 } else if (Stage>0) {
3144 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3147 /* Decrement the count of the previous texture */
3148 if (NULL != oldTxt) {
3149 IDirect3DBaseTexture8Impl_Release(oldTxt);
3152 if (NULL != pTexture) {
3153 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3155 /* Now setup the texture appropraitly */
3156 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3158 if (textureType == D3DRTYPE_TEXTURE) {
3159 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3160 TRACE("Skipping setting texture as old == new\n");
3161 reapplyStates = FALSE;
3163 /* Standard 2D texture */
3164 TRACE("Standard 2d texture\n");
3165 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3167 /* Load up the texture now */
3168 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3170 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3171 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3172 TRACE("Skipping setting texture as old == new\n");
3173 reapplyStates = FALSE;
3175 /* Standard 3D (volume) texture */
3176 TRACE("Standard 3d texture\n");
3177 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3179 /* Load up the texture now */
3180 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3182 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3183 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3184 TRACE("Skipping setting texture as old == new\n");
3185 reapplyStates = FALSE;
3187 /* Standard Cube texture */
3188 TRACE("Standard Cube texture\n");
3189 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3191 /* Load up the texture now */
3192 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3195 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3198 TRACE("Setting to no texture (ie default texture)\n");
3199 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3200 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3201 checkGLcall("glBindTexture");
3202 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3205 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3206 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3207 glDisable(oldTextureDimensions);
3208 checkGLcall("Disable oldTextureDimensions");
3209 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3210 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3211 checkGLcall("glEnable new texture dimensions");
3214 /* If Alpha arg1 is texture then handle the special case when there changes between a
3215 texture and no texture - See comments in set_tex_op */
3216 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3217 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3219 reapplyFlags |= REAPPLY_ALPHAOP;
3224 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3225 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3226 if (reapplyStates) {
3227 setupTextureStates(iface, Stage, reapplyFlags);
3235 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3236 ICOM_THIS(IDirect3DDevice8Impl,iface);
3237 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3238 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3242 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3243 ICOM_THIS(IDirect3DDevice8Impl,iface);
3249 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3251 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3253 /* Reject invalid texture units */
3254 if (Stage >= GL_LIMITS(textures)) {
3255 TRACE("Attempt to access invalid texture rejected\n");
3256 return D3DERR_INVALIDCALL;
3259 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3260 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3261 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3263 /* Handle recording of state blocks */
3264 if (This->isRecordingState) {
3265 TRACE("Recording... not performing anything\n");
3271 /* Make appropriate texture active */
3272 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3273 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3274 #if defined(GL_VERSION_1_3)
3275 glActiveTexture(GL_TEXTURE0 + Stage);
3276 vcheckGLcall("glActiveTexture");
3278 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3279 vcheckGLcall("glActiveTextureARB");
3281 } else if (Stage > 0) {
3282 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3287 case D3DTSS_MINFILTER :
3288 case D3DTSS_MIPFILTER :
3290 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3291 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3292 GLint realVal = GL_LINEAR;
3294 if (ValueMIN == D3DTEXF_NONE) {
3295 /* Doesn't really make sense - Windows just seems to disable
3296 mipmapping when this occurs */
3297 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3298 realVal = GL_LINEAR;
3299 } else if (ValueMIN == D3DTEXF_POINT) {
3301 if (ValueMIP == D3DTEXF_NONE) {
3302 realVal = GL_NEAREST;
3303 } else if (ValueMIP == D3DTEXF_POINT) {
3304 realVal = GL_NEAREST_MIPMAP_NEAREST;
3305 } else if (ValueMIP == D3DTEXF_LINEAR) {
3306 realVal = GL_NEAREST_MIPMAP_LINEAR;
3308 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3309 realVal = GL_NEAREST;
3311 } else if (ValueMIN == D3DTEXF_LINEAR) {
3313 if (ValueMIP == D3DTEXF_NONE) {
3314 realVal = GL_LINEAR;
3315 } else if (ValueMIP == D3DTEXF_POINT) {
3316 realVal = GL_LINEAR_MIPMAP_NEAREST;
3317 } else if (ValueMIP == D3DTEXF_LINEAR) {
3318 realVal = GL_LINEAR_MIPMAP_LINEAR;
3320 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3321 realVal = GL_LINEAR;
3323 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3324 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3325 if (ValueMIP == D3DTEXF_NONE) {
3326 realVal = GL_LINEAR_MIPMAP_LINEAR;
3327 } else if (ValueMIP == D3DTEXF_POINT) {
3328 realVal = GL_LINEAR_MIPMAP_NEAREST;
3329 } else if (ValueMIP == D3DTEXF_LINEAR) {
3330 realVal = GL_LINEAR_MIPMAP_LINEAR;
3332 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3333 realVal = GL_LINEAR;
3336 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3337 realVal = GL_LINEAR;
3340 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3341 realVal = GL_LINEAR_MIPMAP_LINEAR;
3344 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3345 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3346 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3348 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3350 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3351 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3352 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3353 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3354 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3359 case D3DTSS_MAGFILTER :
3361 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3362 GLint realVal = GL_NEAREST;
3364 if (ValueMAG == D3DTEXF_POINT) {
3365 realVal = GL_NEAREST;
3366 } else if (ValueMAG == D3DTEXF_LINEAR) {
3367 realVal = GL_LINEAR;
3368 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3369 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3370 realVal = GL_LINEAR;
3372 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3373 realVal = GL_NEAREST;
3376 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3377 realVal = GL_NEAREST;
3379 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3380 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3381 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3383 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3385 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3386 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3387 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3388 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3389 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3394 case D3DTSS_MAXMIPLEVEL :
3397 * Not really the same, but the more apprioprate than nothing
3399 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3400 GL_TEXTURE_BASE_LEVEL,
3401 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3402 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3406 case D3DTSS_MAXANISOTROPY :
3408 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3409 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3410 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3411 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3412 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3417 case D3DTSS_MIPMAPLODBIAS :
3419 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3421 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3422 GL_TEXTURE_LOD_BIAS_EXT,
3424 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3429 case D3DTSS_ALPHAOP :
3430 case D3DTSS_COLOROP :
3433 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3434 /* TODO: Disable by making this and all later levels disabled */
3435 glDisable(GL_TEXTURE_1D);
3436 checkGLcall("Disable GL_TEXTURE_1D");
3437 glDisable(GL_TEXTURE_2D);
3438 checkGLcall("Disable GL_TEXTURE_2D");
3439 glDisable(GL_TEXTURE_3D);
3440 checkGLcall("Disable GL_TEXTURE_3D");
3441 break; /* Don't bother setting the texture operations */
3443 /* Enable only the appropriate texture dimension */
3444 if (Type == D3DTSS_COLOROP) {
3445 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3446 glEnable(GL_TEXTURE_1D);
3447 checkGLcall("Enable GL_TEXTURE_1D");
3449 glDisable(GL_TEXTURE_1D);
3450 checkGLcall("Disable GL_TEXTURE_1D");
3452 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3453 glEnable(GL_TEXTURE_2D);
3454 checkGLcall("Enable GL_TEXTURE_2D");
3456 glDisable(GL_TEXTURE_2D);
3457 checkGLcall("Disable GL_TEXTURE_2D");
3459 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3460 glEnable(GL_TEXTURE_3D);
3461 checkGLcall("Enable GL_TEXTURE_3D");
3463 glDisable(GL_TEXTURE_3D);
3464 checkGLcall("Disable GL_TEXTURE_3D");
3466 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3467 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3468 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3470 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3471 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3475 /* Drop through... (Except disable case) */
3476 case D3DTSS_COLORARG0 :
3477 case D3DTSS_COLORARG1 :
3478 case D3DTSS_COLORARG2 :
3479 case D3DTSS_ALPHAARG0 :
3480 case D3DTSS_ALPHAARG1 :
3481 case D3DTSS_ALPHAARG2 :
3483 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3484 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3486 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3487 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3488 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3489 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3491 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3492 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3493 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3494 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3500 case D3DTSS_ADDRESSU :
3501 case D3DTSS_ADDRESSV :
3502 case D3DTSS_ADDRESSW :
3504 GLint wrapParm = GL_REPEAT;
3507 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3508 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3509 case D3DTADDRESS_BORDER:
3511 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3512 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3514 /* FIXME: Not right, but better */
3515 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3516 wrapParm = GL_REPEAT;
3520 case D3DTADDRESS_MIRROR:
3522 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3523 wrapParm = GL_MIRRORED_REPEAT_ARB;
3525 /* Unsupported in OpenGL pre-1.4 */
3526 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3527 wrapParm = GL_REPEAT;
3531 case D3DTADDRESS_MIRRORONCE:
3533 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3534 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3536 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3537 wrapParm = GL_REPEAT;
3543 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3544 wrapParm = GL_REPEAT;
3548 case D3DTSS_ADDRESSU:
3549 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3550 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3551 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3553 case D3DTSS_ADDRESSV:
3554 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3555 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3556 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3558 case D3DTSS_ADDRESSW:
3559 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3560 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3561 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3564 break; /** stupic compilator */
3569 case D3DTSS_BORDERCOLOR :
3572 D3DCOLORTOGLFLOAT4(Value, col);
3573 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3574 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3575 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3579 case D3DTSS_TEXCOORDINDEX :
3581 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3583 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3584 one flag, you can still specify an index value, which the system uses to
3585 determine the texture wrapping mode.
3586 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3587 means use the vertex position (camera-space) as the input texture coordinates
3588 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3589 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3590 to the TEXCOORDINDEX value */
3593 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3595 switch (Value & 0xFFFF0000) {
3596 case D3DTSS_TCI_PASSTHRU:
3597 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3598 glDisable(GL_TEXTURE_GEN_S);
3599 glDisable(GL_TEXTURE_GEN_T);
3600 glDisable(GL_TEXTURE_GEN_R);
3601 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3604 case D3DTSS_TCI_CAMERASPACEPOSITION:
3605 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3606 as the input texture coordinates for this stage's texture transformation. This
3607 equates roughly to EYE_LINEAR */
3609 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3610 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3611 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3612 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3613 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3615 glMatrixMode(GL_MODELVIEW);
3618 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3619 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3620 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3621 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3624 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3625 glEnable(GL_TEXTURE_GEN_S);
3626 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3627 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3628 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3629 glEnable(GL_TEXTURE_GEN_T);
3630 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3631 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3632 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3633 glEnable(GL_TEXTURE_GEN_R);
3634 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3635 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3636 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3640 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3641 case D3DTSS_TCI_CAMERASPACENORMAL:
3643 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3644 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3645 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3646 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3647 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3649 glMatrixMode(GL_MODELVIEW);
3652 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3653 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3654 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3655 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3658 glEnable(GL_TEXTURE_GEN_S);
3659 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3660 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3661 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3662 glEnable(GL_TEXTURE_GEN_T);
3663 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3664 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3665 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3666 glEnable(GL_TEXTURE_GEN_R);
3667 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3668 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3669 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3674 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3675 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3678 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3679 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3680 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3681 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3682 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3684 glMatrixMode(GL_MODELVIEW);
3687 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3688 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3689 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3690 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3693 glEnable(GL_TEXTURE_GEN_S);
3694 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3695 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3696 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3697 glEnable(GL_TEXTURE_GEN_T);
3698 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3699 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3700 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3701 glEnable(GL_TEXTURE_GEN_R);
3702 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3703 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3704 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3709 /* Unhandled types: */
3712 /* ? disable GL_TEXTURE_GEN_n ? */
3713 glDisable(GL_TEXTURE_GEN_S);
3714 glDisable(GL_TEXTURE_GEN_T);
3715 glDisable(GL_TEXTURE_GEN_R);
3716 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3723 case D3DTSS_BUMPENVMAT00 :
3724 case D3DTSS_BUMPENVMAT01 :
3725 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3727 case D3DTSS_BUMPENVMAT10 :
3728 case D3DTSS_BUMPENVMAT11 :
3729 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3732 case D3DTSS_TEXTURETRANSFORMFLAGS :
3733 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3736 case D3DTSS_BUMPENVLSCALE :
3737 case D3DTSS_BUMPENVLOFFSET :
3738 case D3DTSS_RESULTARG :
3740 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3741 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3748 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3749 ICOM_THIS(IDirect3DDevice8Impl,iface);
3750 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3753 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3754 ICOM_THIS(IDirect3DDevice8Impl,iface);
3755 FIXME("(%p) : stub\n", This);
3758 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3759 ICOM_THIS(IDirect3DDevice8Impl,iface);
3760 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3761 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3762 if (PaletteNumber >= MAX_PALETTES) {
3763 return D3DERR_INVALIDCALL;
3765 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3768 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3769 ICOM_THIS(IDirect3DDevice8Impl,iface);
3770 if (PaletteNumber >= MAX_PALETTES) {
3771 return D3DERR_INVALIDCALL;
3773 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3774 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3775 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3778 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3779 ICOM_THIS(IDirect3DDevice8Impl,iface);
3780 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3781 if (PaletteNumber >= MAX_PALETTES) {
3782 return D3DERR_INVALIDCALL;
3784 This->currentPalette = PaletteNumber;
3786 #if defined(GL_EXT_paletted_texture)
3787 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3791 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3792 GL_RGBA, /* internal format */
3793 256, /* table size */
3794 GL_RGBA, /* table format */
3795 GL_UNSIGNED_BYTE, /* table type */
3796 This->palettes[PaletteNumber]);
3797 checkGLcall("glColorTableEXT");
3802 /* Delayed palette handling ... waiting for software emulation into preload code */
3807 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3808 ICOM_THIS(IDirect3DDevice8Impl,iface);
3809 *PaletteNumber = This->currentPalette;
3810 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3813 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3815 ICOM_THIS(IDirect3DDevice8Impl,iface);
3816 This->StateBlock->streamIsUP = FALSE;
3818 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3819 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3823 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3824 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3826 IDirect3DIndexBuffer8 *pIB;
3827 D3DINDEXBUFFER_DESC IdxBufDsc;
3829 ICOM_THIS(IDirect3DDevice8Impl,iface);
3830 pIB = This->StateBlock->pIndexData;
3831 This->StateBlock->streamIsUP = FALSE;
3833 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3834 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3835 minIndex, NumVertices, startIndex, primCount);
3837 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3838 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3844 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3849 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3850 ICOM_THIS(IDirect3DDevice8Impl,iface);
3852 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3853 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3855 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3857 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3858 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3859 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3860 This->StateBlock->streamIsUP = TRUE;
3861 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3862 This->StateBlock->stream_stride[0] = 0;
3863 This->StateBlock->stream_source[0] = NULL;
3865 /*stream zero settings set to null at end */
3868 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3869 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3870 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3871 UINT VertexStreamZeroStride) {
3873 ICOM_THIS(IDirect3DDevice8Impl,iface);
3874 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),
3875 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3877 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3878 if (IndexDataFormat == D3DFMT_INDEX16) {
3884 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3885 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3886 This->StateBlock->streamIsUP = TRUE;
3887 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3888 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3890 /*stream zero settings set to null at end */
3891 This->StateBlock->stream_source[0] = NULL;
3892 This->StateBlock->stream_stride[0] = 0;
3893 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3897 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3898 ICOM_THIS(IDirect3DDevice8Impl,iface);
3899 FIXME("(%p) : stub\n", This); return D3D_OK;
3901 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3902 ICOM_THIS(IDirect3DDevice8Impl,iface);
3903 IDirect3DVertexShaderImpl* object;
3904 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3908 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3909 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3910 return D3DERR_INVALIDCALL;
3912 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3913 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3914 return D3DERR_OUTOFVIDEOMEMORY;
3917 /** Create the Vertex Shader */
3918 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3919 /** TODO: check FAILED(res) */
3921 /** Create and Bind the Vertex Shader Declaration */
3922 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3923 /** TODO: check FAILED(res) */
3925 VertexShaders[i] = object;
3926 VertexShaderDeclarations[i] = attached_decl;
3927 *pHandle = VS_HIGHESTFIXEDFXF + i;
3928 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3932 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3933 ICOM_THIS(IDirect3DDevice8Impl,iface);
3935 This->UpdateStateBlock->VertexShader = Handle;
3936 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3937 This->UpdateStateBlock->Set.vertexShader = TRUE;
3939 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3940 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3941 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3942 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3943 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3944 } else { /* use a fvf, so desactivate the vshader decl */
3945 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3946 This->UpdateStateBlock->vertexShaderDecl = NULL;
3947 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3948 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3950 /* Handle recording of state blocks */
3951 if (This->isRecordingState) {
3952 TRACE("Recording... not performing anything\n");
3956 * TODO: merge HAL shaders context switching from prototype
3960 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3961 ICOM_THIS(IDirect3DDevice8Impl,iface);
3962 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3963 *pHandle = This->StateBlock->VertexShader;
3967 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3968 ICOM_THIS(IDirect3DDevice8Impl,iface);
3969 IDirect3DVertexShaderImpl* object;
3970 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3972 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3973 return D3DERR_INVALIDCALL;
3977 * Delete Vertex Shader
3979 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3980 if (NULL == object) {
3981 return D3DERR_INVALIDCALL;
3983 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3984 /* TODO: check validity of object */
3985 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3986 if (object->prgId != 0) {
3987 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
3989 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3990 HeapFree(GetProcessHeap(), 0, (void *)object);
3991 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3994 * Delete Vertex Shader Declaration
3996 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3997 if (NULL == attached_decl) {
3998 return D3DERR_INVALIDCALL;
4000 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4001 /* TODO: check validity of object */
4002 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4003 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4004 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4009 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4010 ICOM_THIS(IDirect3DDevice8Impl,iface);
4012 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4013 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4014 return D3DERR_INVALIDCALL;
4016 if (NULL == pConstantData) {
4017 return D3DERR_INVALIDCALL;
4019 if (ConstantCount > 1) {
4020 FLOAT* f = (FLOAT*)pConstantData;
4022 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4023 for (i = 0; i < ConstantCount; ++i) {
4024 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4028 FLOAT* f = (FLOAT*) pConstantData;
4029 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4031 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4032 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4035 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4036 ICOM_THIS(IDirect3DDevice8Impl,iface);
4038 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4039 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4040 return D3DERR_INVALIDCALL;
4042 if (NULL == pConstantData) {
4043 return D3DERR_INVALIDCALL;
4045 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4048 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4049 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4050 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4052 attached_decl = VERTEX_SHADER_DECL(Handle);
4053 if (NULL == attached_decl) {
4054 return D3DERR_INVALIDCALL;
4056 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4058 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4059 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
4060 IDirect3DVertexShaderImpl* object;
4062 object = VERTEX_SHADER(Handle);
4063 if (NULL == object) {
4064 return D3DERR_INVALIDCALL;
4066 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4069 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4070 ICOM_THIS(IDirect3DDevice8Impl,iface);
4071 IDirect3DIndexBuffer8 *oldIdxs;
4073 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4074 oldIdxs = This->StateBlock->pIndexData;
4076 This->UpdateStateBlock->Changed.Indices = TRUE;
4077 This->UpdateStateBlock->Set.Indices = TRUE;
4078 This->UpdateStateBlock->pIndexData = pIndexData;
4079 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4081 /* Handle recording of state blocks */
4082 if (This->isRecordingState) {
4083 TRACE("Recording... not performing anything\n");
4087 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4088 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4091 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4092 ICOM_THIS(IDirect3DDevice8Impl,iface);
4093 FIXME("(%p) : stub\n", This);
4095 *ppIndexData = This->StateBlock->pIndexData;
4096 /* up ref count on ppindexdata */
4097 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4098 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4102 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4103 ICOM_THIS(IDirect3DDevice8Impl,iface);
4104 IDirect3DPixelShaderImpl* object;
4108 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4109 if (NULL == pFunction || NULL == pHandle) {
4110 return D3DERR_INVALIDCALL;
4112 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4113 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4114 return D3DERR_OUTOFVIDEOMEMORY;
4117 /** Create the Pixel Shader */
4118 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4119 if (SUCCEEDED(res)) {
4120 PixelShaders[i] = object;
4121 *pHandle = VS_HIGHESTFIXEDFXF + i;
4124 *pHandle = 0xFFFFFFFF;
4127 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4128 ICOM_THIS(IDirect3DDevice8Impl,iface);
4130 This->UpdateStateBlock->PixelShader = Handle;
4131 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4132 This->UpdateStateBlock->Set.pixelShader = TRUE;
4134 /* Handle recording of state blocks */
4135 if (This->isRecordingState) {
4136 TRACE_(d3d_shader)("Recording... not performing anything\n");
4140 /* FIXME: Quieten when not being used */
4142 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4144 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
4149 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4150 ICOM_THIS(IDirect3DDevice8Impl,iface);
4151 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4152 *pHandle = This->StateBlock->PixelShader;
4156 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4157 ICOM_THIS(IDirect3DDevice8Impl,iface);
4158 IDirect3DPixelShaderImpl* object;
4160 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4161 return D3DERR_INVALIDCALL;
4163 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4164 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4165 /* TODO: check validity of object before free */
4166 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4167 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4168 HeapFree(GetProcessHeap(), 0, (void *)object);
4169 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4174 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4175 ICOM_THIS(IDirect3DDevice8Impl,iface);
4177 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4178 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4179 return D3DERR_INVALIDCALL;
4181 if (NULL == pConstantData) {
4182 return D3DERR_INVALIDCALL;
4184 if (ConstantCount > 1) {
4185 FLOAT* f = (FLOAT*)pConstantData;
4187 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4188 for (i = 0; i < ConstantCount; ++i) {
4189 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4193 FLOAT* f = (FLOAT*) pConstantData;
4194 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4196 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4197 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4200 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4201 ICOM_THIS(IDirect3DDevice8Impl,iface);
4203 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4204 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4205 return D3DERR_INVALIDCALL;
4207 if (NULL == pConstantData) {
4208 return D3DERR_INVALIDCALL;
4210 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4213 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4214 IDirect3DPixelShaderImpl* object;
4216 object = PIXEL_SHADER(Handle);
4217 if (NULL == object) {
4218 return D3DERR_INVALIDCALL;
4220 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4222 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4223 ICOM_THIS(IDirect3DDevice8Impl,iface);
4224 FIXME("(%p) : stub\n", This); return D3D_OK;
4226 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4227 ICOM_THIS(IDirect3DDevice8Impl,iface);
4228 FIXME("(%p) : stub\n", This); return D3D_OK;
4230 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4231 ICOM_THIS(IDirect3DDevice8Impl,iface);
4232 FIXME("(%p) : stub\n", This); return D3D_OK;
4235 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4236 IDirect3DVertexBuffer8 *oldSrc;
4237 ICOM_THIS(IDirect3DDevice8Impl,iface);
4239 oldSrc = This->StateBlock->stream_source[StreamNumber];
4240 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4242 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4243 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4244 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4245 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4247 /* Handle recording of state blocks */
4248 if (This->isRecordingState) {
4249 TRACE("Recording... not performing anything\n");
4253 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4254 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4257 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4258 ICOM_THIS(IDirect3DDevice8Impl,iface);
4259 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4260 *pStream = This->StateBlock->stream_source[StreamNumber];
4261 *pStride = This->StateBlock->stream_stride[StreamNumber];
4262 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4267 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
4269 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4270 IDirect3DDevice8Impl_QueryInterface,
4271 IDirect3DDevice8Impl_AddRef,
4272 IDirect3DDevice8Impl_Release,
4273 IDirect3DDevice8Impl_TestCooperativeLevel,
4274 IDirect3DDevice8Impl_GetAvailableTextureMem,
4275 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4276 IDirect3DDevice8Impl_GetDirect3D,
4277 IDirect3DDevice8Impl_GetDeviceCaps,
4278 IDirect3DDevice8Impl_GetDisplayMode,
4279 IDirect3DDevice8Impl_GetCreationParameters,
4280 IDirect3DDevice8Impl_SetCursorProperties,
4281 IDirect3DDevice8Impl_SetCursorPosition,
4282 IDirect3DDevice8Impl_ShowCursor,
4283 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4284 IDirect3DDevice8Impl_Reset,
4285 IDirect3DDevice8Impl_Present,
4286 IDirect3DDevice8Impl_GetBackBuffer,
4287 IDirect3DDevice8Impl_GetRasterStatus,
4288 IDirect3DDevice8Impl_SetGammaRamp,
4289 IDirect3DDevice8Impl_GetGammaRamp,
4290 IDirect3DDevice8Impl_CreateTexture,
4291 IDirect3DDevice8Impl_CreateVolumeTexture,
4292 IDirect3DDevice8Impl_CreateCubeTexture,
4293 IDirect3DDevice8Impl_CreateVertexBuffer,
4294 IDirect3DDevice8Impl_CreateIndexBuffer,
4295 IDirect3DDevice8Impl_CreateRenderTarget,
4296 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4297 IDirect3DDevice8Impl_CreateImageSurface,
4298 IDirect3DDevice8Impl_CopyRects,
4299 IDirect3DDevice8Impl_UpdateTexture,
4300 IDirect3DDevice8Impl_GetFrontBuffer,
4301 IDirect3DDevice8Impl_SetRenderTarget,
4302 IDirect3DDevice8Impl_GetRenderTarget,
4303 IDirect3DDevice8Impl_GetDepthStencilSurface,
4304 IDirect3DDevice8Impl_BeginScene,
4305 IDirect3DDevice8Impl_EndScene,
4306 IDirect3DDevice8Impl_Clear,
4307 IDirect3DDevice8Impl_SetTransform,
4308 IDirect3DDevice8Impl_GetTransform,
4309 IDirect3DDevice8Impl_MultiplyTransform,
4310 IDirect3DDevice8Impl_SetViewport,
4311 IDirect3DDevice8Impl_GetViewport,
4312 IDirect3DDevice8Impl_SetMaterial,
4313 IDirect3DDevice8Impl_GetMaterial,
4314 IDirect3DDevice8Impl_SetLight,
4315 IDirect3DDevice8Impl_GetLight,
4316 IDirect3DDevice8Impl_LightEnable,
4317 IDirect3DDevice8Impl_GetLightEnable,
4318 IDirect3DDevice8Impl_SetClipPlane,
4319 IDirect3DDevice8Impl_GetClipPlane,
4320 IDirect3DDevice8Impl_SetRenderState,
4321 IDirect3DDevice8Impl_GetRenderState,
4322 IDirect3DDevice8Impl_BeginStateBlock,
4323 IDirect3DDevice8Impl_EndStateBlock,
4324 IDirect3DDevice8Impl_ApplyStateBlock,
4325 IDirect3DDevice8Impl_CaptureStateBlock,
4326 IDirect3DDevice8Impl_DeleteStateBlock,
4327 IDirect3DDevice8Impl_CreateStateBlock,
4328 IDirect3DDevice8Impl_SetClipStatus,
4329 IDirect3DDevice8Impl_GetClipStatus,
4330 IDirect3DDevice8Impl_GetTexture,
4331 IDirect3DDevice8Impl_SetTexture,
4332 IDirect3DDevice8Impl_GetTextureStageState,
4333 IDirect3DDevice8Impl_SetTextureStageState,
4334 IDirect3DDevice8Impl_ValidateDevice,
4335 IDirect3DDevice8Impl_GetInfo,
4336 IDirect3DDevice8Impl_SetPaletteEntries,
4337 IDirect3DDevice8Impl_GetPaletteEntries,
4338 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4339 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4340 IDirect3DDevice8Impl_DrawPrimitive,
4341 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4342 IDirect3DDevice8Impl_DrawPrimitiveUP,
4343 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4344 IDirect3DDevice8Impl_ProcessVertices,
4345 IDirect3DDevice8Impl_CreateVertexShader,
4346 IDirect3DDevice8Impl_SetVertexShader,
4347 IDirect3DDevice8Impl_GetVertexShader,
4348 IDirect3DDevice8Impl_DeleteVertexShader,
4349 IDirect3DDevice8Impl_SetVertexShaderConstant,
4350 IDirect3DDevice8Impl_GetVertexShaderConstant,
4351 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4352 IDirect3DDevice8Impl_GetVertexShaderFunction,
4353 IDirect3DDevice8Impl_SetStreamSource,
4354 IDirect3DDevice8Impl_GetStreamSource,
4355 IDirect3DDevice8Impl_SetIndices,
4356 IDirect3DDevice8Impl_GetIndices,
4357 IDirect3DDevice8Impl_CreatePixelShader,
4358 IDirect3DDevice8Impl_SetPixelShader,
4359 IDirect3DDevice8Impl_GetPixelShader,
4360 IDirect3DDevice8Impl_DeletePixelShader,
4361 IDirect3DDevice8Impl_SetPixelShaderConstant,
4362 IDirect3DDevice8Impl_GetPixelShaderConstant,
4363 IDirect3DDevice8Impl_GetPixelShaderFunction,
4364 IDirect3DDevice8Impl_DrawRectPatch,
4365 IDirect3DDevice8Impl_DrawTriPatch,
4366 IDirect3DDevice8Impl_DeletePatch
4369 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4371 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4372 ICOM_THIS(IDirect3DDevice8Impl,iface);
4377 if (This->glCtx != This->render_ctx) {
4378 glXDestroyContext(This->display, This->render_ctx);
4379 This->render_ctx = This->glCtx;
4382 if (This->win != This->drawable) {
4383 glXDestroyPbuffer(This->display, This->drawable);
4384 This->drawable = This->win;
4393 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4394 IDirect3DSurface8* RenderSurface,
4395 IDirect3DSurface8* StencilSurface) {
4397 HRESULT ret = D3DERR_INVALIDCALL;
4399 * Currently only active for GLX >= 1.3
4400 * for others versions we'll have to use GLXPixmaps
4402 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4403 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4404 * so only check OpenGL version
4406 #if defined(GL_VERSION_1_3)
4407 GLXFBConfig* cfgs = NULL;
4411 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4412 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4413 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4414 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4415 IDirect3DSurface8Impl* tmp;
4417 ICOM_THIS(IDirect3DDevice8Impl,iface);
4419 #define PUSH1(att) attribs[nAttribs++] = (att);
4420 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4422 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4423 PUSH2(GLX_X_RENDERABLE, TRUE);
4424 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4426 switch (BackBufferFormat) {
4429 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4430 PUSH2(GLX_BUFFER_SIZE, 8);
4431 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4435 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4436 PUSH2(GLX_RED_SIZE, 3);
4437 PUSH2(GLX_GREEN_SIZE, 3);
4438 PUSH2(GLX_BLUE_SIZE, 2);
4441 case D3DFMT_A1R5G5B5:
4442 PUSH2(GLX_ALPHA_SIZE, 1);
4443 case D3DFMT_X1R5G5B5:
4444 PUSH2(GLX_RED_SIZE, 5);
4445 PUSH2(GLX_GREEN_SIZE, 5);
4446 PUSH2(GLX_BLUE_SIZE, 5);
4450 PUSH2(GLX_RED_SIZE, 5);
4451 PUSH2(GLX_GREEN_SIZE, 6);
4452 PUSH2(GLX_BLUE_SIZE, 5);
4455 case D3DFMT_A4R4G4B4:
4456 PUSH2(GLX_ALPHA_SIZE, 4);
4457 case D3DFMT_X4R4G4B4:
4458 PUSH2(GLX_RED_SIZE, 4);
4459 PUSH2(GLX_GREEN_SIZE, 4);
4460 PUSH2(GLX_BLUE_SIZE, 4);
4463 case D3DFMT_A8R8G8B8:
4464 PUSH2(GLX_ALPHA_SIZE, 8);
4466 case D3DFMT_X8R8G8B8:
4467 PUSH2(GLX_RED_SIZE, 8);
4468 PUSH2(GLX_GREEN_SIZE, 8);
4469 PUSH2(GLX_BLUE_SIZE, 8);
4476 switch (StencilBufferFormat) {
4477 case D3DFMT_D16_LOCKABLE:
4479 PUSH2(GLX_DEPTH_SIZE, 16);
4483 PUSH2(GLX_DEPTH_SIZE, 15);
4487 PUSH2(GLX_DEPTH_SIZE, 24);
4490 case D3DFMT_D24X4S4:
4491 PUSH2(GLX_DEPTH_SIZE, 24);
4492 PUSH2(GLX_STENCIL_SIZE, 4);
4496 PUSH2(GLX_DEPTH_SIZE, 24);
4497 PUSH2(GLX_STENCIL_SIZE, 8);
4501 PUSH2(GLX_DEPTH_SIZE, 32);
4512 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4516 for (i = 0; i < nCfgs; ++i) {
4517 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4521 if (NULL != This->renderTarget) {
4522 /*GLenum prev_read; */
4524 vcheckGLcall("glFlush");
4527 /** very very usefull debug code */
4528 glXSwapBuffers(This->display, This->drawable);
4529 printf("Hit Enter to get next frame ...\n");
4534 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4535 vcheckGLcall("glIntegerv");
4536 glReadBuffer(GL_BACK);
4537 vcheckGLcall("glReadBuffer");
4540 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4542 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4545 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4547 This->renderTarget->myDesc.Height - j - 1,
4548 This->renderTarget->myDesc.Width,
4550 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4551 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4552 This->renderTarget->allocatedMemory + j * pitch);
4553 vcheckGLcall("glReadPixels");
4556 glReadBuffer(prev_read);
4557 vcheckGLcall("glReadBuffer");
4561 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4562 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4564 PUSH2(GLX_PBUFFER_WIDTH, Width);
4565 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4567 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4569 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4570 if (NULL == This->render_ctx) {
4571 ERR("cannot create glxContext\n");
4575 glXSwapBuffers(This->display, This->drawable);
4576 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4577 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4579 checkGLcall("glXMakeContextCurrent");
4582 tmp = This->renderTarget;
4583 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4584 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4585 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4587 tmp = This->stencilBufferTarget;
4588 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4589 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4590 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4594 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4595 This->renderUpsideDown = This->renderTarget != This->frontBuffer;
4596 /* Force updating the cull mode */
4597 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4598 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4599 /* Force updating projection matrix */
4600 This->last_was_rhw = FALSE;
4601 This->proj_valid = FALSE;
4607 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));