2 * IDirect3DDevice8 implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2004 Christian Costa
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
35 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
36 /*#define GL_GLEXT_PROTOTYPES*/
37 /*#undef GLX_GLXEXT_LEGACY*/
38 #include "d3d8_private.h"
40 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
43 /* Uncomment the next line to get extra traces, important but impact speed */
44 /* #define EXTRA_TRACES */
46 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
47 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
48 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
50 IDirect3DVertexShaderImpl* VertexShaders[64];
51 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
52 IDirect3DPixelShaderImpl* PixelShaders[64];
55 #ifdef FRAME_DEBUGGING
57 BOOL isDumpingFrames = FALSE;
62 * Utility functions or macros
64 #define conv_mat(mat,gl_mat) \
66 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
68 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
69 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
70 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
73 /* Apply the current values to the specified texture stage */
74 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
75 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
78 BOOL changeTexture = TRUE;
80 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
81 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
86 /* Performance: For texture states where multiples effect the outcome, only bother
87 applying the last one as it will pick up all the other values */
88 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
89 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
90 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
91 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
92 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
93 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
97 /* Performance: If the texture states only impact settings for the texture unit
98 (compared to the texture object) then there is no need to reapply them. The
99 only time they need applying is the first time, since we cheat and put the
100 values into the stateblock without applying.
101 Per-texture unit: texture function (eg. combine), ops and args
103 texture generation settings
104 Note: Due to some special conditions there may be a need to do particular ones
105 of these, which is what the Flags allows */
107 case D3DTSS_TEXCOORDINDEX:
108 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
112 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
120 /* Performance: Only change to this texture if we have to */
122 /* Make appropriate texture active */
123 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
124 #if defined(GL_VERSION_1_3)
125 glActiveTexture(GL_TEXTURE0 + Stage);
126 checkGLcall("glActiveTexture");
128 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
129 checkGLcall("glActiveTextureARB");
131 } else if (Stage > 0) {
132 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
134 changeTexture = FALSE;
137 /* Now apply the change */
138 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
142 /* Note the D3DRS value applies to all textures, but GL has one
143 * per texture, so apply it now ready to be used!
145 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
146 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
147 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
149 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
152 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
153 static void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
156 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
157 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
159 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
160 glMatrixMode(GL_MODELVIEW);
162 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
165 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
166 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
167 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
168 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
169 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
170 checkGLcall("glLightfv");
173 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
174 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
175 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
176 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
177 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
178 checkGLcall("glLightfv");
181 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
182 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
183 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
184 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
185 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
186 checkGLcall("glLightfv");
188 /* Attenuation - Are these right? guessing... */
189 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
190 checkGLcall("glLightf");
191 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
192 checkGLcall("glLightf");
194 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
195 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
196 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
197 checkGLcall("glLightf");
199 switch (lightInfo->OriginalParms.Type) {
202 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
203 checkGLcall("glLightfv");
204 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
205 checkGLcall("glLightf");
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
214 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
215 checkGLcall("glLightfv");
216 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
217 checkGLcall("glLightf");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
219 checkGLcall("glLightf");
223 case D3DLIGHT_DIRECTIONAL:
225 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
226 checkGLcall("glLightfv");
227 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228 checkGLcall("glLightf");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
230 checkGLcall("glLightf");
234 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
237 /* Restore the modelview matrix */
241 /* Setup this textures matrix */
242 static void set_texture_matrix(const float *smat, DWORD flags)
246 glMatrixMode(GL_TEXTURE);
248 if (flags == D3DTTFF_DISABLE) {
250 checkGLcall("glLoadIdentity()");
254 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
255 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
256 checkGLcall("glLoadIdentity()");
260 memcpy(mat, smat, 16*sizeof(float));
262 switch (flags & ~D3DTTFF_PROJECTED) {
263 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
264 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
265 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
268 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
270 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
271 mat[1] = mat[5] = mat[9] = mat[13] = 0;
274 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
275 mat[2] = mat[6] = mat[10] = mat[14] = 0;
279 checkGLcall("glLoadMatrixf(mat)");
282 /* IDirect3D IUnknown parts follow: */
283 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
285 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
287 if (IsEqualGUID(riid, &IID_IUnknown)
288 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
289 IDirect3DDevice8Impl_AddRef(iface);
294 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
295 return E_NOINTERFACE;
298 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
299 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
300 ULONG ref = InterlockedIncrement(&This->ref);
302 TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
307 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
308 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
309 ULONG ref = InterlockedDecrement(&This->ref);
311 TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
314 IDirect3DDevice8Impl_CleanRender(iface);
315 IDirect3D8_Release((LPDIRECT3D8) This->direct3d8);
316 IWineD3DDevice_Release(This->WineD3DDevice);
318 if (glXGetCurrentContext() == This->glCtx) {
319 glXMakeCurrent(This->display, None, NULL);
321 glXDestroyContext(This->display, This->glCtx);
323 HeapFree(GetProcessHeap(), 0, This);
328 /* IDirect3DDevice Interface follow: */
329 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
330 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
331 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
335 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
336 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
337 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
339 * pretend we have 32MB of any type of memory queried.
341 return (1024*1024*32);
344 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
345 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
346 FIXME("(%p) : stub\n", This);
349 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
350 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
351 TRACE("(%p) : returning %p\n", This, This->direct3d8);
354 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
356 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
359 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
360 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
361 FIXME("(%p) : stub, calling idirect3d for now\n", This);
362 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
365 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
370 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
371 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
372 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
373 pMode->RefreshRate = 85; /*FIXME: How to identify? */
375 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
376 bpp = GetDeviceCaps(hdc, BITSPIXEL);
380 case 8: pMode->Format = D3DFMT_R8G8B8; break;
381 case 16: pMode->Format = D3DFMT_R5G6B5; break;
382 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
383 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
385 FIXME("Unrecognized display mode format\n");
386 pMode->Format = D3DFMT_UNKNOWN;
389 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
390 pMode->Format, debug_d3dformat(pMode->Format));
393 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
394 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
395 TRACE("(%p) copying to %p\n", This, pParameters);
396 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
399 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
400 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
401 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
402 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
404 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
405 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
406 return D3DERR_INVALIDCALL;
408 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
409 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
410 return D3DERR_INVALIDCALL;
413 This->xHotSpot = XHotSpot;
414 This->yHotSpot = YHotSpot;
417 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
418 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
419 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
420 This->xScreenSpace = XScreenSpace;
421 This->yScreenSpace = YScreenSpace;
424 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
425 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
426 TRACE("(%p) : visible(%d)\n", This, bShow);
427 This->bCursorVisible = bShow;
430 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
431 IDirect3DSwapChain8Impl* object;
432 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
433 FIXME("(%p) : stub\n", This);
435 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
436 if (NULL == object) {
437 return D3DERR_OUTOFVIDEOMEMORY;
439 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
442 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
443 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
444 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
446 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
447 (pPresentationParameters->BackBufferHeight == 0))) {
450 GetClientRect(This->win_handle, &Rect);
452 if (pPresentationParameters->BackBufferWidth == 0) {
453 pPresentationParameters->BackBufferWidth = Rect.right;
454 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
456 if (pPresentationParameters->BackBufferHeight == 0) {
457 pPresentationParameters->BackBufferHeight = Rect.bottom;
458 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
462 /* Save the presentation parms now filled in correctly */
463 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
465 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
466 pPresentationParameters->BackBufferWidth,
467 pPresentationParameters->BackBufferHeight,
468 pPresentationParameters->BackBufferFormat,
469 pPresentationParameters->MultiSampleType,
471 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
473 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
474 pPresentationParameters->BackBufferWidth,
475 pPresentationParameters->BackBufferHeight,
476 pPresentationParameters->BackBufferFormat,
477 pPresentationParameters->MultiSampleType,
479 (LPDIRECT3DSURFACE8*) &object->backBuffer);
481 if (pPresentationParameters->EnableAutoDepthStencil) {
482 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
483 pPresentationParameters->BackBufferWidth,
484 pPresentationParameters->BackBufferHeight,
485 pPresentationParameters->AutoDepthStencilFormat,
487 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
489 object->depthStencilBuffer = NULL;
492 *pSwapChain = (IDirect3DSwapChain8*) object;
495 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
496 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
497 FIXME("(%p) : stub\n", This);
500 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
501 CONST RECT* pSourceRect, CONST RECT* pDestRect,
502 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
503 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
504 TRACE("(%p) : complete stub!\n", This);
508 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
511 glXSwapBuffers(This->display, This->drawable);
512 /* Don't call checkGLcall, as glGetError is not applicable here */
513 TRACE("glXSwapBuffers called, Starting new frame\n");
516 if (TRACE_ON(d3d_fps))
518 static long prev_time, frames;
520 DWORD time = GetTickCount();
522 /* every 1.5 seconds */
523 if (time - prev_time > 1500) {
524 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
530 #if defined(FRAME_DEBUGGING)
532 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
535 FIXME("Enabling D3D Trace\n");
536 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
537 #if defined(SHOW_FRAME_MAKEUP)
538 FIXME("Singe Frame snapshots Starting\n");
539 isDumpingFrames = TRUE;
540 glClear(GL_COLOR_BUFFER_BIT);
543 #if defined(SINGLE_FRAME_DEBUGGING)
545 #if defined(SHOW_FRAME_MAKEUP)
546 FIXME("Singe Frame snapshots Finishing\n");
547 isDumpingFrames = FALSE;
549 FIXME("Singe Frame trace complete\n");
550 DeleteFileA("C:\\D3DTRACE");
551 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
557 #if defined(SHOW_FRAME_MAKEUP)
558 FIXME("Singe Frame snapshots Finishing\n");
559 isDumpingFrames = FALSE;
561 FIXME("Disabling D3D Trace\n");
562 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
569 /* Although this is not strictly required, a simple demo showed this does occur
570 on (at least non-debug) d3d */
571 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
572 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
577 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
578 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
579 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
580 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
582 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
583 FIXME("Only one backBuffer currently supported\n");
584 return D3DERR_INVALIDCALL;
587 /* Note inc ref on returned surface */
588 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
592 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
593 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
594 FIXME("(%p) : stub\n", This);
597 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
599 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
601 FIXME("(%p) : pRamp@%p\n", This, pRamp);
602 hDC = GetDC(This->win_handle);
603 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
604 ReleaseDC(This->win_handle, hDC);
607 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
609 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
611 FIXME("(%p) : pRamp@%p\n", This, pRamp);
612 hDC = GetDC(This->win_handle);
613 GetDeviceGammaRamp(hDC, pRamp);
614 ReleaseDC(This->win_handle, hDC);
617 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
618 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
619 IDirect3DTexture8Impl *object;
624 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
626 /* Allocate the storage for the device */
627 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);
628 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
629 object->lpVtbl = &Direct3DTexture8_Vtbl;
630 object->Device = This;
631 object->ResourceType = D3DRTYPE_TEXTURE;
633 object->width = Width;
634 object->height = Height;
635 object->levels = Levels;
636 object->usage = Usage;
637 object->format = Format;
639 /* Calculate levels for mip mapping */
644 while (tmpW > 1 && tmpH > 1) {
645 tmpW = max(1, tmpW / 2);
646 tmpH = max(1, tmpH / 2);
649 TRACE("Calculated levels = %d\n", object->levels);
652 /* Generate all the surfaces */
655 for (i = 0; i < object->levels; i++)
657 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
658 object->surfaces[i]->Container = (IUnknown*) object;
659 object->surfaces[i]->myDesc.Usage = Usage;
660 object->surfaces[i]->myDesc.Pool = Pool;
662 * As written in msdn in IDirect3DTexture8::LockRect
663 * Textures created in D3DPOOL_DEFAULT are not lockable.
665 if (D3DPOOL_DEFAULT == Pool) {
666 object->surfaces[i]->lockable = FALSE;
669 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
670 tmpW = max(1, tmpW / 2);
671 tmpH = max(1, tmpH / 2);
674 *ppTexture = (LPDIRECT3DTEXTURE8) object;
675 TRACE("(%p) : Created texture %p\n", This, object);
678 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
679 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
680 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
682 IDirect3DVolumeTexture8Impl *object;
688 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
690 /* Allocate the storage for it */
691 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));
692 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
693 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
694 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
695 object->Device = This;
698 object->width = Width;
699 object->height = Height;
700 object->depth = Depth;
701 object->levels = Levels;
702 object->usage = Usage;
703 object->format = Format;
705 /* Calculate levels for mip mapping */
711 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
712 tmpW = max(1, tmpW / 2);
713 tmpH = max(1, tmpH / 2);
714 tmpD = max(1, tmpD / 2);
717 TRACE("Calculated levels = %d\n", object->levels);
720 /* Generate all the surfaces */
725 for (i = 0; i < object->levels; i++)
727 IDirect3DVolume8Impl* volume;
729 /* Create the volume - No entry point for this seperately?? */
730 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
731 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
733 volume->lpVtbl = &Direct3DVolume8_Vtbl;
734 volume->Device = This;
735 volume->ResourceType = D3DRTYPE_VOLUME;
736 volume->Container = (IUnknown*) object;
739 volume->myDesc.Width = Width;
740 volume->myDesc.Height = Height;
741 volume->myDesc.Depth = Depth;
742 volume->myDesc.Format = Format;
743 volume->myDesc.Type = D3DRTYPE_VOLUME;
744 volume->myDesc.Pool = Pool;
745 volume->myDesc.Usage = Usage;
746 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
747 /* Note: Volume textures cannot be dxtn, hence no need to check here */
748 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
749 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
751 volume->lockable = TRUE;
752 volume->locked = FALSE;
753 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
754 volume->Dirty = FALSE;
755 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
757 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
758 This, Width, Height, Depth, Format, debug_d3dformat(Format),
759 volume, volume->allocatedMemory, volume->myDesc.Size);
761 tmpW = max(1, tmpW / 2);
762 tmpH = max(1, tmpH / 2);
763 tmpD = max(1, tmpD / 2);
766 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
767 TRACE("(%p) : Created volume texture %p\n", This, object);
770 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
771 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
773 IDirect3DCubeTexture8Impl *object;
774 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
778 /* Allocate the storage for it */
779 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));
780 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
781 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
783 object->Device = This;
784 object->ResourceType = D3DRTYPE_CUBETEXTURE;
786 object->edgeLength = EdgeLength;
787 object->levels = Levels;
788 object->usage = Usage;
789 object->format = Format;
791 /* Calculate levels for mip mapping */
796 tmpW = max(1, tmpW / 2);
799 TRACE("Calculated levels = %d\n", object->levels);
802 /* Generate all the surfaces */
804 for (i = 0; i < object->levels; i++) {
805 /* Create the 6 faces */
806 for (j = 0; j < 6; j++) {
807 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
808 object->surfaces[j][i]->Container = (IUnknown*) object;
809 object->surfaces[j][i]->myDesc.Usage = Usage;
810 object->surfaces[j][i]->myDesc.Pool = Pool;
812 * As written in msdn in IDirect3DCubeTexture8::LockRect
813 * Textures created in D3DPOOL_DEFAULT are not lockable.
815 if (D3DPOOL_DEFAULT == Pool) {
816 object->surfaces[j][i]->lockable = FALSE;
819 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
821 tmpW = max(1, tmpW / 2);
824 TRACE("(%p) : Iface@%p\n", This, object);
825 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
828 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
829 IDirect3DVertexBuffer8Impl *object;
831 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
833 /* Allocate the storage for the device */
834 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
835 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
836 object->Device = This;
837 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
839 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
840 object->currentDesc.Usage = Usage;
841 object->currentDesc.Pool = Pool;
842 object->currentDesc.FVF = FVF;
843 object->currentDesc.Size = Size;
845 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
847 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
851 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
852 IDirect3DIndexBuffer8Impl *object;
854 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
855 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
857 /* Allocate the storage for the device */
858 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
859 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
860 object->Device = This;
862 object->ResourceType = D3DRTYPE_INDEXBUFFER;
864 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
865 object->currentDesc.Usage = Usage;
866 object->currentDesc.Pool = Pool;
867 object->currentDesc.Format = Format;
868 object->currentDesc.Size = Length;
870 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
872 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
874 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
878 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
879 IDirect3DSurface8Impl *object;
880 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
882 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
883 if (NULL == object) {
885 return D3DERR_OUTOFVIDEOMEMORY;
887 *ppSurface = (LPDIRECT3DSURFACE8) object;
888 object->lpVtbl = &Direct3DSurface8_Vtbl;
889 object->Device = This;
890 object->ResourceType = D3DRTYPE_SURFACE;
891 object->Container = (IUnknown*) This;
894 object->myDesc.Width = Width;
895 object->myDesc.Height = Height;
896 object->myDesc.Format = Format;
897 object->myDesc.Type = D3DRTYPE_SURFACE;
898 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
899 object->myDesc.Pool = D3DPOOL_DEFAULT;
900 object->myDesc.MultiSampleType = MultiSample;
901 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
902 if (Format == D3DFMT_DXT1) {
903 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
905 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
907 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
908 object->lockable = Lockable;
909 object->locked = FALSE;
910 memset(&object->lockedRect, 0, sizeof(RECT));
911 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
913 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);
916 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
917 IDirect3DSurface8Impl *object;
919 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
921 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
922 if (NULL == object) {
924 return D3DERR_OUTOFVIDEOMEMORY;
926 *ppSurface = (LPDIRECT3DSURFACE8) object;
927 object->lpVtbl = &Direct3DSurface8_Vtbl;
928 object->Device = This;
929 object->ResourceType = D3DRTYPE_SURFACE;
930 object->Container = (IUnknown*) This;
933 object->myDesc.Width = Width;
934 object->myDesc.Height = Height;
935 object->myDesc.Format = Format;
936 object->myDesc.Type = D3DRTYPE_SURFACE;
937 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
938 object->myDesc.Pool = D3DPOOL_DEFAULT;
939 object->myDesc.MultiSampleType = MultiSample;
940 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
941 if (Format == D3DFMT_DXT1) {
942 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
944 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
946 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
947 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
948 object->locked = FALSE;
949 memset(&object->lockedRect, 0, sizeof(RECT));
950 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
952 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);
955 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
956 IDirect3DSurface8Impl *object;
958 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
960 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
961 *ppSurface = (LPDIRECT3DSURFACE8) object;
962 object->lpVtbl = &Direct3DSurface8_Vtbl;
963 object->Device = This;
964 object->ResourceType = D3DRTYPE_SURFACE;
965 object->Container = (IUnknown*) This;
968 object->myDesc.Width = Width;
969 object->myDesc.Height = Height;
970 object->myDesc.Format = Format;
971 object->myDesc.Type = D3DRTYPE_SURFACE;
972 object->myDesc.Usage = 0;
973 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
974 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
975 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
976 it is based around 4x4 pixel blocks it requires padding, so allocate enough
978 if (Format == D3DFMT_DXT1) {
979 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
980 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
981 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
982 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
984 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
986 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
987 object->lockable = TRUE;
988 object->locked = FALSE;
989 memset(&object->lockedRect, 0, sizeof(RECT));
990 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
992 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);
995 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
996 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
997 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
1000 IDirect3DBaseTexture8* texture = NULL;
1003 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
1004 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1006 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1007 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1008 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1010 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1011 a sample and doesn't seem to break anything as far as I can tell */
1012 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1013 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1014 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1015 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1016 rc = D3DERR_INVALIDCALL;
1018 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1019 TRACE("Converting dest to same format as source, since dest was unknown\n");
1020 dst->myDesc.Format = src->myDesc.Format;
1022 /* Convert container as well */
1023 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1024 if (SUCCEEDED(rc) && NULL != texture) {
1025 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1026 /** Releasing texture after GetContainer */
1027 IDirect3DBaseTexture8_Release(texture);
1032 /* Quick if complete copy ... */
1033 if (SUCCEEDED(rc)) {
1034 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1036 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1038 D3DLOCKED_RECT lrSrc;
1039 D3DLOCKED_RECT lrDst;
1040 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1041 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1042 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1044 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1046 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1047 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1048 TRACE("Unlocked src and dst\n");
1052 FIXME("Wanted to copy all surfaces but size not compatible\n");
1053 rc = D3DERR_INVALIDCALL;
1059 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1061 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1064 /* Copy rect by rect */
1065 for (i = 0; i < cRects; i++) {
1066 CONST RECT* r = &pSourceRectsArray[i];
1067 CONST POINT* p = &pDestPointsArray[i];
1070 D3DLOCKED_RECT lrSrc;
1071 D3DLOCKED_RECT lrDst;
1074 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1075 if (src->myDesc.Format == D3DFMT_DXT1) {
1076 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1078 copyperline = ((r->right - r->left) * bytesPerPixel);
1080 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1081 dest_rect.left = p->x;
1082 dest_rect.top = p->y;
1083 dest_rect.right = p->x + (r->right - r->left);
1084 dest_rect.bottom= p->y + (r->bottom - r->top);
1085 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1086 TRACE("Locked src and dst\n");
1088 /* Find where to start */
1089 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1090 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1092 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1093 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1094 TRACE("Unlocked src and dst\n");
1097 FIXME("Wanted to copy partial surfaces not implemented\n");
1098 rc = D3DERR_INVALIDCALL;
1105 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1106 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1107 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1108 D3DRESOURCETYPE srcType;
1109 D3DRESOURCETYPE dstType;
1111 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1112 TRACE("(%p) : first try\n", This);
1114 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1115 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1117 if (srcType != dstType) {
1118 return D3DERR_INVALIDCALL;
1120 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1121 return D3DERR_INVALIDCALL;
1123 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1124 return D3DERR_INVALIDCALL;
1126 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1127 /** Only copy Dirty textures */
1128 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1129 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1130 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1133 for (i = skipLevels; i < srcLevelCnt; ++i) {
1137 case D3DRTYPE_TEXTURE:
1139 IDirect3DSurface8* srcSur = NULL;
1140 IDirect3DSurface8* dstSur = NULL;
1141 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1142 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1144 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1145 about dst with less levels than the source?) */
1146 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1148 IDirect3DSurface8Impl_Release(srcSur);
1149 IDirect3DSurface8Impl_Release(dstSur);
1152 case D3DRTYPE_VOLUMETEXTURE:
1154 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1157 case D3DRTYPE_CUBETEXTURE:
1159 IDirect3DSurface8* srcSur = NULL;
1160 IDirect3DSurface8* dstSur = NULL;
1161 for (j = 0; j < 5; ++j) {
1162 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1163 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &dstSur);
1165 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1167 IDirect3DSurface8Impl_Release(srcSur);
1168 IDirect3DSurface8Impl_Release(dstSur);
1176 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1181 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1183 D3DLOCKED_RECT lockedRect;
1188 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1190 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1192 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1193 ERR("(%p) : surface(%p) has an invalid format\n", This, pDestSurface);
1194 return D3DERR_INVALIDCALL;
1197 wantedRect.left = 0;
1199 wantedRect.right = This->PresentParms.BackBufferWidth;
1200 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1202 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1204 ERR("(%p) : cannot lock surface\n", This);
1205 return D3DERR_INVALIDCALL;
1211 vcheckGLcall("glFlush");
1212 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1213 vcheckGLcall("glIntegerv");
1214 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1215 vcheckGLcall("glIntegerv");
1217 glReadBuffer(GL_FRONT);
1218 vcheckGLcall("glReadBuffer");
1219 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1220 vcheckGLcall("glPixelStorei");
1224 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1225 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1226 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1227 vcheckGLcall("glReadPixels");
1230 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1231 vcheckGLcall("glPixelStorei");
1232 glReadBuffer(prev_read);
1233 vcheckGLcall("glReadBuffer");
1237 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1240 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1241 HRESULT hr = D3D_OK;
1242 D3DVIEWPORT8 viewport;
1244 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1246 /* If pRenderTarget == NULL, it seems to default to back buffer */
1247 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1249 /* For ease of code later on, handle a null depth as leave alone
1250 - Have not tested real d3d for this case but doing this avoids
1251 numerous null pointer checks */
1252 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1254 /* If we are trying to set what we already have, don't bother */
1255 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1256 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1258 /* Otherwise, set the render target up */
1259 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1260 IDirect3DDevice8Impl_CleanRender(iface);
1261 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1264 if (SUCCEEDED(hr)) {
1265 /* Finally, reset the viewport as the MSDN states. */
1266 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1267 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1270 viewport.MaxZ = 1.0f;
1271 viewport.MinZ = 0.0f;
1272 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1278 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1279 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1281 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1283 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1284 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1289 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1290 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1292 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1294 /* Note inc ref on returned surface */
1295 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1296 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1301 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1302 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1303 return IWineD3DDevice_BeginScene(This->WineD3DDevice);
1306 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1307 IDirect3DBaseTexture8* cont = NULL;
1309 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1310 TRACE("(%p)\n", This);
1315 checkGLcall("glFlush");
1317 #if 0 /* Useful for debugging sometimes! */
1318 printf("Hit Enter ...\n");
1322 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1325 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1326 vcheckGLcall("glIntegerv");
1327 glReadBuffer(GL_FRONT);
1328 vcheckGLcall("glReadBuffer");
1331 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1333 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1336 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1338 This->renderTarget->myDesc.Height - j - 1,
1339 This->renderTarget->myDesc.Width,
1341 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1342 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1343 This->renderTarget->allocatedMemory + j * pitch);
1344 vcheckGLcall("glReadPixels");
1347 glReadBuffer(prev_read);
1348 vcheckGLcall("glReadBuffer");
1351 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1352 if (SUCCEEDED(hr) && NULL != cont) {
1353 /** always dirtify for now. we must find a better way to see that surface have been modified */
1354 This->renderTarget->inPBuffer = TRUE;
1355 This->renderTarget->inTexture = FALSE;
1356 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1357 IDirect3DBaseTexture8_PreLoad(cont);
1358 This->renderTarget->inPBuffer = FALSE;
1359 IDirect3DBaseTexture8Impl_Release(cont);
1367 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1368 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1370 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1371 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1372 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1373 GLbitfield glMask = 0;
1374 GLboolean old_ztest;
1375 GLfloat old_z_clear_value;
1376 GLint old_stencil_clear_value;
1377 GLfloat old_color_clear_value[4];
1379 CONST D3DRECT* curRect;
1381 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1382 Count, pRects, Flags, Z, Stencil);
1385 glEnable(GL_SCISSOR_TEST);
1386 checkGLcall("glEnable GL_SCISSOR_TEST");
1387 if (Count > 0 && pRects) {
1393 /* Only set the values up once, as they are not changing */
1394 if (Flags & D3DCLEAR_STENCIL) {
1395 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1396 glClearStencil(Stencil);
1397 checkGLcall("glClearStencil");
1398 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1399 glStencilMask(0xFFFFFFFF);
1402 if (Flags & D3DCLEAR_ZBUFFER) {
1403 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1404 glDepthMask(GL_TRUE);
1405 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1407 checkGLcall("glClearDepth");
1408 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1411 if (Flags & D3DCLEAR_TARGET) {
1412 TRACE("Clearing screen with glClear to color %lx\n", Color);
1413 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1414 glClearColor(D3DCOLOR_R(Color),
1418 checkGLcall("glClearColor");
1420 /* Clear ALL colors! */
1421 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1422 glMask = glMask | GL_COLOR_BUFFER_BIT;
1425 /* Now process each rect in turn */
1426 for (i = 0; i < Count || i == 0; i++) {
1429 /* Note gl uses lower left, width/height */
1430 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1431 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1432 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1433 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1434 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1435 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1436 checkGLcall("glScissor");
1438 glScissor(This->StateBlock->viewport.X,
1439 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1440 This->StateBlock->viewport.Width,
1441 This->StateBlock->viewport.Height);
1442 checkGLcall("glScissor");
1445 /* Clear the selected rectangle (or full screen) */
1447 checkGLcall("glClear");
1449 /* Step to the next rectangle */
1450 if (curRect) curRect = curRect + sizeof(D3DRECT);
1453 /* Restore the old values (why..?) */
1454 if (Flags & D3DCLEAR_STENCIL) {
1455 glClearStencil(old_stencil_clear_value);
1456 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1458 if (Flags & D3DCLEAR_ZBUFFER) {
1459 glDepthMask(old_ztest);
1460 glClearDepth(old_z_clear_value);
1462 if (Flags & D3DCLEAR_TARGET) {
1463 glClearColor(old_color_clear_value[0],
1464 old_color_clear_value[1],
1465 old_color_clear_value[2],
1466 old_color_clear_value[3]);
1467 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1468 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1469 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1470 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1473 glDisable(GL_SCISSOR_TEST);
1474 checkGLcall("glDisable");
1479 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1480 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1483 /* Most of this routine, comments included copied from ddraw tree initially: */
1484 TRACE("(%p) : State=%d\n", This, d3dts);
1486 /* Handle recording of state blocks */
1487 if (This->isRecordingState) {
1488 TRACE("Recording... not performing anything\n");
1489 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1490 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1491 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1496 * if the new matrix is the same as the current one,
1497 * we cut off any further processing. this seems to be a reasonable
1498 * optimization because as was noticed, some apps (warcraft3 for example)
1499 * tend towards setting the same matrix repeatedly for some dumb reason.
1501 * From here on we assume that the new matrix is different, wherever it matters
1504 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1505 TRACE("The app is setting the same matrix over again\n");
1508 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1512 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1513 where ViewMat = Camera space, WorldMat = world space.
1515 In OpenGL, camera and world space is combined into GL_MODELVIEW
1516 matrix. The Projection matrix stay projection matrix.
1519 /* Capture the times we can just ignore the change */
1520 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1521 This->modelview_valid = FALSE;
1524 } else if (d3dts == D3DTS_PROJECTION) {
1525 This->proj_valid = FALSE;
1528 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1529 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1530 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1534 /* Chances are we really are going to have to change a matrix */
1537 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1538 if (d3dts < GL_LIMITS(textures)) {
1539 int tex = d3dts - D3DTS_TEXTURE0;
1540 #if defined(GL_VERSION_1_3)
1541 glActiveTexture(GL_TEXTURE0 + tex);
1542 checkGLcall("glActiveTexture");
1544 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1545 checkGLcall("glActiveTextureARB");
1547 set_texture_matrix((const float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1550 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1552 PLIGHTINFOEL *lightChain = NULL;
1553 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1554 This->modelview_valid = FALSE;
1555 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1556 glMatrixMode(GL_MODELVIEW);
1557 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1559 glLoadMatrixf((const float *)lpmatrix);
1560 checkGLcall("glLoadMatrixf(...)");
1562 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1563 * NOTE: We have to reset the positions even if the light/plane is not currently
1564 * enabled, since the call to enable it will not reset the position.
1565 * NOTE2: Apparently texture transforms do NOT need reapplying
1569 lightChain = This->StateBlock->lights;
1570 while (lightChain && lightChain->glIndex != -1) {
1571 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1572 checkGLcall("glLightfv posn");
1573 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1574 checkGLcall("glLightfv dirn");
1575 lightChain = lightChain->next;
1577 /* Reset Clipping Planes if clipping is enabled */
1578 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1579 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1580 checkGLcall("glClipPlane");
1584 } else { /* What was requested!?? */
1585 WARN("invalid matrix specified: %i\n", d3dts);
1589 /* Release lock, all done */
1594 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1595 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1596 TRACE("(%p) : for State %d\n", This, State);
1597 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1601 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1602 D3DMATRIX *mat = NULL;
1605 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1606 but works regardless of recording being on.
1607 If this is found to be wrong, change to StateBlock. */
1608 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1609 TRACE("(%p) : For state %u\n", This, State);
1611 if (State < HIGHEST_TRANSFORMSTATE)
1613 mat = &This->UpdateStateBlock->transforms[State];
1615 FIXME("Unhandled transform state!!\n");
1618 /* Copied from ddraw code: */
1619 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);
1620 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);
1621 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);
1622 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);
1624 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);
1625 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);
1626 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);
1627 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);
1629 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);
1630 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);
1631 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);
1632 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);
1634 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);
1635 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);
1636 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);
1637 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);
1639 /* Apply change via set transform - will reapply to eg. lights this way */
1640 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1643 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1644 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1646 TRACE("(%p)\n", This);
1647 This->UpdateStateBlock->Changed.viewport = TRUE;
1648 This->UpdateStateBlock->Set.viewport = TRUE;
1649 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1651 /* Handle recording of state blocks */
1652 if (This->isRecordingState) {
1653 TRACE("Recording... not performing anything\n");
1659 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1660 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1662 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1663 checkGLcall("glDepthRange");
1664 /* Note: GL requires lower left, DirectX supplies upper left */
1665 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1666 pViewport->Width, pViewport->Height);
1667 checkGLcall("glViewport");
1674 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1675 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1676 TRACE("(%p)\n", This);
1677 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1681 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1682 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1684 This->UpdateStateBlock->Changed.material = TRUE;
1685 This->UpdateStateBlock->Set.material = TRUE;
1686 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1688 /* Handle recording of state blocks */
1689 if (This->isRecordingState) {
1690 TRACE("Recording... not performing anything\n");
1695 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1696 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1697 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1698 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1699 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1701 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1702 checkGLcall("glMaterialfv");
1703 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1704 checkGLcall("glMaterialfv");
1706 /* Only change material color if specular is enabled, otherwise it is set to black */
1707 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1708 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1709 checkGLcall("glMaterialfv");
1711 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1712 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1713 checkGLcall("glMaterialfv");
1715 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1716 checkGLcall("glMaterialfv");
1717 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1718 checkGLcall("glMaterialf");
1723 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1724 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1725 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1726 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1727 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1728 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1729 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1730 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1734 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1735 you can reference any indexes you want as long as that number max are enabled are any
1736 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1737 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1738 but when recording, just build a chain pretty much of commands to be replayed. */
1740 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1742 PLIGHTINFOEL *object, *temp;
1744 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1745 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1747 /* If recording state block, just add to end of lights chain */
1748 if (This->isRecordingState) {
1749 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1750 if (NULL == object) {
1751 return D3DERR_OUTOFVIDEOMEMORY;
1753 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1754 object->OriginalIndex = Index;
1755 object->glIndex = -1;
1756 object->changed = TRUE;
1758 /* Add to the END of the chain of lights changes to be replayed */
1759 if (This->UpdateStateBlock->lights == NULL) {
1760 This->UpdateStateBlock->lights = object;
1762 temp = This->UpdateStateBlock->lights;
1763 while (temp->next != NULL) temp=temp->next;
1764 temp->next = object;
1766 TRACE("Recording... not performing anything more\n");
1770 /* Ok, not recording any longer so do real work */
1771 object = This->StateBlock->lights;
1772 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1774 /* If we didn't find it in the list of lights, time to add it */
1775 if (object == NULL) {
1776 PLIGHTINFOEL *insertAt,*prevPos;
1778 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1779 if (NULL == object) {
1780 return D3DERR_OUTOFVIDEOMEMORY;
1782 object->OriginalIndex = Index;
1783 object->glIndex = -1;
1785 /* Add it to the front of list with the idea that lights will be changed as needed
1786 BUT after any lights currently assigned GL indexes */
1787 insertAt = This->StateBlock->lights;
1789 while (insertAt != NULL && insertAt->glIndex != -1) {
1791 insertAt = insertAt->next;
1794 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1795 This->StateBlock->lights = object;
1796 } else if (insertAt == NULL) { /* End of list */
1797 prevPos->next = object;
1798 object->prev = prevPos;
1799 } else { /* Middle of chain */
1800 if (prevPos == NULL) {
1801 This->StateBlock->lights = object;
1803 prevPos->next = object;
1805 object->prev = prevPos;
1806 object->next = insertAt;
1807 insertAt->prev = object;
1811 /* Initialze the object */
1812 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,
1813 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1814 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1815 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1816 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1817 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1818 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1820 /* Save away the information */
1821 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1823 switch (pLight->Type) {
1824 case D3DLIGHT_POINT:
1826 object->lightPosn[0] = pLight->Position.x;
1827 object->lightPosn[1] = pLight->Position.y;
1828 object->lightPosn[2] = pLight->Position.z;
1829 object->lightPosn[3] = 1.0f;
1830 object->cutoff = 180.0f;
1834 case D3DLIGHT_DIRECTIONAL:
1836 object->lightPosn[0] = -pLight->Direction.x;
1837 object->lightPosn[1] = -pLight->Direction.y;
1838 object->lightPosn[2] = -pLight->Direction.z;
1839 object->lightPosn[3] = 0.0;
1840 object->exponent = 0.0f;
1841 object->cutoff = 180.0f;
1846 object->lightPosn[0] = pLight->Position.x;
1847 object->lightPosn[1] = pLight->Position.y;
1848 object->lightPosn[2] = pLight->Position.z;
1849 object->lightPosn[3] = 1.0;
1852 object->lightDirn[0] = pLight->Direction.x;
1853 object->lightDirn[1] = pLight->Direction.y;
1854 object->lightDirn[2] = pLight->Direction.z;
1855 object->lightDirn[3] = 1.0;
1858 * opengl-ish and d3d-ish spot lights use too different models for the
1859 * light "intensity" as a function of the angle towards the main light direction,
1860 * so we only can approximate very roughly.
1861 * however spot lights are rather rarely used in games (if ever used at all).
1862 * furthermore if still used, probably nobody pays attention to such details.
1864 if (pLight->Falloff == 0) {
1867 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1869 if (rho < 0.0001) rho = 0.0001f;
1870 object->exponent = -0.3/log(cos(rho/2));
1871 object->cutoff = pLight->Phi*90/M_PI;
1877 FIXME("Unrecognized light type %d\n", pLight->Type);
1880 /* Update the live definitions if the light is currently assigned a glIndex */
1881 if (object->glIndex != -1) {
1882 setup_light(iface, object->glIndex, object);
1886 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1887 PLIGHTINFOEL *lightInfo = NULL;
1888 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1889 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1891 /* Locate the light in the live lights */
1892 lightInfo = This->StateBlock->lights;
1893 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1895 if (lightInfo == NULL) {
1896 TRACE("Light information requested but light not defined\n");
1897 return D3DERR_INVALIDCALL;
1900 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1903 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1904 PLIGHTINFOEL *lightInfo = NULL;
1905 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1906 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1908 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1909 if (This->isRecordingState) {
1910 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1911 if (NULL == lightInfo) {
1912 return D3DERR_OUTOFVIDEOMEMORY;
1914 lightInfo->OriginalIndex = Index;
1915 lightInfo->glIndex = -1;
1916 lightInfo->enabledChanged = TRUE;
1918 /* Add to the END of the chain of lights changes to be replayed */
1919 if (This->UpdateStateBlock->lights == NULL) {
1920 This->UpdateStateBlock->lights = lightInfo;
1922 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1923 while (temp->next != NULL) temp=temp->next;
1924 temp->next = lightInfo;
1926 TRACE("Recording... not performing anything more\n");
1930 /* Not recording... So, locate the light in the live lights */
1931 lightInfo = This->StateBlock->lights;
1932 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1934 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1935 if (lightInfo == NULL) {
1936 D3DLIGHT8 lightParms;
1937 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1938 wait until someone confirms it seems to work! */
1939 TRACE("Light enabled requested but light not defined, so defining one!\n");
1940 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1941 lightParms.Diffuse.r = 1.0;
1942 lightParms.Diffuse.g = 1.0;
1943 lightParms.Diffuse.b = 1.0;
1944 lightParms.Diffuse.a = 0.0;
1945 lightParms.Specular.r = 0.0;
1946 lightParms.Specular.g = 0.0;
1947 lightParms.Specular.b = 0.0;
1948 lightParms.Specular.a = 0.0;
1949 lightParms.Ambient.r = 0.0;
1950 lightParms.Ambient.g = 0.0;
1951 lightParms.Ambient.b = 0.0;
1952 lightParms.Ambient.a = 0.0;
1953 lightParms.Position.x = 0.0;
1954 lightParms.Position.y = 0.0;
1955 lightParms.Position.z = 0.0;
1956 lightParms.Direction.x = 0.0;
1957 lightParms.Direction.y = 0.0;
1958 lightParms.Direction.z = 1.0;
1959 lightParms.Range = 0.0;
1960 lightParms.Falloff = 0.0;
1961 lightParms.Attenuation0 = 0.0;
1962 lightParms.Attenuation1 = 0.0;
1963 lightParms.Attenuation2 = 0.0;
1964 lightParms.Theta = 0.0;
1965 lightParms.Phi = 0.0;
1966 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1968 /* Search for it again! Should be fairly quick as near head of list */
1969 lightInfo = This->StateBlock->lights;
1970 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1971 if (lightInfo == NULL) {
1972 FIXME("Adding default lights has failed dismally\n");
1973 return D3DERR_INVALIDCALL;
1977 /* OK, we now have a light... */
1978 if (Enable == FALSE) {
1980 /* If we are disabling it, check it was enabled, and
1981 still only do something if it has assigned a glIndex (which it should have!) */
1982 if (lightInfo->lightEnabled && (lightInfo->glIndex != -1)) {
1983 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1985 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1986 checkGLcall("glDisable GL_LIGHT0+Index");
1989 TRACE("Nothing to do as light was not enabled\n");
1991 lightInfo->lightEnabled = FALSE;
1994 /* We are enabling it. If it is enabled, its really simple */
1995 if (lightInfo->lightEnabled) {
1997 TRACE("Nothing to do as light was enabled\n");
1999 /* If it already has a glIndex, its still simple */
2000 } else if (lightInfo->glIndex != -1) {
2001 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2002 lightInfo->lightEnabled = TRUE;
2004 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2005 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2008 /* Otherwise got to find space - lights are ordered gl indexes first */
2010 PLIGHTINFOEL *bsf = NULL;
2011 PLIGHTINFOEL *pos = This->StateBlock->lights;
2012 PLIGHTINFOEL *prev = NULL;
2016 /* Try to minimize changes as much as possible */
2017 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2019 /* Try to remember which index can be replaced if necessary */
2020 if (bsf==NULL && pos->lightEnabled == FALSE) {
2021 /* Found a light we can replace, save as best replacement */
2025 /* Step to next space */
2031 /* If we have too many active lights, fail the call */
2032 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2033 FIXME("Program requests too many concurrent lights\n");
2034 return D3DERR_INVALIDCALL;
2036 /* If we have allocated all lights, but not all are enabled,
2037 reuse one which is not enabled */
2038 } else if (Index == This->maxConcurrentLights) {
2039 /* use bsf - Simply swap the new light and the BSF one */
2040 PLIGHTINFOEL *bsfNext = bsf->next;
2041 PLIGHTINFOEL *bsfPrev = bsf->prev;
2044 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2045 if (bsf->prev != NULL) {
2046 bsf->prev->next = lightInfo;
2048 This->StateBlock->lights = lightInfo;
2051 /* If not side by side, lots of chains to update */
2052 if (bsf->next != lightInfo) {
2053 lightInfo->prev->next = bsf;
2054 bsf->next->prev = lightInfo;
2055 bsf->next = lightInfo->next;
2056 bsf->prev = lightInfo->prev;
2057 lightInfo->next = bsfNext;
2058 lightInfo->prev = bsfPrev;
2062 bsf->prev = lightInfo;
2063 bsf->next = lightInfo->next;
2064 lightInfo->next = bsf;
2065 lightInfo->prev = bsfPrev;
2070 glIndex = bsf->glIndex;
2072 lightInfo->glIndex = glIndex;
2073 lightInfo->lightEnabled = TRUE;
2075 /* Finally set up the light in gl itself */
2076 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2078 setup_light(iface, glIndex, lightInfo);
2079 glEnable(GL_LIGHT0 + glIndex);
2080 checkGLcall("glEnable GL_LIGHT0 new setup");
2083 /* If we reached the end of the allocated lights, with space in the
2084 gl lights, setup a new light */
2085 } else if (pos->glIndex == -1) {
2087 /* We reached the end of the allocated gl lights, so already
2088 know the index of the next one! */
2090 lightInfo->glIndex = glIndex;
2091 lightInfo->lightEnabled = TRUE;
2093 /* In an ideal world, its already in the right place */
2094 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2095 /* No need to move it */
2097 /* Remove this light from the list */
2098 lightInfo->prev->next = lightInfo->next;
2099 if (lightInfo->next != NULL) {
2100 lightInfo->next->prev = lightInfo->prev;
2103 /* Add in at appropriate place (inbetween prev and pos) */
2104 lightInfo->prev = prev;
2105 lightInfo->next = pos;
2107 This->StateBlock->lights = lightInfo;
2109 prev->next = lightInfo;
2112 pos->prev = lightInfo;
2116 /* Finally set up the light in gl itself */
2117 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2119 setup_light(iface, glIndex, lightInfo);
2120 glEnable(GL_LIGHT0 + glIndex);
2121 checkGLcall("glEnable GL_LIGHT0 new setup");
2129 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2131 PLIGHTINFOEL *lightInfo = NULL;
2132 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2133 TRACE("(%p) : for idx(%ld)\n", This, Index);
2135 /* Locate the light in the live lights */
2136 lightInfo = This->StateBlock->lights;
2137 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2139 if (lightInfo == NULL) {
2140 TRACE("Light enabled state requested but light not defined\n");
2141 return D3DERR_INVALIDCALL;
2143 *pEnable = lightInfo->lightEnabled;
2146 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2147 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2148 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2150 /* Validate Index */
2151 if (Index >= GL_LIMITS(clipplanes)) {
2152 TRACE("Application has requested clipplane this device doesn't support\n");
2153 return D3DERR_INVALIDCALL;
2156 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2157 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2158 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2159 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2160 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2161 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2163 /* Handle recording of state blocks */
2164 if (This->isRecordingState) {
2165 TRACE("Recording... not performing anything\n");
2173 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2174 glMatrixMode(GL_MODELVIEW);
2176 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2178 TRACE("Clipplane [%f,%f,%f,%f]\n",
2179 This->UpdateStateBlock->clipplane[Index][0],
2180 This->UpdateStateBlock->clipplane[Index][1],
2181 This->UpdateStateBlock->clipplane[Index][2],
2182 This->UpdateStateBlock->clipplane[Index][3]);
2183 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2184 checkGLcall("glClipPlane");
2192 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2193 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2194 TRACE("(%p) : for idx %ld\n", This, Index);
2196 /* Validate Index */
2197 if (Index >= GL_LIMITS(clipplanes)) {
2198 TRACE("Application has requested clipplane this device doesn't support\n");
2199 return D3DERR_INVALIDCALL;
2202 pPlane[0] = This->StateBlock->clipplane[Index][0];
2203 pPlane[1] = This->StateBlock->clipplane[Index][1];
2204 pPlane[2] = This->StateBlock->clipplane[Index][2];
2205 pPlane[3] = This->StateBlock->clipplane[Index][3];
2208 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2213 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2214 DWORD OldValue = This->StateBlock->renderstate[State];
2216 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2217 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2218 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2219 This->UpdateStateBlock->renderstate[State] = Value;
2221 /* Handle recording of state blocks */
2222 if (This->isRecordingState) {
2223 TRACE("Recording... not performing anything\n");
2230 case D3DRS_FILLMODE :
2231 switch ((D3DFILLMODE) Value) {
2232 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2233 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2234 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2236 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2238 checkGLcall("glPolygonMode (fillmode)");
2241 case D3DRS_LIGHTING :
2243 glEnable(GL_LIGHTING);
2244 checkGLcall("glEnable GL_LIGHTING");
2246 glDisable(GL_LIGHTING);
2247 checkGLcall("glDisable GL_LIGHTING");
2251 case D3DRS_ZENABLE :
2252 switch ((D3DZBUFFERTYPE) Value) {
2254 glDisable(GL_DEPTH_TEST);
2255 checkGLcall("glDisable GL_DEPTH_TEST");
2258 glEnable(GL_DEPTH_TEST);
2259 checkGLcall("glEnable GL_DEPTH_TEST");
2262 glEnable(GL_DEPTH_TEST);
2263 checkGLcall("glEnable GL_DEPTH_TEST");
2264 FIXME("W buffer is not well handled\n");
2267 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2271 case D3DRS_CULLMODE :
2273 /* If we are culling "back faces with clockwise vertices" then
2274 set front faces to be counter clockwise and enable culling
2276 switch ((D3DCULL) Value) {
2278 glDisable(GL_CULL_FACE);
2279 checkGLcall("glDisable GL_CULL_FACE");
2282 glEnable(GL_CULL_FACE);
2283 checkGLcall("glEnable GL_CULL_FACE");
2284 if (This->renderUpsideDown) {
2286 checkGLcall("glFrontFace GL_CW");
2288 glFrontFace(GL_CCW);
2289 checkGLcall("glFrontFace GL_CCW");
2291 glCullFace(GL_BACK);
2294 glEnable(GL_CULL_FACE);
2295 checkGLcall("glEnable GL_CULL_FACE");
2296 if (This->renderUpsideDown) {
2297 glFrontFace(GL_CCW);
2298 checkGLcall("glFrontFace GL_CCW");
2301 checkGLcall("glFrontFace GL_CW");
2303 glCullFace(GL_BACK);
2306 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2310 case D3DRS_SHADEMODE :
2311 switch ((D3DSHADEMODE) Value) {
2313 glShadeModel(GL_FLAT);
2314 checkGLcall("glShadeModel");
2316 case D3DSHADE_GOURAUD:
2317 glShadeModel(GL_SMOOTH);
2318 checkGLcall("glShadeModel");
2320 case D3DSHADE_PHONG:
2321 FIXME("D3DSHADE_PHONG isn't supported?\n");
2324 return D3DERR_INVALIDCALL;
2326 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2330 case D3DRS_DITHERENABLE :
2332 glEnable(GL_DITHER);
2333 checkGLcall("glEnable GL_DITHER");
2335 glDisable(GL_DITHER);
2336 checkGLcall("glDisable GL_DITHER");
2340 case D3DRS_ZWRITEENABLE :
2343 checkGLcall("glDepthMask");
2346 checkGLcall("glDepthMask");
2352 int glParm = GL_LESS;
2354 switch ((D3DCMPFUNC) Value) {
2355 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2356 case D3DCMP_LESS: glParm=GL_LESS; break;
2357 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2358 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2359 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2360 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2361 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2362 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2364 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2366 glDepthFunc(glParm);
2367 checkGLcall("glDepthFunc");
2371 case D3DRS_AMBIENT :
2374 D3DCOLORTOGLFLOAT4(Value, col);
2375 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2376 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2377 checkGLcall("glLightModel for MODEL_AMBIENT");
2382 case D3DRS_ALPHABLENDENABLE :
2385 checkGLcall("glEnable GL_BLEND");
2387 glDisable(GL_BLEND);
2388 checkGLcall("glDisable GL_BLEND");
2392 case D3DRS_SRCBLEND :
2393 case D3DRS_DESTBLEND :
2395 int newVal = GL_ZERO;
2397 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2398 case D3DBLEND_ONE : newVal = GL_ONE; break;
2399 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2400 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2401 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2402 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2403 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2404 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2405 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2406 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2407 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2409 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2410 This->srcBlend = newVal;
2411 This->dstBlend = newVal;
2414 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2415 This->srcBlend = newVal;
2416 This->dstBlend = newVal;
2419 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2422 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2423 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2424 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2425 glBlendFunc(This->srcBlend, This->dstBlend);
2427 checkGLcall("glBlendFunc");
2431 case D3DRS_ALPHATESTENABLE :
2433 glEnable(GL_ALPHA_TEST);
2434 checkGLcall("glEnable GL_ALPHA_TEST");
2436 glDisable(GL_ALPHA_TEST);
2437 checkGLcall("glDisable GL_ALPHA_TEST");
2441 case D3DRS_ALPHAFUNC :
2443 int glParm = GL_LESS;
2444 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2446 switch ((D3DCMPFUNC) Value) {
2447 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2448 case D3DCMP_LESS: glParm = GL_LESS; break;
2449 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2450 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2451 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2452 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2453 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2454 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2456 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2458 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2459 glAlphaFunc(glParm, ref);
2460 This->alphafunc = glParm;
2461 checkGLcall("glAlphaFunc");
2465 case D3DRS_ALPHAREF :
2467 int glParm = This->alphafunc;
2470 ref = ((float) Value) / 255.0f;
2471 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2472 glAlphaFunc(glParm, ref);
2473 checkGLcall("glAlphaFunc");
2477 case D3DRS_CLIPPLANEENABLE :
2478 case D3DRS_CLIPPING :
2480 /* Ensure we only do the changed clip planes */
2481 DWORD enable = 0xFFFFFFFF;
2482 DWORD disable = 0x00000000;
2484 /* If enabling / disabling all */
2485 if (State == D3DRS_CLIPPING) {
2487 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2490 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2494 enable = Value & ~OldValue;
2495 disable = ~Value & OldValue;
2498 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2499 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2500 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2501 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2502 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2503 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2505 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2506 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2507 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2508 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2509 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2510 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2512 /** update clipping status */
2514 This->StateBlock->clip_status.ClipUnion = 0;
2515 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2517 This->StateBlock->clip_status.ClipUnion = 0;
2518 This->StateBlock->clip_status.ClipIntersection = 0;
2523 case D3DRS_BLENDOP :
2525 int glParm = GL_FUNC_ADD;
2527 switch ((D3DBLENDOP) Value) {
2528 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2529 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2530 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2531 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2532 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2534 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2536 TRACE("glBlendEquation(%x)\n", glParm);
2537 glBlendEquation(glParm);
2538 checkGLcall("glBlendEquation");
2542 case D3DRS_TEXTUREFACTOR :
2546 /* Note the texture color applies to all textures whereas
2547 GL_TEXTURE_ENV_COLOR applies to active only */
2549 D3DCOLORTOGLFLOAT4(Value, col);
2550 /* Set the default alpha blend color */
2551 glBlendColor(col[0], col[1], col[2], col[3]);
2552 checkGLcall("glBlendColor");
2554 /* And now the default texture color as well */
2555 for (i = 0; i < GL_LIMITS(textures); i++) {
2557 /* Note the D3DRS value applies to all textures, but GL has one
2558 per texture, so apply it now ready to be used! */
2559 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2560 #if defined(GL_VERSION_1_3)
2561 glActiveTexture(GL_TEXTURE0 + i);
2563 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2565 checkGLcall("Activate texture.. to update const color");
2567 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2570 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2571 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2576 case D3DRS_SPECULARENABLE :
2578 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2579 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2580 specular color. This is wrong:
2581 Separate specular color means the specular colour is maintained separately, whereas
2582 single color means it is merged in. However in both cases they are being used to
2584 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2585 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2589 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2590 checkGLcall("glMaterialfv");
2591 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2592 glEnable(GL_COLOR_SUM_EXT);
2594 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2596 checkGLcall("glEnable(GL_COLOR_SUM)");
2598 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2600 /* for the case of enabled lighting: */
2601 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2602 checkGLcall("glMaterialfv");
2604 /* for the case of disabled lighting: */
2605 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2606 glDisable(GL_COLOR_SUM_EXT);
2608 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2610 checkGLcall("glDisable(GL_COLOR_SUM)");
2615 case D3DRS_STENCILENABLE :
2617 glEnable(GL_STENCIL_TEST);
2618 checkGLcall("glEnable GL_STENCIL_TEST");
2620 glDisable(GL_STENCIL_TEST);
2621 checkGLcall("glDisable GL_STENCIL_TEST");
2625 case D3DRS_STENCILFUNC :
2627 int glParm = GL_ALWAYS;
2628 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2629 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2631 switch ((D3DCMPFUNC) Value) {
2632 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2633 case D3DCMP_LESS: glParm=GL_LESS; break;
2634 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2635 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2636 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2637 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2638 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2639 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2641 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2643 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2644 This->stencilfunc = glParm;
2645 glStencilFunc(glParm, ref, mask);
2646 checkGLcall("glStencilFunc");
2650 case D3DRS_STENCILREF :
2652 int glParm = This->stencilfunc;
2654 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2657 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2658 glStencilFunc(glParm, ref, mask);
2659 checkGLcall("glStencilFunc");
2663 case D3DRS_STENCILMASK :
2665 int glParm = This->stencilfunc;
2666 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2667 GLuint mask = Value;
2669 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2670 glStencilFunc(glParm, ref, mask);
2671 checkGLcall("glStencilFunc");
2675 case D3DRS_STENCILFAIL :
2681 fail = StencilOp(Value);
2682 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2683 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2684 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2685 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2687 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2688 glStencilOp(fail, zfail, zpass);
2689 checkGLcall("glStencilOp(fail, zfail, zpass);");
2692 case D3DRS_STENCILZFAIL :
2698 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2699 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2700 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2701 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2702 zfail = StencilOp(Value);
2704 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2705 glStencilOp(fail, zfail, zpass);
2706 checkGLcall("glStencilOp(fail, zfail, zpass);");
2709 case D3DRS_STENCILPASS :
2715 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2716 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2717 zpass = StencilOp(Value);
2718 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2719 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2721 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2722 glStencilOp(fail, zfail, zpass);
2723 checkGLcall("glStencilOp(fail, zfail, zpass);");
2727 case D3DRS_STENCILWRITEMASK :
2729 glStencilMask(Value);
2730 TRACE("glStencilMask(%lu)\n", Value);
2731 checkGLcall("glStencilMask");
2735 case D3DRS_FOGENABLE :
2737 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2739 checkGLcall("glEnable GL_FOG");
2742 checkGLcall("glDisable GL_FOG");
2747 case D3DRS_RANGEFOGENABLE :
2750 TRACE("Enabled RANGEFOG");
2752 TRACE("Disabled RANGEFOG");
2757 case D3DRS_FOGCOLOR :
2760 D3DCOLORTOGLFLOAT4(Value, col);
2761 /* Set the default alpha blend color */
2762 glFogfv(GL_FOG_COLOR, &col[0]);
2763 checkGLcall("glFog GL_FOG_COLOR");
2767 case D3DRS_FOGTABLEMODE :
2769 glHint(GL_FOG_HINT, GL_NICEST);
2771 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2772 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2773 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2774 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2776 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2778 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2779 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2784 case D3DRS_FOGVERTEXMODE :
2786 glHint(GL_FOG_HINT, GL_FASTEST);
2788 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2789 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2790 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2791 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2793 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2795 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2796 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2801 case D3DRS_FOGSTART :
2804 glFogfv(GL_FOG_START, &tmpvalue.f);
2805 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2806 TRACE("Fog Start == %f\n", tmpvalue.f);
2813 glFogfv(GL_FOG_END, &tmpvalue.f);
2814 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2815 TRACE("Fog End == %f\n", tmpvalue.f);
2819 case D3DRS_FOGDENSITY :
2822 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2823 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2827 case D3DRS_VERTEXBLEND :
2829 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2830 TRACE("Vertex Blending state to %ld\n", Value);
2834 case D3DRS_TWEENFACTOR :
2837 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2838 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2842 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2844 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2848 case D3DRS_COLORVERTEX :
2849 case D3DRS_DIFFUSEMATERIALSOURCE :
2850 case D3DRS_SPECULARMATERIALSOURCE :
2851 case D3DRS_AMBIENTMATERIALSOURCE :
2852 case D3DRS_EMISSIVEMATERIALSOURCE :
2854 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2856 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2857 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2858 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2859 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2860 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2861 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2863 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2864 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2865 Parm = GL_AMBIENT_AND_DIFFUSE;
2869 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2871 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2873 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2880 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2882 This->tracking_color = NEEDS_TRACKING;
2883 This->tracking_parm = Parm;
2887 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2892 case D3DRS_LINEPATTERN :
2898 tmppattern.d = Value;
2900 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2902 if (tmppattern.lp.wRepeatFactor) {
2903 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2904 checkGLcall("glLineStipple(repeat, linepattern)");
2905 glEnable(GL_LINE_STIPPLE);
2906 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2908 glDisable(GL_LINE_STIPPLE);
2909 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2918 TRACE("ZBias value %f\n", tmpvalue.f);
2919 glPolygonOffset(0, -tmpvalue.f);
2920 checkGLcall("glPolygonOffset(0, -Value)");
2921 glEnable(GL_POLYGON_OFFSET_FILL);
2922 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2923 glEnable(GL_POLYGON_OFFSET_LINE);
2924 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2925 glEnable(GL_POLYGON_OFFSET_POINT);
2926 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2928 glDisable(GL_POLYGON_OFFSET_FILL);
2929 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2930 glDisable(GL_POLYGON_OFFSET_LINE);
2931 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2932 glDisable(GL_POLYGON_OFFSET_POINT);
2933 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2938 case D3DRS_NORMALIZENORMALS :
2940 glEnable(GL_NORMALIZE);
2941 checkGLcall("glEnable(GL_NORMALIZE);");
2943 glDisable(GL_NORMALIZE);
2944 checkGLcall("glDisable(GL_NORMALIZE);");
2948 case D3DRS_POINTSIZE :
2950 TRACE("Set point size to %f\n", tmpvalue.f);
2951 glPointSize(tmpvalue.f);
2952 checkGLcall("glPointSize(...);");
2955 case D3DRS_POINTSIZE_MIN :
2956 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2958 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2959 checkGLcall("glPointParameterfEXT(...);");
2961 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2965 case D3DRS_POINTSIZE_MAX :
2966 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2968 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2969 checkGLcall("glPointParameterfEXT(...);");
2971 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2975 case D3DRS_POINTSCALE_A :
2976 case D3DRS_POINTSCALE_B :
2977 case D3DRS_POINTSCALE_C :
2978 case D3DRS_POINTSCALEENABLE :
2980 /* If enabled, supply the parameters, otherwise fall back to defaults */
2981 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2982 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2983 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2984 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2985 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2987 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2988 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2989 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2991 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2994 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2995 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2996 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2997 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2999 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
3005 case D3DRS_COLORWRITEENABLE :
3007 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3008 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3009 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3010 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3011 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3012 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3013 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3014 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3015 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3016 checkGLcall("glColorMask(...)");
3020 case D3DRS_LOCALVIEWER :
3022 GLint state = (Value) ? 1 : 0;
3023 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3024 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3028 case D3DRS_LASTPIXEL :
3031 TRACE("Last Pixel Drawing Enabled\n");
3033 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3038 case D3DRS_SOFTWAREVERTEXPROCESSING :
3041 TRACE("Software Processing Enabled\n");
3043 TRACE("Software Processing Disabled\n");
3048 /** not supported */
3049 case D3DRS_ZVISIBLE :
3052 return D3DERR_INVALIDCALL;
3055 /* Unhandled yet...! */
3056 case D3DRS_EDGEANTIALIAS :
3059 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3061 checkGLcall("glEnable GL_BLEND");
3062 glEnable(GL_LINE_SMOOTH);
3063 checkGLcall("glEnable Gl_LINE_SMOOTH");
3065 glDisable(GL_BLEND);
3066 checkGLcall("glDisable GL_BLEND");
3067 glDisable(GL_LINE_SMOOTH);
3068 checkGLcall("glDisable GL_LINE_SMOOTH");
3081 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3084 case D3DRS_POINTSPRITEENABLE :
3086 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
3087 TRACE("Point sprites not supported\n");
3092 glEnable(GL_POINT_SPRITE_ARB);
3093 checkGLcall("glEnable GL_POINT_SPRITE_ARB");
3095 glDisable(GL_POINT_SPRITE_ARB);
3096 checkGLcall("glDisable GL_POINT_SPRITE_ARB");
3100 case D3DRS_MULTISAMPLEANTIALIAS :
3102 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
3103 TRACE("Multisample antialiasing not supported\n");
3108 glEnable(GL_MULTISAMPLE_ARB);
3109 checkGLcall("glEnable GL_MULTISAMPLE_ARB");
3111 glDisable(GL_MULTISAMPLE_ARB);
3112 checkGLcall("glDisable GL_MULTISAMPLE_ARB");
3116 case D3DRS_MULTISAMPLEMASK :
3117 case D3DRS_PATCHEDGESTYLE :
3118 case D3DRS_PATCHSEGMENTS :
3119 case D3DRS_DEBUGMONITORTOKEN :
3120 case D3DRS_POSITIONORDER :
3121 case D3DRS_NORMALORDER :
3122 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3123 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3126 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3133 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3134 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3135 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3136 *pValue = This->StateBlock->renderstate[State];
3139 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3140 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3142 TRACE("(%p)\n", This);
3144 return IDirect3DDeviceImpl_BeginStateBlock(This);
3146 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3147 IDirect3DStateBlockImpl* pSB;
3148 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3151 TRACE("(%p)\n", This);
3153 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3154 *pToken = (DWORD) pSB;
3158 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3159 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3160 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3162 TRACE("(%p)\n", This);
3164 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3167 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3168 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3169 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3171 TRACE("(%p)\n", This);
3173 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3175 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3176 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3177 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3179 TRACE("(%p)\n", This);
3181 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3184 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3185 IDirect3DStateBlockImpl* pSB;
3186 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3189 TRACE("(%p) : for type %d\n", This, Type);
3191 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3192 *pToken = (DWORD) pSB;
3196 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3197 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3198 FIXME("(%p) : stub\n", This);
3199 if (NULL == pClipStatus) {
3200 return D3DERR_INVALIDCALL;
3202 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3203 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3206 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3207 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3208 FIXME("(%p) : stub\n", This);
3209 if (NULL == pClipStatus) {
3210 return D3DERR_INVALIDCALL;
3212 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3213 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3216 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3217 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3218 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3219 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3221 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3224 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3226 IDirect3DBaseTexture8 *oldTxt;
3227 BOOL reapplyStates = TRUE;
3228 INT oldTextureDimensions = -1;
3229 DWORD reapplyFlags = 0;
3231 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3232 D3DRESOURCETYPE textureType;
3234 oldTxt = This->UpdateStateBlock->textures[Stage];
3235 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3237 /* Reject invalid texture units */
3238 if (Stage >= GL_LIMITS(textures)) {
3239 TRACE("Attempt to access invalid texture rejected\n");
3240 return D3DERR_INVALIDCALL;
3243 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3244 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3245 This->UpdateStateBlock->textures[Stage] = pTexture;
3247 /* Handle recording of state blocks */
3248 if (This->isRecordingState) {
3249 TRACE("Recording... not performing anything\n");
3253 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3256 /* Make appropriate texture active */
3257 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3258 #if defined(GL_VERSION_1_3)
3259 glActiveTexture(GL_TEXTURE0 + Stage);
3260 checkGLcall("glActiveTexture");
3262 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3263 checkGLcall("glActiveTextureARB");
3265 } else if (Stage>0) {
3266 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3269 /* Decrement the count of the previous texture */
3270 if (NULL != oldTxt) {
3271 IDirect3DBaseTexture8Impl_Release(oldTxt);
3274 if (NULL != pTexture) {
3275 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3277 /* Now setup the texture appropraitly */
3278 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3280 if (textureType == D3DRTYPE_TEXTURE) {
3281 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3282 TRACE("Skipping setting texture as old == new\n");
3283 reapplyStates = FALSE;
3285 /* Standard 2D texture */
3286 TRACE("Standard 2d texture\n");
3287 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3289 /* Load up the texture now */
3290 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3292 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3293 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3294 TRACE("Skipping setting texture as old == new\n");
3295 reapplyStates = FALSE;
3297 /* Standard 3D (volume) texture */
3298 TRACE("Standard 3d texture\n");
3299 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3301 /* Load up the texture now */
3302 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3304 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3305 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3306 TRACE("Skipping setting texture as old == new\n");
3307 reapplyStates = FALSE;
3309 /* Standard Cube texture */
3310 TRACE("Standard Cube texture\n");
3311 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3313 /* Load up the texture now */
3314 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3317 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3320 TRACE("Setting to no texture (ie default texture)\n");
3321 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3322 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3323 checkGLcall("glBindTexture");
3324 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3327 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3328 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3329 glDisable(oldTextureDimensions);
3330 checkGLcall("Disable oldTextureDimensions");
3331 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3332 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3333 checkGLcall("glEnable new texture dimensions");
3336 /* If Alpha arg1 is texture then handle the special case when there changes between a
3337 texture and no texture - See comments in set_tex_op */
3338 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3339 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3341 reapplyFlags |= REAPPLY_ALPHAOP;
3346 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3347 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3348 if (reapplyStates) {
3349 setupTextureStates(iface, Stage, reapplyFlags);
3357 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3358 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3359 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3360 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3364 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3365 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3371 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3373 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3375 /* Reject invalid texture units */
3376 if (Stage >= GL_LIMITS(textures)) {
3377 TRACE("Attempt to access invalid texture rejected\n");
3378 return D3DERR_INVALIDCALL;
3381 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3382 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3383 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3385 /* Handle recording of state blocks */
3386 if (This->isRecordingState) {
3387 TRACE("Recording... not performing anything\n");
3393 /* Make appropriate texture active */
3394 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3395 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3396 #if defined(GL_VERSION_1_3)
3397 glActiveTexture(GL_TEXTURE0 + Stage);
3398 vcheckGLcall("glActiveTexture");
3400 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3401 vcheckGLcall("glActiveTextureARB");
3403 } else if (Stage > 0) {
3404 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3409 case D3DTSS_MINFILTER :
3410 case D3DTSS_MIPFILTER :
3412 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3413 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3414 GLint realVal = GL_LINEAR;
3416 if (ValueMIN == D3DTEXF_NONE) {
3417 /* Doesn't really make sense - Windows just seems to disable
3418 mipmapping when this occurs */
3419 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3420 realVal = GL_LINEAR;
3421 } else if (ValueMIN == D3DTEXF_POINT) {
3423 if (ValueMIP == D3DTEXF_NONE) {
3424 realVal = GL_NEAREST;
3425 } else if (ValueMIP == D3DTEXF_POINT) {
3426 realVal = GL_NEAREST_MIPMAP_NEAREST;
3427 } else if (ValueMIP == D3DTEXF_LINEAR) {
3428 realVal = GL_NEAREST_MIPMAP_LINEAR;
3430 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3431 realVal = GL_NEAREST;
3433 } else if (ValueMIN == D3DTEXF_LINEAR) {
3435 if (ValueMIP == D3DTEXF_NONE) {
3436 realVal = GL_LINEAR;
3437 } else if (ValueMIP == D3DTEXF_POINT) {
3438 realVal = GL_LINEAR_MIPMAP_NEAREST;
3439 } else if (ValueMIP == D3DTEXF_LINEAR) {
3440 realVal = GL_LINEAR_MIPMAP_LINEAR;
3442 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3443 realVal = GL_LINEAR;
3445 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3446 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3447 if (ValueMIP == D3DTEXF_NONE) {
3448 realVal = GL_LINEAR_MIPMAP_LINEAR;
3449 } else if (ValueMIP == D3DTEXF_POINT) {
3450 realVal = GL_LINEAR_MIPMAP_NEAREST;
3451 } else if (ValueMIP == D3DTEXF_LINEAR) {
3452 realVal = GL_LINEAR_MIPMAP_LINEAR;
3454 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3455 realVal = GL_LINEAR;
3458 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3459 realVal = GL_LINEAR;
3462 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3463 realVal = GL_LINEAR_MIPMAP_LINEAR;
3466 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3467 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3468 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3470 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3472 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3473 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3474 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3475 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3476 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3481 case D3DTSS_MAGFILTER :
3483 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3484 GLint realVal = GL_NEAREST;
3486 if (ValueMAG == D3DTEXF_POINT) {
3487 realVal = GL_NEAREST;
3488 } else if (ValueMAG == D3DTEXF_LINEAR) {
3489 realVal = GL_LINEAR;
3490 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3491 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3492 realVal = GL_LINEAR;
3494 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3495 realVal = GL_NEAREST;
3498 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3499 realVal = GL_NEAREST;
3501 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3502 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3503 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3505 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3507 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3508 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3509 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3510 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3511 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3516 case D3DTSS_MAXMIPLEVEL :
3519 * Not really the same, but the more apprioprate than nothing
3521 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3522 GL_TEXTURE_BASE_LEVEL,
3523 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3524 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3528 case D3DTSS_MAXANISOTROPY :
3530 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3531 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3532 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3533 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3534 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3539 case D3DTSS_MIPMAPLODBIAS :
3541 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3543 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3544 GL_TEXTURE_LOD_BIAS_EXT,
3546 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3551 case D3DTSS_ALPHAOP :
3552 case D3DTSS_COLOROP :
3555 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3556 /* TODO: Disable by making this and all later levels disabled */
3557 glDisable(GL_TEXTURE_1D);
3558 checkGLcall("Disable GL_TEXTURE_1D");
3559 glDisable(GL_TEXTURE_2D);
3560 checkGLcall("Disable GL_TEXTURE_2D");
3561 glDisable(GL_TEXTURE_3D);
3562 checkGLcall("Disable GL_TEXTURE_3D");
3563 break; /* Don't bother setting the texture operations */
3565 /* Enable only the appropriate texture dimension */
3566 if (Type == D3DTSS_COLOROP) {
3567 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3568 glEnable(GL_TEXTURE_1D);
3569 checkGLcall("Enable GL_TEXTURE_1D");
3571 glDisable(GL_TEXTURE_1D);
3572 checkGLcall("Disable GL_TEXTURE_1D");
3574 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3575 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3576 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3577 checkGLcall("Enable GL_TEXTURE_2D");
3579 glEnable(GL_TEXTURE_2D);
3580 checkGLcall("Enable GL_TEXTURE_2D");
3583 glDisable(GL_TEXTURE_2D);
3584 checkGLcall("Disable GL_TEXTURE_2D");
3586 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3587 glEnable(GL_TEXTURE_3D);
3588 checkGLcall("Enable GL_TEXTURE_3D");
3590 glDisable(GL_TEXTURE_3D);
3591 checkGLcall("Disable GL_TEXTURE_3D");
3593 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3594 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3595 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3597 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3598 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3602 /* Drop through... (Except disable case) */
3603 case D3DTSS_COLORARG0 :
3604 case D3DTSS_COLORARG1 :
3605 case D3DTSS_COLORARG2 :
3606 case D3DTSS_ALPHAARG0 :
3607 case D3DTSS_ALPHAARG1 :
3608 case D3DTSS_ALPHAARG2 :
3610 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3611 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3613 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3614 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3615 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3616 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3618 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3619 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3620 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3621 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3627 case D3DTSS_ADDRESSU :
3628 case D3DTSS_ADDRESSV :
3629 case D3DTSS_ADDRESSW :
3631 GLint wrapParm = GL_REPEAT;
3634 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3635 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3636 case D3DTADDRESS_BORDER:
3638 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3639 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3641 /* FIXME: Not right, but better */
3642 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3643 wrapParm = GL_REPEAT;
3647 case D3DTADDRESS_MIRROR:
3649 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3650 wrapParm = GL_MIRRORED_REPEAT_ARB;
3652 /* Unsupported in OpenGL pre-1.4 */
3653 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3654 wrapParm = GL_REPEAT;
3658 case D3DTADDRESS_MIRRORONCE:
3660 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3661 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3663 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3664 wrapParm = GL_REPEAT;
3670 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3671 wrapParm = GL_REPEAT;
3675 case D3DTSS_ADDRESSU:
3676 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3677 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3678 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3680 case D3DTSS_ADDRESSV:
3681 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3682 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3683 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3685 case D3DTSS_ADDRESSW:
3686 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3687 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3688 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3691 break; /** stupic compilator */
3696 case D3DTSS_BORDERCOLOR :
3699 D3DCOLORTOGLFLOAT4(Value, col);
3700 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3701 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3702 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3706 case D3DTSS_TEXCOORDINDEX :
3708 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3710 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3711 one flag, you can still specify an index value, which the system uses to
3712 determine the texture wrapping mode.
3713 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3714 means use the vertex position (camera-space) as the input texture coordinates
3715 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3716 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3717 to the TEXCOORDINDEX value */
3720 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3722 switch (Value & 0xFFFF0000) {
3723 case D3DTSS_TCI_PASSTHRU:
3724 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3725 glDisable(GL_TEXTURE_GEN_S);
3726 glDisable(GL_TEXTURE_GEN_T);
3727 glDisable(GL_TEXTURE_GEN_R);
3728 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3731 case D3DTSS_TCI_CAMERASPACEPOSITION:
3732 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3733 as the input texture coordinates for this stage's texture transformation. This
3734 equates roughly to EYE_LINEAR */
3736 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3737 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3738 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3739 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3740 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3742 glMatrixMode(GL_MODELVIEW);
3745 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3746 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3747 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3748 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3751 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3752 glEnable(GL_TEXTURE_GEN_S);
3753 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3754 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3755 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3756 glEnable(GL_TEXTURE_GEN_T);
3757 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3758 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3759 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3760 glEnable(GL_TEXTURE_GEN_R);
3761 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3762 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3763 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3767 case D3DTSS_TCI_CAMERASPACENORMAL:
3769 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3770 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3771 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3772 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3773 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3774 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3776 glMatrixMode(GL_MODELVIEW);
3779 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3780 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3781 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3782 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3785 glEnable(GL_TEXTURE_GEN_S);
3786 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3787 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3788 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3789 glEnable(GL_TEXTURE_GEN_T);
3790 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3791 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3792 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3793 glEnable(GL_TEXTURE_GEN_R);
3794 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3795 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3796 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3801 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3803 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3804 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3805 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3806 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3807 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3808 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3810 glMatrixMode(GL_MODELVIEW);
3813 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3814 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3815 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3816 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3819 glEnable(GL_TEXTURE_GEN_S);
3820 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3821 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3822 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3823 glEnable(GL_TEXTURE_GEN_T);
3824 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3825 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3826 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3827 glEnable(GL_TEXTURE_GEN_R);
3828 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3829 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3830 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3835 /* Unhandled types: */
3838 /* ? disable GL_TEXTURE_GEN_n ? */
3839 glDisable(GL_TEXTURE_GEN_S);
3840 glDisable(GL_TEXTURE_GEN_T);
3841 glDisable(GL_TEXTURE_GEN_R);
3842 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3849 case D3DTSS_TEXTURETRANSFORMFLAGS :
3850 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3853 case D3DTSS_BUMPENVMAT00 :
3854 case D3DTSS_BUMPENVMAT01 :
3855 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3857 case D3DTSS_BUMPENVMAT10 :
3858 case D3DTSS_BUMPENVMAT11 :
3859 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3862 case D3DTSS_BUMPENVLSCALE :
3863 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3866 case D3DTSS_BUMPENVLOFFSET :
3867 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3870 case D3DTSS_RESULTARG :
3871 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3875 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3876 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3883 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3884 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3885 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3888 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3889 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3890 FIXME("(%p) : stub\n", This);
3893 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3894 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3895 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3896 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3897 if (PaletteNumber >= MAX_PALETTES) {
3898 return D3DERR_INVALIDCALL;
3900 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3903 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3904 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3905 if (PaletteNumber >= MAX_PALETTES) {
3906 return D3DERR_INVALIDCALL;
3908 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3909 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3910 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3913 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3914 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3915 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3916 if (PaletteNumber >= MAX_PALETTES) {
3917 return D3DERR_INVALIDCALL;
3919 This->currentPalette = PaletteNumber;
3921 #if defined(GL_EXT_paletted_texture)
3922 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3926 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3927 GL_RGBA, /* internal format */
3928 256, /* table size */
3929 GL_RGBA, /* table format */
3930 GL_UNSIGNED_BYTE, /* table type */
3931 This->palettes[PaletteNumber]);
3932 checkGLcall("glColorTableEXT");
3937 /* Delayed palette handling ... waiting for software emulation into preload code */
3942 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3943 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3944 *PaletteNumber = This->currentPalette;
3945 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3948 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3950 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3951 This->StateBlock->streamIsUP = FALSE;
3953 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3954 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3958 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3959 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3961 IDirect3DIndexBuffer8 *pIB;
3962 D3DINDEXBUFFER_DESC IdxBufDsc;
3964 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3965 pIB = This->StateBlock->pIndexData;
3966 This->StateBlock->streamIsUP = FALSE;
3968 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
3969 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3970 minIndex, NumVertices, startIndex, primCount);
3972 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3973 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3979 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3984 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3985 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3987 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3988 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3990 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3992 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3993 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3994 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3995 This->StateBlock->streamIsUP = TRUE;
3996 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3997 This->StateBlock->stream_stride[0] = 0;
3998 This->StateBlock->stream_source[0] = NULL;
4000 /*stream zero settings set to null at end */
4003 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
4004 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4005 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4006 UINT VertexStreamZeroStride) {
4008 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4009 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),
4010 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4012 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
4013 if (IndexDataFormat == D3DFMT_INDEX16) {
4019 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
4020 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
4021 This->StateBlock->streamIsUP = TRUE;
4022 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
4023 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
4025 /*stream zero settings set to null at end */
4026 This->StateBlock->stream_source[0] = NULL;
4027 This->StateBlock->stream_stride[0] = 0;
4028 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
4032 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
4033 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4034 FIXME("(%p) : stub\n", This); return D3D_OK;
4036 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
4037 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4038 IDirect3DVertexShaderImpl* object;
4039 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4043 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
4044 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
4045 return D3DERR_INVALIDCALL;
4047 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
4048 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
4049 return D3DERR_OUTOFVIDEOMEMORY;
4052 /** Create the Vertex Shader */
4053 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
4054 /** TODO: check FAILED(res) */
4056 /** Create and Bind the Vertex Shader Declaration */
4057 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4058 /** TODO: check FAILED(res) */
4060 VertexShaders[i] = object;
4061 VertexShaderDeclarations[i] = attached_decl;
4062 *pHandle = VS_HIGHESTFIXEDFXF + i;
4063 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4067 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4068 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4070 This->UpdateStateBlock->VertexShader = Handle;
4071 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4072 This->UpdateStateBlock->Set.vertexShader = TRUE;
4074 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4075 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4076 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4077 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4078 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4079 } else { /* use a fvf, so desactivate the vshader decl */
4080 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4081 This->UpdateStateBlock->vertexShaderDecl = NULL;
4082 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4083 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4085 /* Handle recording of state blocks */
4086 if (This->isRecordingState) {
4087 TRACE("Recording... not performing anything\n");
4091 * TODO: merge HAL shaders context switching from prototype
4095 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4096 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4097 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4098 *pHandle = This->StateBlock->VertexShader;
4102 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4103 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4104 IDirect3DVertexShaderImpl* object;
4105 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4107 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4108 return D3DERR_INVALIDCALL;
4112 * Delete Vertex Shader
4114 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4115 if (NULL == object) {
4116 return D3DERR_INVALIDCALL;
4118 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4119 /* TODO: check validity of object */
4120 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4121 if (object->prgId != 0) {
4122 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4124 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4125 HeapFree(GetProcessHeap(), 0, (void *)object);
4126 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4129 * Delete Vertex Shader Declaration
4131 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4132 if (NULL == attached_decl) {
4133 return D3DERR_INVALIDCALL;
4135 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4136 /* TODO: check validity of object */
4137 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4138 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4139 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4144 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4145 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4147 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4148 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4149 return D3DERR_INVALIDCALL;
4151 if (NULL == pConstantData) {
4152 return D3DERR_INVALIDCALL;
4154 if (ConstantCount > 1) {
4155 const FLOAT* f = (const FLOAT*)pConstantData;
4157 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4158 for (i = 0; i < ConstantCount; ++i) {
4159 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4163 const FLOAT* f = (const FLOAT*) pConstantData;
4164 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4166 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4167 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4170 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4171 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4173 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4174 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4175 return D3DERR_INVALIDCALL;
4177 if (NULL == pConstantData) {
4178 return D3DERR_INVALIDCALL;
4180 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4183 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4184 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4185 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4187 attached_decl = VERTEX_SHADER_DECL(Handle);
4188 if (NULL == attached_decl) {
4189 return D3DERR_INVALIDCALL;
4191 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4193 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4194 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4195 IDirect3DVertexShaderImpl* object;
4197 object = VERTEX_SHADER(Handle);
4198 if (NULL == object) {
4199 return D3DERR_INVALIDCALL;
4201 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4204 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4205 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4206 IDirect3DIndexBuffer8 *oldIdxs;
4208 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4209 oldIdxs = This->StateBlock->pIndexData;
4211 This->UpdateStateBlock->Changed.Indices = TRUE;
4212 This->UpdateStateBlock->Set.Indices = TRUE;
4213 This->UpdateStateBlock->pIndexData = pIndexData;
4214 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4216 /* Handle recording of state blocks */
4217 if (This->isRecordingState) {
4218 TRACE("Recording... not performing anything\n");
4222 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRefInt(This->StateBlock->pIndexData);
4223 if (oldIdxs) IDirect3DIndexBuffer8Impl_ReleaseInt(oldIdxs);
4226 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4227 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4228 FIXME("(%p) : stub\n", This);
4230 *ppIndexData = This->StateBlock->pIndexData;
4231 /* up ref count on ppindexdata */
4232 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4233 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4237 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4238 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4239 IDirect3DPixelShaderImpl* object;
4243 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4244 if (NULL == pFunction || NULL == pHandle) {
4245 return D3DERR_INVALIDCALL;
4247 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4248 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4249 return D3DERR_OUTOFVIDEOMEMORY;
4252 /** Create the Pixel Shader */
4253 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4254 if (SUCCEEDED(res)) {
4255 PixelShaders[i] = object;
4256 *pHandle = VS_HIGHESTFIXEDFXF + i;
4259 *pHandle = 0xFFFFFFFF;
4263 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4264 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4266 This->UpdateStateBlock->PixelShader = Handle;
4267 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4268 This->UpdateStateBlock->Set.pixelShader = TRUE;
4270 /* Handle recording of state blocks */
4271 if (This->isRecordingState) {
4272 TRACE_(d3d_shader)("Recording... not performing anything\n");
4277 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4279 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4285 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4286 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4287 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4288 *pHandle = This->StateBlock->PixelShader;
4292 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4293 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4294 IDirect3DPixelShaderImpl* object;
4296 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4297 return D3DERR_INVALIDCALL;
4299 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4300 if (NULL == object) {
4301 return D3DERR_INVALIDCALL;
4303 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4304 /* TODO: check validity of object before free */
4305 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4306 if (object->prgId != 0) {
4307 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4309 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4310 HeapFree(GetProcessHeap(), 0, (void *)object);
4311 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4316 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4317 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4319 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4320 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4321 return D3DERR_INVALIDCALL;
4323 if (NULL == pConstantData) {
4324 return D3DERR_INVALIDCALL;
4326 if (ConstantCount > 1) {
4327 const FLOAT* f = (const FLOAT*)pConstantData;
4329 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4330 for (i = 0; i < ConstantCount; ++i) {
4331 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4335 const FLOAT* f = (const FLOAT*) pConstantData;
4336 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4338 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4339 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4342 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4343 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4345 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4346 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4347 return D3DERR_INVALIDCALL;
4349 if (NULL == pConstantData) {
4350 return D3DERR_INVALIDCALL;
4352 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4355 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4356 IDirect3DPixelShaderImpl* object;
4358 object = PIXEL_SHADER(Handle);
4359 if (NULL == object) {
4360 return D3DERR_INVALIDCALL;
4362 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4364 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4365 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4366 FIXME("(%p) : stub\n", This); return D3D_OK;
4368 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4369 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4370 FIXME("(%p) : stub\n", This); return D3D_OK;
4372 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4373 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4374 FIXME("(%p) : stub\n", This); return D3D_OK;
4377 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4378 IDirect3DVertexBuffer8 *oldSrc;
4379 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4381 oldSrc = This->StateBlock->stream_source[StreamNumber];
4382 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4384 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4385 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4386 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4387 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4389 /* Handle recording of state blocks */
4390 if (This->isRecordingState) {
4391 TRACE("Recording... not performing anything\n");
4395 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRefInt(pStreamData);
4396 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_ReleaseInt(oldSrc);
4399 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4400 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4401 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4402 *pStream = This->StateBlock->stream_source[StreamNumber];
4403 *pStride = This->StateBlock->stream_stride[StreamNumber];
4404 if (*pStream != NULL) IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4409 const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4411 IDirect3DDevice8Impl_QueryInterface,
4412 IDirect3DDevice8Impl_AddRef,
4413 IDirect3DDevice8Impl_Release,
4414 IDirect3DDevice8Impl_TestCooperativeLevel,
4415 IDirect3DDevice8Impl_GetAvailableTextureMem,
4416 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4417 IDirect3DDevice8Impl_GetDirect3D,
4418 IDirect3DDevice8Impl_GetDeviceCaps,
4419 IDirect3DDevice8Impl_GetDisplayMode,
4420 IDirect3DDevice8Impl_GetCreationParameters,
4421 IDirect3DDevice8Impl_SetCursorProperties,
4422 IDirect3DDevice8Impl_SetCursorPosition,
4423 IDirect3DDevice8Impl_ShowCursor,
4424 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4425 IDirect3DDevice8Impl_Reset,
4426 IDirect3DDevice8Impl_Present,
4427 IDirect3DDevice8Impl_GetBackBuffer,
4428 IDirect3DDevice8Impl_GetRasterStatus,
4429 IDirect3DDevice8Impl_SetGammaRamp,
4430 IDirect3DDevice8Impl_GetGammaRamp,
4431 IDirect3DDevice8Impl_CreateTexture,
4432 IDirect3DDevice8Impl_CreateVolumeTexture,
4433 IDirect3DDevice8Impl_CreateCubeTexture,
4434 IDirect3DDevice8Impl_CreateVertexBuffer,
4435 IDirect3DDevice8Impl_CreateIndexBuffer,
4436 IDirect3DDevice8Impl_CreateRenderTarget,
4437 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4438 IDirect3DDevice8Impl_CreateImageSurface,
4439 IDirect3DDevice8Impl_CopyRects,
4440 IDirect3DDevice8Impl_UpdateTexture,
4441 IDirect3DDevice8Impl_GetFrontBuffer,
4442 IDirect3DDevice8Impl_SetRenderTarget,
4443 IDirect3DDevice8Impl_GetRenderTarget,
4444 IDirect3DDevice8Impl_GetDepthStencilSurface,
4445 IDirect3DDevice8Impl_BeginScene,
4446 IDirect3DDevice8Impl_EndScene,
4447 IDirect3DDevice8Impl_Clear,
4448 IDirect3DDevice8Impl_SetTransform,
4449 IDirect3DDevice8Impl_GetTransform,
4450 IDirect3DDevice8Impl_MultiplyTransform,
4451 IDirect3DDevice8Impl_SetViewport,
4452 IDirect3DDevice8Impl_GetViewport,
4453 IDirect3DDevice8Impl_SetMaterial,
4454 IDirect3DDevice8Impl_GetMaterial,
4455 IDirect3DDevice8Impl_SetLight,
4456 IDirect3DDevice8Impl_GetLight,
4457 IDirect3DDevice8Impl_LightEnable,
4458 IDirect3DDevice8Impl_GetLightEnable,
4459 IDirect3DDevice8Impl_SetClipPlane,
4460 IDirect3DDevice8Impl_GetClipPlane,
4461 IDirect3DDevice8Impl_SetRenderState,
4462 IDirect3DDevice8Impl_GetRenderState,
4463 IDirect3DDevice8Impl_BeginStateBlock,
4464 IDirect3DDevice8Impl_EndStateBlock,
4465 IDirect3DDevice8Impl_ApplyStateBlock,
4466 IDirect3DDevice8Impl_CaptureStateBlock,
4467 IDirect3DDevice8Impl_DeleteStateBlock,
4468 IDirect3DDevice8Impl_CreateStateBlock,
4469 IDirect3DDevice8Impl_SetClipStatus,
4470 IDirect3DDevice8Impl_GetClipStatus,
4471 IDirect3DDevice8Impl_GetTexture,
4472 IDirect3DDevice8Impl_SetTexture,
4473 IDirect3DDevice8Impl_GetTextureStageState,
4474 IDirect3DDevice8Impl_SetTextureStageState,
4475 IDirect3DDevice8Impl_ValidateDevice,
4476 IDirect3DDevice8Impl_GetInfo,
4477 IDirect3DDevice8Impl_SetPaletteEntries,
4478 IDirect3DDevice8Impl_GetPaletteEntries,
4479 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4480 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4481 IDirect3DDevice8Impl_DrawPrimitive,
4482 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4483 IDirect3DDevice8Impl_DrawPrimitiveUP,
4484 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4485 IDirect3DDevice8Impl_ProcessVertices,
4486 IDirect3DDevice8Impl_CreateVertexShader,
4487 IDirect3DDevice8Impl_SetVertexShader,
4488 IDirect3DDevice8Impl_GetVertexShader,
4489 IDirect3DDevice8Impl_DeleteVertexShader,
4490 IDirect3DDevice8Impl_SetVertexShaderConstant,
4491 IDirect3DDevice8Impl_GetVertexShaderConstant,
4492 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4493 IDirect3DDevice8Impl_GetVertexShaderFunction,
4494 IDirect3DDevice8Impl_SetStreamSource,
4495 IDirect3DDevice8Impl_GetStreamSource,
4496 IDirect3DDevice8Impl_SetIndices,
4497 IDirect3DDevice8Impl_GetIndices,
4498 IDirect3DDevice8Impl_CreatePixelShader,
4499 IDirect3DDevice8Impl_SetPixelShader,
4500 IDirect3DDevice8Impl_GetPixelShader,
4501 IDirect3DDevice8Impl_DeletePixelShader,
4502 IDirect3DDevice8Impl_SetPixelShaderConstant,
4503 IDirect3DDevice8Impl_GetPixelShaderConstant,
4504 IDirect3DDevice8Impl_GetPixelShaderFunction,
4505 IDirect3DDevice8Impl_DrawRectPatch,
4506 IDirect3DDevice8Impl_DrawTriPatch,
4507 IDirect3DDevice8Impl_DeletePatch
4510 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4512 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4513 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4518 if (This->glCtx != This->render_ctx) {
4519 glXDestroyContext(This->display, This->render_ctx);
4520 This->render_ctx = This->glCtx;
4523 if (This->win != This->drawable) {
4524 glXDestroyPbuffer(This->display, This->drawable);
4525 This->drawable = This->win;
4534 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4535 IDirect3DSurface8* RenderSurface,
4536 IDirect3DSurface8* StencilSurface) {
4538 HRESULT ret = D3DERR_INVALIDCALL;
4540 * Currently only active for GLX >= 1.3
4541 * for others versions we'll have to use GLXPixmaps
4543 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4544 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4545 * so only check OpenGL version
4547 #if defined(GL_VERSION_1_3)
4548 GLXFBConfig* cfgs = NULL;
4552 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4553 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4554 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4555 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4556 IDirect3DSurface8Impl* tmp;
4558 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4560 #define PUSH1(att) attribs[nAttribs++] = (att);
4561 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4563 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4564 PUSH2(GLX_X_RENDERABLE, TRUE);
4565 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4567 switch (BackBufferFormat) {
4570 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4571 PUSH2(GLX_BUFFER_SIZE, 8);
4572 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4576 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4577 PUSH2(GLX_RED_SIZE, 3);
4578 PUSH2(GLX_GREEN_SIZE, 3);
4579 PUSH2(GLX_BLUE_SIZE, 2);
4582 case D3DFMT_A1R5G5B5:
4583 PUSH2(GLX_ALPHA_SIZE, 1);
4584 case D3DFMT_X1R5G5B5:
4585 PUSH2(GLX_RED_SIZE, 5);
4586 PUSH2(GLX_GREEN_SIZE, 5);
4587 PUSH2(GLX_BLUE_SIZE, 5);
4591 PUSH2(GLX_RED_SIZE, 5);
4592 PUSH2(GLX_GREEN_SIZE, 6);
4593 PUSH2(GLX_BLUE_SIZE, 5);
4596 case D3DFMT_A4R4G4B4:
4597 PUSH2(GLX_ALPHA_SIZE, 4);
4598 case D3DFMT_X4R4G4B4:
4599 PUSH2(GLX_RED_SIZE, 4);
4600 PUSH2(GLX_GREEN_SIZE, 4);
4601 PUSH2(GLX_BLUE_SIZE, 4);
4604 case D3DFMT_A8R8G8B8:
4605 PUSH2(GLX_ALPHA_SIZE, 8);
4607 case D3DFMT_X8R8G8B8:
4608 PUSH2(GLX_RED_SIZE, 8);
4609 PUSH2(GLX_GREEN_SIZE, 8);
4610 PUSH2(GLX_BLUE_SIZE, 8);
4617 switch (StencilBufferFormat) {
4618 case D3DFMT_D16_LOCKABLE:
4620 PUSH2(GLX_DEPTH_SIZE, 16);
4624 PUSH2(GLX_DEPTH_SIZE, 15);
4628 PUSH2(GLX_DEPTH_SIZE, 24);
4631 case D3DFMT_D24X4S4:
4632 PUSH2(GLX_DEPTH_SIZE, 24);
4633 PUSH2(GLX_STENCIL_SIZE, 4);
4637 PUSH2(GLX_DEPTH_SIZE, 24);
4638 PUSH2(GLX_STENCIL_SIZE, 8);
4642 PUSH2(GLX_DEPTH_SIZE, 32);
4653 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4657 for (i = 0; i < nCfgs; ++i) {
4658 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4662 if (NULL != This->renderTarget) {
4663 /*GLenum prev_read; */
4665 vcheckGLcall("glFlush");
4668 /** very very useful debug code */
4669 glXSwapBuffers(This->display, This->drawable);
4670 printf("Hit Enter to get next frame ...\n");
4675 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4676 vcheckGLcall("glIntegerv");
4677 glReadBuffer(GL_BACK);
4678 vcheckGLcall("glReadBuffer");
4681 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4683 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4686 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4688 This->renderTarget->myDesc.Height - j - 1,
4689 This->renderTarget->myDesc.Width,
4691 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4692 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4693 This->renderTarget->allocatedMemory + j * pitch);
4694 vcheckGLcall("glReadPixels");
4697 glReadBuffer(prev_read);
4698 vcheckGLcall("glReadBuffer");
4702 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4703 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4705 PUSH2(GLX_PBUFFER_WIDTH, Width);
4706 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4708 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4710 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4711 if (NULL == This->render_ctx) {
4712 ERR("cannot create glxContext\n");
4716 glXSwapBuffers(This->display, This->drawable);
4717 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4718 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4720 checkGLcall("glXMakeContextCurrent");
4723 tmp = This->renderTarget;
4724 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4725 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4726 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4728 tmp = This->stencilBufferTarget;
4729 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4730 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4731 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4735 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4736 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4737 /* Force updating the cull mode */
4738 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4739 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4740 /* Force updating projection matrix */
4741 This->last_was_rhw = FALSE;
4742 This->proj_valid = FALSE;
4748 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));