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 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(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 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
301 return ++(This->ref);
304 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
305 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
306 ULONG ref = --This->ref;
307 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
309 IDirect3DDevice8Impl_CleanRender(iface);
310 IDirect3D8_Release((LPDIRECT3D8) This->direct3d8);
311 IWineD3DDevice_Release(This->WineD3DDevice);
312 HeapFree(GetProcessHeap(), 0, This);
317 /* IDirect3DDevice Interface follow: */
318 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
319 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
320 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
324 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
325 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
326 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
328 * pretend we have 32MB of any type of memory queried.
330 return (1024*1024*32);
333 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
334 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
335 FIXME("(%p) : stub\n", This);
338 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
339 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
340 TRACE("(%p) : returning %p\n", This, This->direct3d8);
343 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
345 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
348 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
349 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
350 FIXME("(%p) : stub, calling idirect3d for now\n", This);
351 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
354 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
359 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
360 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
361 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
362 pMode->RefreshRate = 85; /*FIXME: How to identify? */
364 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
365 bpp = GetDeviceCaps(hdc, BITSPIXEL);
369 case 8: pMode->Format = D3DFMT_R8G8B8; break;
370 case 16: pMode->Format = D3DFMT_R5G6B5; break;
371 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
372 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
374 FIXME("Unrecognized display mode format\n");
375 pMode->Format = D3DFMT_UNKNOWN;
378 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
379 pMode->Format, debug_d3dformat(pMode->Format));
382 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
383 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
384 TRACE("(%p) copying to %p\n", This, pParameters);
385 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
388 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
389 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
390 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
391 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
393 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
394 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
395 return D3DERR_INVALIDCALL;
397 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
398 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
399 return D3DERR_INVALIDCALL;
402 This->xHotSpot = XHotSpot;
403 This->yHotSpot = YHotSpot;
406 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
407 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
408 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
409 This->xScreenSpace = XScreenSpace;
410 This->yScreenSpace = YScreenSpace;
413 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
414 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
415 TRACE("(%p) : visible(%d)\n", This, bShow);
416 This->bCursorVisible = bShow;
419 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
420 IDirect3DSwapChain8Impl* object;
421 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
422 FIXME("(%p) : stub\n", This);
424 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
425 if (NULL == object) {
426 return D3DERR_OUTOFVIDEOMEMORY;
428 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
431 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
432 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
433 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
435 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
436 (pPresentationParameters->BackBufferHeight == 0))) {
439 GetClientRect(This->win_handle, &Rect);
441 if (pPresentationParameters->BackBufferWidth == 0) {
442 pPresentationParameters->BackBufferWidth = Rect.right;
443 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
445 if (pPresentationParameters->BackBufferHeight == 0) {
446 pPresentationParameters->BackBufferHeight = Rect.bottom;
447 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
451 /* Save the presentation parms now filled in correctly */
452 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
454 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
455 pPresentationParameters->BackBufferWidth,
456 pPresentationParameters->BackBufferHeight,
457 pPresentationParameters->BackBufferFormat,
458 pPresentationParameters->MultiSampleType,
460 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
462 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
463 pPresentationParameters->BackBufferWidth,
464 pPresentationParameters->BackBufferHeight,
465 pPresentationParameters->BackBufferFormat,
466 pPresentationParameters->MultiSampleType,
468 (LPDIRECT3DSURFACE8*) &object->backBuffer);
470 if (pPresentationParameters->EnableAutoDepthStencil) {
471 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
472 pPresentationParameters->BackBufferWidth,
473 pPresentationParameters->BackBufferHeight,
474 pPresentationParameters->AutoDepthStencilFormat,
476 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
478 object->depthStencilBuffer = NULL;
481 *pSwapChain = (IDirect3DSwapChain8*) object;
484 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
485 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
486 FIXME("(%p) : stub\n", This);
489 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
490 CONST RECT* pSourceRect, CONST RECT* pDestRect,
491 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
492 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
493 TRACE("(%p) : complete stub!\n", This);
497 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
500 glXSwapBuffers(This->display, This->drawable);
501 /* Don't call checkGLcall, as glGetError is not applicable here */
502 TRACE("glXSwapBuffers called, Starting new frame\n");
505 if (TRACE_ON(d3d_fps))
507 static long prev_time, frames;
509 DWORD time = GetTickCount();
511 /* every 1.5 seconds */
512 if (time - prev_time > 1500) {
513 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
519 #if defined(FRAME_DEBUGGING)
521 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
524 FIXME("Enabling D3D Trace\n");
525 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
526 #if defined(SHOW_FRAME_MAKEUP)
527 FIXME("Singe Frame snapshots Starting\n");
528 isDumpingFrames = TRUE;
529 glClear(GL_COLOR_BUFFER_BIT);
532 #if defined(SINGLE_FRAME_DEBUGGING)
534 #if defined(SHOW_FRAME_MAKEUP)
535 FIXME("Singe Frame snapshots Finishing\n");
536 isDumpingFrames = FALSE;
538 FIXME("Singe Frame trace complete\n");
539 DeleteFileA("C:\\D3DTRACE");
540 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
546 #if defined(SHOW_FRAME_MAKEUP)
547 FIXME("Singe Frame snapshots Finishing\n");
548 isDumpingFrames = FALSE;
550 FIXME("Disabling D3D Trace\n");
551 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
558 /* Although this is not strictly required, a simple demo showed this does occur
559 on (at least non-debug) d3d */
560 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
561 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
566 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
567 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
568 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
569 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
571 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
572 FIXME("Only one backBuffer currently supported\n");
573 return D3DERR_INVALIDCALL;
576 /* Note inc ref on returned surface */
577 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
581 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
582 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
583 FIXME("(%p) : stub\n", This);
586 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
588 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
590 FIXME("(%p) : pRamp@%p\n", This, pRamp);
591 hDC = GetDC(This->win_handle);
592 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
593 ReleaseDC(This->win_handle, hDC);
596 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
598 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
600 FIXME("(%p) : pRamp@%p\n", This, pRamp);
601 hDC = GetDC(This->win_handle);
602 GetDeviceGammaRamp(hDC, pRamp);
603 ReleaseDC(This->win_handle, hDC);
606 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
607 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
608 IDirect3DTexture8Impl *object;
613 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
615 /* Allocate the storage for the device */
616 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);
617 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
618 object->lpVtbl = &Direct3DTexture8_Vtbl;
619 object->Device = This;
620 object->ResourceType = D3DRTYPE_TEXTURE;
622 object->width = Width;
623 object->height = Height;
624 object->levels = Levels;
625 object->usage = Usage;
626 object->format = Format;
628 /* Calculate levels for mip mapping */
633 while (tmpW > 1 && tmpH > 1) {
634 tmpW = max(1, tmpW / 2);
635 tmpH = max(1, tmpH / 2);
638 TRACE("Calculated levels = %d\n", object->levels);
641 /* Generate all the surfaces */
644 for (i = 0; i < object->levels; i++)
646 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
647 object->surfaces[i]->Container = (IUnknown*) object;
648 object->surfaces[i]->myDesc.Usage = Usage;
649 object->surfaces[i]->myDesc.Pool = Pool;
651 * As written in msdn in IDirect3DTexture8::LockRect
652 * Textures created in D3DPOOL_DEFAULT are not lockable.
654 if (D3DPOOL_DEFAULT == Pool) {
655 object->surfaces[i]->lockable = FALSE;
658 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
659 tmpW = max(1, tmpW / 2);
660 tmpH = max(1, tmpH / 2);
663 *ppTexture = (LPDIRECT3DTEXTURE8) object;
664 TRACE("(%p) : Created texture %p\n", This, object);
667 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
668 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
669 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
671 IDirect3DVolumeTexture8Impl *object;
677 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
679 /* Allocate the storage for it */
680 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));
681 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
682 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
683 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
684 object->Device = This;
687 object->width = Width;
688 object->height = Height;
689 object->depth = Depth;
690 object->levels = Levels;
691 object->usage = Usage;
692 object->format = Format;
694 /* Calculate levels for mip mapping */
700 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
701 tmpW = max(1, tmpW / 2);
702 tmpH = max(1, tmpH / 2);
703 tmpD = max(1, tmpD / 2);
706 TRACE("Calculated levels = %d\n", object->levels);
709 /* Generate all the surfaces */
714 for (i = 0; i < object->levels; i++)
716 IDirect3DVolume8Impl* volume;
718 /* Create the volume - No entry point for this seperately?? */
719 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
720 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
722 volume->lpVtbl = &Direct3DVolume8_Vtbl;
723 volume->Device = This;
724 volume->ResourceType = D3DRTYPE_VOLUME;
725 volume->Container = (IUnknown*) object;
728 volume->myDesc.Width = Width;
729 volume->myDesc.Height = Height;
730 volume->myDesc.Depth = Depth;
731 volume->myDesc.Format = Format;
732 volume->myDesc.Type = D3DRTYPE_VOLUME;
733 volume->myDesc.Pool = Pool;
734 volume->myDesc.Usage = Usage;
735 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
736 /* Note: Volume textures cannot be dxtn, hence no need to check here */
737 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
738 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
740 volume->lockable = TRUE;
741 volume->locked = FALSE;
742 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
743 volume->Dirty = FALSE;
744 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
746 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
747 This, Width, Height, Depth, Format, debug_d3dformat(Format),
748 volume, volume->allocatedMemory, volume->myDesc.Size);
750 tmpW = max(1, tmpW / 2);
751 tmpH = max(1, tmpH / 2);
752 tmpD = max(1, tmpD / 2);
755 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
756 TRACE("(%p) : Created volume texture %p\n", This, object);
759 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
760 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
762 IDirect3DCubeTexture8Impl *object;
763 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
767 /* Allocate the storage for it */
768 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));
769 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
770 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
772 object->Device = This;
773 object->ResourceType = D3DRTYPE_CUBETEXTURE;
775 object->edgeLength = EdgeLength;
776 object->levels = Levels;
777 object->usage = Usage;
778 object->format = Format;
780 /* Calculate levels for mip mapping */
785 tmpW = max(1, tmpW / 2);
788 TRACE("Calculated levels = %d\n", object->levels);
791 /* Generate all the surfaces */
793 for (i = 0; i < object->levels; i++) {
794 /* Create the 6 faces */
795 for (j = 0; j < 6; j++) {
796 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
797 object->surfaces[j][i]->Container = (IUnknown*) object;
798 object->surfaces[j][i]->myDesc.Usage = Usage;
799 object->surfaces[j][i]->myDesc.Pool = Pool;
801 * As written in msdn in IDirect3DCubeTexture8::LockRect
802 * Textures created in D3DPOOL_DEFAULT are not lockable.
804 if (D3DPOOL_DEFAULT == Pool) {
805 object->surfaces[j][i]->lockable = FALSE;
808 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
810 tmpW = max(1, tmpW / 2);
813 TRACE("(%p) : Iface@%p\n", This, object);
814 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
817 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
818 IDirect3DVertexBuffer8Impl *object;
820 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
822 /* Allocate the storage for the device */
823 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
824 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
825 object->Device = This;
826 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
828 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
829 object->currentDesc.Usage = Usage;
830 object->currentDesc.Pool = Pool;
831 object->currentDesc.FVF = FVF;
832 object->currentDesc.Size = Size;
834 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
836 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
840 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
841 IDirect3DIndexBuffer8Impl *object;
843 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
844 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
846 /* Allocate the storage for the device */
847 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
848 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
849 object->Device = This;
851 object->ResourceType = D3DRTYPE_INDEXBUFFER;
853 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
854 object->currentDesc.Usage = Usage;
855 object->currentDesc.Pool = Pool;
856 object->currentDesc.Format = Format;
857 object->currentDesc.Size = Length;
859 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
861 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
863 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
867 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
868 IDirect3DSurface8Impl *object;
869 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
871 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
872 if (NULL == object) {
874 return D3DERR_OUTOFVIDEOMEMORY;
876 *ppSurface = (LPDIRECT3DSURFACE8) object;
877 object->lpVtbl = &Direct3DSurface8_Vtbl;
878 object->Device = This;
879 object->ResourceType = D3DRTYPE_SURFACE;
880 object->Container = (IUnknown*) This;
883 object->myDesc.Width = Width;
884 object->myDesc.Height = Height;
885 object->myDesc.Format = Format;
886 object->myDesc.Type = D3DRTYPE_SURFACE;
887 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
888 object->myDesc.Pool = D3DPOOL_DEFAULT;
889 object->myDesc.MultiSampleType = MultiSample;
890 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
891 if (Format == D3DFMT_DXT1) {
892 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
894 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
896 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
897 object->lockable = Lockable;
898 object->locked = FALSE;
899 memset(&object->lockedRect, 0, sizeof(RECT));
900 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
902 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);
905 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
906 IDirect3DSurface8Impl *object;
908 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
910 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
911 if (NULL == object) {
913 return D3DERR_OUTOFVIDEOMEMORY;
915 *ppSurface = (LPDIRECT3DSURFACE8) object;
916 object->lpVtbl = &Direct3DSurface8_Vtbl;
917 object->Device = This;
918 object->ResourceType = D3DRTYPE_SURFACE;
919 object->Container = (IUnknown*) This;
922 object->myDesc.Width = Width;
923 object->myDesc.Height = Height;
924 object->myDesc.Format = Format;
925 object->myDesc.Type = D3DRTYPE_SURFACE;
926 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
927 object->myDesc.Pool = D3DPOOL_DEFAULT;
928 object->myDesc.MultiSampleType = MultiSample;
929 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
930 if (Format == D3DFMT_DXT1) {
931 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
933 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
935 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
936 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
937 object->locked = FALSE;
938 memset(&object->lockedRect, 0, sizeof(RECT));
939 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
941 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);
944 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
945 IDirect3DSurface8Impl *object;
947 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
949 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
950 *ppSurface = (LPDIRECT3DSURFACE8) object;
951 object->lpVtbl = &Direct3DSurface8_Vtbl;
952 object->Device = This;
953 object->ResourceType = D3DRTYPE_SURFACE;
954 object->Container = (IUnknown*) This;
957 object->myDesc.Width = Width;
958 object->myDesc.Height = Height;
959 object->myDesc.Format = Format;
960 object->myDesc.Type = D3DRTYPE_SURFACE;
961 object->myDesc.Usage = 0;
962 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
963 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
964 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
965 it is based around 4x4 pixel blocks it requires padding, so allocate enough
967 if (Format == D3DFMT_DXT1) {
968 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
969 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
970 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
971 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
973 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
975 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
976 object->lockable = TRUE;
977 object->locked = FALSE;
978 memset(&object->lockedRect, 0, sizeof(RECT));
979 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
981 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);
984 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
985 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
986 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
989 IDirect3DBaseTexture8* texture = NULL;
992 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
993 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
995 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
996 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
997 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
999 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1000 a sample and doesn't seem to break anything as far as I can tell */
1001 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1002 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1003 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1004 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1005 rc = D3DERR_INVALIDCALL;
1007 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1008 TRACE("Converting dest to same format as source, since dest was unknown\n");
1009 dst->myDesc.Format = src->myDesc.Format;
1011 /* Convert container as well */
1012 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1013 if (SUCCEEDED(rc) && NULL != texture) {
1014 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1015 /** Releasing texture after GetContainer */
1016 IDirect3DBaseTexture8_Release(texture);
1021 /* Quick if complete copy ... */
1022 if (SUCCEEDED(rc)) {
1023 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1025 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1027 D3DLOCKED_RECT lrSrc;
1028 D3DLOCKED_RECT lrDst;
1029 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1030 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1031 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1033 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1035 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1036 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1037 TRACE("Unlocked src and dst\n");
1041 FIXME("Wanted to copy all surfaces but size not compatible\n");
1042 rc = D3DERR_INVALIDCALL;
1048 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1050 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1053 /* Copy rect by rect */
1054 for (i = 0; i < cRects; i++) {
1055 CONST RECT* r = &pSourceRectsArray[i];
1056 CONST POINT* p = &pDestPointsArray[i];
1059 D3DLOCKED_RECT lrSrc;
1060 D3DLOCKED_RECT lrDst;
1063 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1064 if (src->myDesc.Format == D3DFMT_DXT1) {
1065 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1067 copyperline = ((r->right - r->left) * bytesPerPixel);
1069 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1070 dest_rect.left = p->x;
1071 dest_rect.top = p->y;
1072 dest_rect.right = p->x + (r->right - r->left);
1073 dest_rect.bottom= p->y + (r->bottom - r->top);
1074 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1075 TRACE("Locked src and dst\n");
1077 /* Find where to start */
1078 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1079 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1081 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1082 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1083 TRACE("Unlocked src and dst\n");
1086 FIXME("Wanted to copy partial surfaces not implemented\n");
1087 rc = D3DERR_INVALIDCALL;
1094 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1095 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1096 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1097 D3DRESOURCETYPE srcType;
1098 D3DRESOURCETYPE dstType;
1100 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1101 TRACE("(%p) : first try\n", This);
1103 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1104 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1106 if (srcType != dstType) {
1107 return D3DERR_INVALIDCALL;
1109 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1110 return D3DERR_INVALIDCALL;
1112 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1113 return D3DERR_INVALIDCALL;
1115 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1116 /** Only copy Dirty textures */
1117 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1118 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1119 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1122 for (i = skipLevels; i < srcLevelCnt; ++i) {
1126 case D3DRTYPE_TEXTURE:
1128 IDirect3DSurface8* srcSur = NULL;
1129 IDirect3DSurface8* dstSur = NULL;
1130 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1131 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1133 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1134 about dst with less levels than the source?) */
1135 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1137 IDirect3DSurface8Impl_Release(srcSur);
1138 IDirect3DSurface8Impl_Release(dstSur);
1141 case D3DRTYPE_VOLUMETEXTURE:
1143 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1146 case D3DRTYPE_CUBETEXTURE:
1148 IDirect3DSurface8* srcSur = NULL;
1149 IDirect3DSurface8* dstSur = NULL;
1150 for (j = 0; j < 5; ++j) {
1151 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1152 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1153 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1154 IDirect3DSurface8Impl_Release(srcSur);
1155 IDirect3DSurface8Impl_Release(dstSur);
1163 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1168 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1170 D3DLOCKED_RECT lockedRect;
1175 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1177 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1179 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1180 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1181 return D3DERR_INVALIDCALL;
1184 wantedRect.left = 0;
1186 wantedRect.right = This->PresentParms.BackBufferWidth;
1187 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1189 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1191 ERR("(%p) : cannot lock surface\n", This);
1192 return D3DERR_INVALIDCALL;
1198 vcheckGLcall("glFlush");
1199 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1200 vcheckGLcall("glIntegerv");
1201 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1202 vcheckGLcall("glIntegerv");
1204 glReadBuffer(GL_FRONT);
1205 vcheckGLcall("glReadBuffer");
1206 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1207 vcheckGLcall("glPixelStorei");
1211 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1212 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1213 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1214 vcheckGLcall("glReadPixels");
1217 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1218 vcheckGLcall("glPixelStorei");
1219 glReadBuffer(prev_read);
1220 vcheckGLcall("glReadBuffer");
1224 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1227 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1228 HRESULT hr = D3D_OK;
1229 D3DVIEWPORT8 viewport;
1231 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1233 /* If pRenderTarget == NULL, it seems to default to back buffer */
1234 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1236 /* For ease of code later on, handle a null depth as leave alone
1237 - Have not tested real d3d for this case but doing this avoids
1238 numerous null pointer checks */
1239 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1241 /* If we are trying to set what we already have, don't bother */
1242 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1243 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1245 /* Otherwise, set the render target up */
1246 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1247 IDirect3DDevice8Impl_CleanRender(iface);
1248 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1251 if (SUCCEEDED(hr)) {
1252 /* Finally, reset the viewport as the MSDN states. */
1253 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1254 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1257 viewport.MaxZ = 1.0f;
1258 viewport.MinZ = 0.0f;
1259 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1265 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1266 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1268 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1270 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1271 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1276 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1277 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1279 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1281 /* Note inc ref on returned surface */
1282 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1283 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1288 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1289 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1290 TRACE("(%p) : stub\n", This);
1294 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1295 IDirect3DBaseTexture8* cont = NULL;
1297 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1298 TRACE("(%p)\n", This);
1303 checkGLcall("glFlush");
1305 #if 0 /* Useful for debugging sometimes! */
1306 printf("Hit Enter ...\n");
1310 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1313 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1314 vcheckGLcall("glIntegerv");
1315 glReadBuffer(GL_FRONT);
1316 vcheckGLcall("glReadBuffer");
1319 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1321 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1324 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1326 This->renderTarget->myDesc.Height - j - 1,
1327 This->renderTarget->myDesc.Width,
1329 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1330 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1331 This->renderTarget->allocatedMemory + j * pitch);
1332 vcheckGLcall("glReadPixels");
1335 glReadBuffer(prev_read);
1336 vcheckGLcall("glReadBuffer");
1339 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1340 if (SUCCEEDED(hr) && NULL != cont) {
1341 /** always dirtify for now. we must find a better way to see that surface have been modified */
1342 This->renderTarget->inPBuffer = TRUE;
1343 This->renderTarget->inTexture = FALSE;
1344 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1345 IDirect3DBaseTexture8_PreLoad(cont);
1346 This->renderTarget->inPBuffer = FALSE;
1347 IDirect3DBaseTexture8Impl_Release(cont);
1355 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1356 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1358 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1359 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1360 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1361 GLbitfield glMask = 0;
1362 GLboolean old_ztest;
1363 GLfloat old_z_clear_value;
1364 GLint old_stencil_clear_value;
1365 GLfloat old_color_clear_value[4];
1367 CONST D3DRECT* curRect;
1369 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1370 Count, pRects, Flags, Z, Stencil);
1373 glEnable(GL_SCISSOR_TEST);
1374 checkGLcall("glEnable GL_SCISSOR_TEST");
1375 if (Count > 0 && pRects) {
1381 /* Only set the values up once, as they are not changing */
1382 if (Flags & D3DCLEAR_STENCIL) {
1383 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1384 glClearStencil(Stencil);
1385 checkGLcall("glClearStencil");
1386 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1387 glStencilMask(0xFFFFFFFF);
1390 if (Flags & D3DCLEAR_ZBUFFER) {
1391 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1392 glDepthMask(GL_TRUE);
1393 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1395 checkGLcall("glClearDepth");
1396 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1399 if (Flags & D3DCLEAR_TARGET) {
1400 TRACE("Clearing screen with glClear to color %lx\n", Color);
1401 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1402 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1403 ((Color >> 8) & 0xFF) / 255.0f,
1404 ((Color >> 0) & 0xFF) / 255.0f,
1405 ((Color >> 24) & 0xFF) / 255.0f);
1406 checkGLcall("glClearColor");
1408 /* Clear ALL colors! */
1409 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1410 glMask = glMask | GL_COLOR_BUFFER_BIT;
1413 /* Now process each rect in turn */
1414 for (i = 0; i < Count || i == 0; i++) {
1417 /* Note gl uses lower left, width/height */
1418 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1419 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1420 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1421 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1422 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1423 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1424 checkGLcall("glScissor");
1426 glScissor(This->StateBlock->viewport.X,
1427 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1428 This->StateBlock->viewport.Width,
1429 This->StateBlock->viewport.Height);
1430 checkGLcall("glScissor");
1433 /* Clear the selected rectangle (or full screen) */
1435 checkGLcall("glClear");
1437 /* Step to the next rectangle */
1438 if (curRect) curRect = curRect + sizeof(D3DRECT);
1441 /* Restore the old values (why..?) */
1442 if (Flags & D3DCLEAR_STENCIL) {
1443 glClearStencil(old_stencil_clear_value);
1444 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1446 if (Flags & D3DCLEAR_ZBUFFER) {
1447 glDepthMask(old_ztest);
1448 glClearDepth(old_z_clear_value);
1450 if (Flags & D3DCLEAR_TARGET) {
1451 glClearColor(old_color_clear_value[0],
1452 old_color_clear_value[1],
1453 old_color_clear_value[2],
1454 old_color_clear_value[3]);
1455 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1456 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1457 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1458 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1461 glDisable(GL_SCISSOR_TEST);
1462 checkGLcall("glDisable");
1467 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1468 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1471 /* Most of this routine, comments included copied from ddraw tree initially: */
1472 TRACE("(%p) : State=%d\n", This, d3dts);
1474 /* Handle recording of state blocks */
1475 if (This->isRecordingState) {
1476 TRACE("Recording... not performing anything\n");
1477 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1478 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1479 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1484 * if the new matrix is the same as the current one,
1485 * we cut off any further processing. this seems to be a reasonable
1486 * optimization because as was noticed, some apps (warcraft3 for example)
1487 * tend towards setting the same matrix repeatedly for some dumb reason.
1489 * From here on we assume that the new matrix is different, wherever it matters
1492 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1493 TRACE("The app is setting the same matrix over again\n");
1496 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1500 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1501 where ViewMat = Camera space, WorldMat = world space.
1503 In OpenGL, camera and world space is combined into GL_MODELVIEW
1504 matrix. The Projection matrix stay projection matrix.
1507 /* Capture the times we can just ignore the change */
1508 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1509 This->modelview_valid = FALSE;
1512 } else if (d3dts == D3DTS_PROJECTION) {
1513 This->proj_valid = FALSE;
1516 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1517 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1518 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1522 /* Chances are we really are going to have to change a matrix */
1525 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1526 if (d3dts < GL_LIMITS(textures)) {
1527 int tex = d3dts - D3DTS_TEXTURE0;
1528 #if defined(GL_VERSION_1_3)
1529 glActiveTexture(GL_TEXTURE0 + tex);
1530 checkGLcall("glActiveTexture");
1532 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1533 checkGLcall("glActiveTextureARB");
1535 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1538 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1540 PLIGHTINFOEL *lightChain = NULL;
1541 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1542 This->modelview_valid = FALSE;
1543 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1544 glMatrixMode(GL_MODELVIEW);
1545 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1547 glLoadMatrixf((float *)lpmatrix);
1548 checkGLcall("glLoadMatrixf(...)");
1550 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1551 * NOTE: We have to reset the positions even if the light/plane is not currently
1552 * enabled, since the call to enable it will not reset the position.
1553 * NOTE2: Apparently texture transforms do NOT need reapplying
1557 lightChain = This->StateBlock->lights;
1558 while (lightChain && lightChain->glIndex != -1) {
1559 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1560 checkGLcall("glLightfv posn");
1561 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1562 checkGLcall("glLightfv dirn");
1563 lightChain = lightChain->next;
1565 /* Reset Clipping Planes if clipping is enabled */
1566 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1567 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1568 checkGLcall("glClipPlane");
1572 } else { /* What was requested!?? */
1573 WARN("invalid matrix specified: %i\n", d3dts);
1577 /* Release lock, all done */
1582 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1583 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1584 TRACE("(%p) : for State %d\n", This, State);
1585 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1589 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1590 D3DMATRIX *mat = NULL;
1593 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1594 but works regardless of recording being on.
1595 If this is found to be wrong, change to StateBlock. */
1596 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1597 TRACE("(%p) : For state %u\n", This, State);
1599 if (State < HIGHEST_TRANSFORMSTATE)
1601 mat = &This->UpdateStateBlock->transforms[State];
1603 FIXME("Unhandled transform state!!\n");
1606 /* Copied from ddraw code: */
1607 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);
1608 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);
1609 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);
1610 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);
1612 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);
1613 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);
1614 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);
1615 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);
1617 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);
1618 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);
1619 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);
1620 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);
1622 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);
1623 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);
1624 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);
1625 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);
1627 /* Apply change via set transform - will reapply to eg. lights this way */
1628 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1631 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1632 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1634 TRACE("(%p)\n", This);
1635 This->UpdateStateBlock->Changed.viewport = TRUE;
1636 This->UpdateStateBlock->Set.viewport = TRUE;
1637 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1639 /* Handle recording of state blocks */
1640 if (This->isRecordingState) {
1641 TRACE("Recording... not performing anything\n");
1647 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1648 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1650 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1651 checkGLcall("glDepthRange");
1652 /* Note: GL requires lower left, DirectX supplies upper left */
1653 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1654 pViewport->Width, pViewport->Height);
1655 checkGLcall("glViewport");
1662 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1663 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1664 TRACE("(%p)\n", This);
1665 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1669 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1670 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1672 This->UpdateStateBlock->Changed.material = TRUE;
1673 This->UpdateStateBlock->Set.material = TRUE;
1674 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1676 /* Handle recording of state blocks */
1677 if (This->isRecordingState) {
1678 TRACE("Recording... not performing anything\n");
1683 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1684 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1685 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1686 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1687 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1689 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1690 checkGLcall("glMaterialfv");
1691 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1692 checkGLcall("glMaterialfv");
1694 /* Only change material color if specular is enabled, otherwise it is set to black */
1695 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1696 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1697 checkGLcall("glMaterialfv");
1699 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1700 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1701 checkGLcall("glMaterialfv");
1703 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1704 checkGLcall("glMaterialfv");
1705 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1706 checkGLcall("glMaterialf");
1711 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1712 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1713 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1714 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1715 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1716 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1717 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1718 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1722 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1723 you can reference any indexes you want as long as that number max are enabled are any
1724 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1725 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1726 but when recording, just build a chain pretty much of commands to be replayed. */
1728 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1730 PLIGHTINFOEL *object, *temp;
1732 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1733 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1735 /* If recording state block, just add to end of lights chain */
1736 if (This->isRecordingState) {
1737 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1738 if (NULL == object) {
1739 return D3DERR_OUTOFVIDEOMEMORY;
1741 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1742 object->OriginalIndex = Index;
1743 object->glIndex = -1;
1744 object->changed = TRUE;
1746 /* Add to the END of the chain of lights changes to be replayed */
1747 if (This->UpdateStateBlock->lights == NULL) {
1748 This->UpdateStateBlock->lights = object;
1750 temp = This->UpdateStateBlock->lights;
1751 while (temp->next != NULL) temp=temp->next;
1752 temp->next = object;
1754 TRACE("Recording... not performing anything more\n");
1758 /* Ok, not recording any longer so do real work */
1759 object = This->StateBlock->lights;
1760 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1762 /* If we didn't find it in the list of lights, time to add it */
1763 if (object == NULL) {
1764 PLIGHTINFOEL *insertAt,*prevPos;
1766 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1767 if (NULL == object) {
1768 return D3DERR_OUTOFVIDEOMEMORY;
1770 object->OriginalIndex = Index;
1771 object->glIndex = -1;
1773 /* Add it to the front of list with the idea that lights will be changed as needed
1774 BUT after any lights currently assigned GL indexes */
1775 insertAt = This->StateBlock->lights;
1777 while (insertAt != NULL && insertAt->glIndex != -1) {
1779 insertAt = insertAt->next;
1782 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1783 This->StateBlock->lights = object;
1784 } else if (insertAt == NULL) { /* End of list */
1785 prevPos->next = object;
1786 object->prev = prevPos;
1787 } else { /* Middle of chain */
1788 if (prevPos == NULL) {
1789 This->StateBlock->lights = object;
1791 prevPos->next = object;
1793 object->prev = prevPos;
1794 object->next = insertAt;
1795 insertAt->prev = object;
1799 /* Initialze the object */
1800 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,
1801 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1802 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1803 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1804 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1805 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1806 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1808 /* Save away the information */
1809 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1811 switch (pLight->Type) {
1812 case D3DLIGHT_POINT:
1814 object->lightPosn[0] = pLight->Position.x;
1815 object->lightPosn[1] = pLight->Position.y;
1816 object->lightPosn[2] = pLight->Position.z;
1817 object->lightPosn[3] = 1.0f;
1818 object->cutoff = 180.0f;
1822 case D3DLIGHT_DIRECTIONAL:
1824 object->lightPosn[0] = -pLight->Direction.x;
1825 object->lightPosn[1] = -pLight->Direction.y;
1826 object->lightPosn[2] = -pLight->Direction.z;
1827 object->lightPosn[3] = 0.0;
1828 object->exponent = 0.0f;
1829 object->cutoff = 180.0f;
1834 object->lightPosn[0] = pLight->Position.x;
1835 object->lightPosn[1] = pLight->Position.y;
1836 object->lightPosn[2] = pLight->Position.z;
1837 object->lightPosn[3] = 1.0;
1840 object->lightDirn[0] = pLight->Direction.x;
1841 object->lightDirn[1] = pLight->Direction.y;
1842 object->lightDirn[2] = pLight->Direction.z;
1843 object->lightDirn[3] = 1.0;
1846 * opengl-ish and d3d-ish spot lights use too different models for the
1847 * light "intensity" as a function of the angle towards the main light direction,
1848 * so we only can approximate very roughly.
1849 * however spot lights are rather rarely used in games (if ever used at all).
1850 * furthermore if still used, probably nobody pays attention to such details.
1852 if (pLight->Falloff == 0) {
1855 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1857 if (rho < 0.0001) rho = 0.0001f;
1858 object->exponent = -0.3/log(cos(rho/2));
1859 object->cutoff = pLight->Phi*90/M_PI;
1865 FIXME("Unrecognized light type %d\n", pLight->Type);
1868 /* Update the live definitions if the light is currently assigned a glIndex */
1869 if (object->glIndex != -1) {
1870 setup_light(iface, object->glIndex, object);
1874 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1875 PLIGHTINFOEL *lightInfo = NULL;
1876 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1877 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1879 /* Locate the light in the live lights */
1880 lightInfo = This->StateBlock->lights;
1881 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1883 if (lightInfo == NULL) {
1884 TRACE("Light information requested but light not defined\n");
1885 return D3DERR_INVALIDCALL;
1888 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1891 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1892 PLIGHTINFOEL *lightInfo = NULL;
1893 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1894 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1896 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1897 if (This->isRecordingState) {
1898 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1899 if (NULL == lightInfo) {
1900 return D3DERR_OUTOFVIDEOMEMORY;
1902 lightInfo->OriginalIndex = Index;
1903 lightInfo->glIndex = -1;
1904 lightInfo->enabledChanged = TRUE;
1906 /* Add to the END of the chain of lights changes to be replayed */
1907 if (This->UpdateStateBlock->lights == NULL) {
1908 This->UpdateStateBlock->lights = lightInfo;
1910 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1911 while (temp->next != NULL) temp=temp->next;
1912 temp->next = lightInfo;
1914 TRACE("Recording... not performing anything more\n");
1918 /* Not recording... So, locate the light in the live lights */
1919 lightInfo = This->StateBlock->lights;
1920 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1922 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1923 if (lightInfo == NULL) {
1924 D3DLIGHT8 lightParms;
1925 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1926 wait until someone confirms it seems to work! */
1927 TRACE("Light enabled requested but light not defined, so defining one!\n");
1928 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1929 lightParms.Diffuse.r = 1.0;
1930 lightParms.Diffuse.g = 1.0;
1931 lightParms.Diffuse.b = 1.0;
1932 lightParms.Diffuse.a = 0.0;
1933 lightParms.Specular.r = 0.0;
1934 lightParms.Specular.g = 0.0;
1935 lightParms.Specular.b = 0.0;
1936 lightParms.Specular.a = 0.0;
1937 lightParms.Ambient.r = 0.0;
1938 lightParms.Ambient.g = 0.0;
1939 lightParms.Ambient.b = 0.0;
1940 lightParms.Ambient.a = 0.0;
1941 lightParms.Position.x = 0.0;
1942 lightParms.Position.y = 0.0;
1943 lightParms.Position.z = 0.0;
1944 lightParms.Direction.x = 0.0;
1945 lightParms.Direction.y = 0.0;
1946 lightParms.Direction.z = 1.0;
1947 lightParms.Range = 0.0;
1948 lightParms.Falloff = 0.0;
1949 lightParms.Attenuation0 = 0.0;
1950 lightParms.Attenuation1 = 0.0;
1951 lightParms.Attenuation2 = 0.0;
1952 lightParms.Theta = 0.0;
1953 lightParms.Phi = 0.0;
1954 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1956 /* Search for it again! Should be fairly quick as near head of list */
1957 lightInfo = This->StateBlock->lights;
1958 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1959 if (lightInfo == NULL) {
1960 FIXME("Adding default lights has failed dismally\n");
1961 return D3DERR_INVALIDCALL;
1965 /* OK, we now have a light... */
1966 if (Enable == FALSE) {
1968 /* If we are disabling it, check it was enabled, and
1969 still only do something if it has assigned a glIndex (which it should have!) */
1970 if ((lightInfo->lightEnabled == TRUE) && (lightInfo->glIndex != -1)) {
1971 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1973 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1974 checkGLcall("glDisable GL_LIGHT0+Index");
1977 TRACE("Nothing to do as light was not enabled\n");
1979 lightInfo->lightEnabled = FALSE;
1982 /* We are enabling it. If it is enabled, its really simple */
1983 if (lightInfo->lightEnabled == TRUE) {
1985 TRACE("Nothing to do as light was enabled\n");
1987 /* If it already has a glIndex, its still simple */
1988 } else if (lightInfo->glIndex != -1) {
1989 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1990 lightInfo->lightEnabled = TRUE;
1992 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1993 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1996 /* Otherwise got to find space - lights are ordered gl indexes first */
1998 PLIGHTINFOEL *bsf = NULL;
1999 PLIGHTINFOEL *pos = This->StateBlock->lights;
2000 PLIGHTINFOEL *prev = NULL;
2004 /* Try to minimize changes as much as possible */
2005 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2007 /* Try to remember which index can be replaced if necessary */
2008 if (bsf==NULL && pos->lightEnabled == FALSE) {
2009 /* Found a light we can replace, save as best replacement */
2013 /* Step to next space */
2019 /* If we have too many active lights, fail the call */
2020 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2021 FIXME("Program requests too many concurrent lights\n");
2022 return D3DERR_INVALIDCALL;
2024 /* If we have allocated all lights, but not all are enabled,
2025 reuse one which is not enabled */
2026 } else if (Index == This->maxConcurrentLights) {
2027 /* use bsf - Simply swap the new light and the BSF one */
2028 PLIGHTINFOEL *bsfNext = bsf->next;
2029 PLIGHTINFOEL *bsfPrev = bsf->prev;
2032 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2033 if (bsf->prev != NULL) {
2034 bsf->prev->next = lightInfo;
2036 This->StateBlock->lights = lightInfo;
2039 /* If not side by side, lots of chains to update */
2040 if (bsf->next != lightInfo) {
2041 lightInfo->prev->next = bsf;
2042 bsf->next->prev = lightInfo;
2043 bsf->next = lightInfo->next;
2044 bsf->prev = lightInfo->prev;
2045 lightInfo->next = bsfNext;
2046 lightInfo->prev = bsfPrev;
2050 bsf->prev = lightInfo;
2051 bsf->next = lightInfo->next;
2052 lightInfo->next = bsf;
2053 lightInfo->prev = bsfPrev;
2058 glIndex = bsf->glIndex;
2060 lightInfo->glIndex = glIndex;
2061 lightInfo->lightEnabled = TRUE;
2063 /* Finally set up the light in gl itself */
2064 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2066 setup_light(iface, glIndex, lightInfo);
2067 glEnable(GL_LIGHT0 + glIndex);
2068 checkGLcall("glEnable GL_LIGHT0 new setup");
2071 /* If we reached the end of the allocated lights, with space in the
2072 gl lights, setup a new light */
2073 } else if (pos->glIndex == -1) {
2075 /* We reached the end of the allocated gl lights, so already
2076 know the index of the next one! */
2078 lightInfo->glIndex = glIndex;
2079 lightInfo->lightEnabled = TRUE;
2081 /* In an ideal world, its already in the right place */
2082 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2083 /* No need to move it */
2085 /* Remove this light from the list */
2086 lightInfo->prev->next = lightInfo->next;
2087 if (lightInfo->next != NULL) {
2088 lightInfo->next->prev = lightInfo->prev;
2091 /* Add in at appropriate place (inbetween prev and pos) */
2092 lightInfo->prev = prev;
2093 lightInfo->next = pos;
2095 This->StateBlock->lights = lightInfo;
2097 prev->next = lightInfo;
2100 pos->prev = lightInfo;
2104 /* Finally set up the light in gl itself */
2105 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2107 setup_light(iface, glIndex, lightInfo);
2108 glEnable(GL_LIGHT0 + glIndex);
2109 checkGLcall("glEnable GL_LIGHT0 new setup");
2117 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2119 PLIGHTINFOEL *lightInfo = NULL;
2120 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2121 TRACE("(%p) : for idx(%ld)\n", This, Index);
2123 /* Locate the light in the live lights */
2124 lightInfo = This->StateBlock->lights;
2125 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2127 if (lightInfo == NULL) {
2128 TRACE("Light enabled state requested but light not defined\n");
2129 return D3DERR_INVALIDCALL;
2131 *pEnable = lightInfo->lightEnabled;
2134 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2135 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2136 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2138 /* Validate Index */
2139 if (Index >= GL_LIMITS(clipplanes)) {
2140 TRACE("Application has requested clipplane this device doesn't support\n");
2141 return D3DERR_INVALIDCALL;
2144 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2145 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2146 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2147 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2148 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2149 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2151 /* Handle recording of state blocks */
2152 if (This->isRecordingState) {
2153 TRACE("Recording... not performing anything\n");
2161 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2162 glMatrixMode(GL_MODELVIEW);
2164 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2166 TRACE("Clipplane [%f,%f,%f,%f]\n",
2167 This->UpdateStateBlock->clipplane[Index][0],
2168 This->UpdateStateBlock->clipplane[Index][1],
2169 This->UpdateStateBlock->clipplane[Index][2],
2170 This->UpdateStateBlock->clipplane[Index][3]);
2171 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2172 checkGLcall("glClipPlane");
2180 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2181 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2182 TRACE("(%p) : for idx %ld\n", This, Index);
2184 /* Validate Index */
2185 if (Index >= GL_LIMITS(clipplanes)) {
2186 TRACE("Application has requested clipplane this device doesn't support\n");
2187 return D3DERR_INVALIDCALL;
2190 pPlane[0] = This->StateBlock->clipplane[Index][0];
2191 pPlane[1] = This->StateBlock->clipplane[Index][1];
2192 pPlane[2] = This->StateBlock->clipplane[Index][2];
2193 pPlane[3] = This->StateBlock->clipplane[Index][3];
2196 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2201 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2202 DWORD OldValue = This->StateBlock->renderstate[State];
2204 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2205 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2206 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2207 This->UpdateStateBlock->renderstate[State] = Value;
2209 /* Handle recording of state blocks */
2210 if (This->isRecordingState) {
2211 TRACE("Recording... not performing anything\n");
2218 case D3DRS_FILLMODE :
2219 switch ((D3DFILLMODE) Value) {
2220 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2221 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2222 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2224 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2226 checkGLcall("glPolygonMode (fillmode)");
2229 case D3DRS_LIGHTING :
2231 glEnable(GL_LIGHTING);
2232 checkGLcall("glEnable GL_LIGHTING");
2234 glDisable(GL_LIGHTING);
2235 checkGLcall("glDisable GL_LIGHTING");
2239 case D3DRS_ZENABLE :
2240 switch ((D3DZBUFFERTYPE) Value) {
2242 glDisable(GL_DEPTH_TEST);
2243 checkGLcall("glDisable GL_DEPTH_TEST");
2246 glEnable(GL_DEPTH_TEST);
2247 checkGLcall("glEnable GL_DEPTH_TEST");
2250 glEnable(GL_DEPTH_TEST);
2251 checkGLcall("glEnable GL_DEPTH_TEST");
2252 FIXME("W buffer is not well handled\n");
2255 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2259 case D3DRS_CULLMODE :
2261 /* If we are culling "back faces with clockwise vertices" then
2262 set front faces to be counter clockwise and enable culling
2264 switch ((D3DCULL) Value) {
2266 glDisable(GL_CULL_FACE);
2267 checkGLcall("glDisable GL_CULL_FACE");
2270 glEnable(GL_CULL_FACE);
2271 checkGLcall("glEnable GL_CULL_FACE");
2272 if (This->renderUpsideDown) {
2274 checkGLcall("glFrontFace GL_CW");
2276 glFrontFace(GL_CCW);
2277 checkGLcall("glFrontFace GL_CCW");
2279 glCullFace(GL_BACK);
2282 glEnable(GL_CULL_FACE);
2283 checkGLcall("glEnable GL_CULL_FACE");
2284 if (This->renderUpsideDown) {
2285 glFrontFace(GL_CCW);
2286 checkGLcall("glFrontFace GL_CCW");
2289 checkGLcall("glFrontFace GL_CW");
2291 glCullFace(GL_BACK);
2294 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2298 case D3DRS_SHADEMODE :
2299 switch ((D3DSHADEMODE) Value) {
2301 glShadeModel(GL_FLAT);
2302 checkGLcall("glShadeModel");
2304 case D3DSHADE_GOURAUD:
2305 glShadeModel(GL_SMOOTH);
2306 checkGLcall("glShadeModel");
2308 case D3DSHADE_PHONG:
2309 FIXME("D3DSHADE_PHONG isn't supported?\n");
2312 return D3DERR_INVALIDCALL;
2314 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2318 case D3DRS_DITHERENABLE :
2320 glEnable(GL_DITHER);
2321 checkGLcall("glEnable GL_DITHER");
2323 glDisable(GL_DITHER);
2324 checkGLcall("glDisable GL_DITHER");
2328 case D3DRS_ZWRITEENABLE :
2331 checkGLcall("glDepthMask");
2334 checkGLcall("glDepthMask");
2340 int glParm = GL_LESS;
2342 switch ((D3DCMPFUNC) Value) {
2343 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2344 case D3DCMP_LESS: glParm=GL_LESS; break;
2345 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2346 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2347 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2348 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2349 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2350 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2352 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2354 glDepthFunc(glParm);
2355 checkGLcall("glDepthFunc");
2359 case D3DRS_AMBIENT :
2362 D3DCOLORTOGLFLOAT4(Value, col);
2363 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2364 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2365 checkGLcall("glLightModel for MODEL_AMBIENT");
2370 case D3DRS_ALPHABLENDENABLE :
2373 checkGLcall("glEnable GL_BLEND");
2375 glDisable(GL_BLEND);
2376 checkGLcall("glDisable GL_BLEND");
2380 case D3DRS_SRCBLEND :
2381 case D3DRS_DESTBLEND :
2383 int newVal = GL_ZERO;
2385 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2386 case D3DBLEND_ONE : newVal = GL_ONE; break;
2387 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2388 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2389 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2390 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2391 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2392 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2393 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2394 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2395 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2397 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2398 This->srcBlend = newVal;
2399 This->dstBlend = newVal;
2402 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2403 This->srcBlend = newVal;
2404 This->dstBlend = newVal;
2407 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2410 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2411 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2412 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2413 glBlendFunc(This->srcBlend, This->dstBlend);
2415 checkGLcall("glBlendFunc");
2419 case D3DRS_ALPHATESTENABLE :
2421 glEnable(GL_ALPHA_TEST);
2422 checkGLcall("glEnable GL_ALPHA_TEST");
2424 glDisable(GL_ALPHA_TEST);
2425 checkGLcall("glDisable GL_ALPHA_TEST");
2429 case D3DRS_ALPHAFUNC :
2431 int glParm = GL_LESS;
2432 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2434 switch ((D3DCMPFUNC) Value) {
2435 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2436 case D3DCMP_LESS: glParm = GL_LESS; break;
2437 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2438 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2439 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2440 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2441 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2442 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2444 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2446 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2447 glAlphaFunc(glParm, ref);
2448 This->alphafunc = glParm;
2449 checkGLcall("glAlphaFunc");
2453 case D3DRS_ALPHAREF :
2455 int glParm = This->alphafunc;
2458 ref = ((float) Value) / 255.0f;
2459 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2460 glAlphaFunc(glParm, ref);
2461 checkGLcall("glAlphaFunc");
2465 case D3DRS_CLIPPLANEENABLE :
2466 case D3DRS_CLIPPING :
2468 /* Ensure we only do the changed clip planes */
2469 DWORD enable = 0xFFFFFFFF;
2470 DWORD disable = 0x00000000;
2472 /* If enabling / disabling all */
2473 if (State == D3DRS_CLIPPING) {
2475 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2478 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2482 enable = Value & ~OldValue;
2483 disable = ~Value & OldValue;
2486 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2487 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2488 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2489 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2490 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2491 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2493 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2494 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2495 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2496 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2497 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2498 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2500 /** update clipping status */
2502 This->StateBlock->clip_status.ClipUnion = 0;
2503 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2505 This->StateBlock->clip_status.ClipUnion = 0;
2506 This->StateBlock->clip_status.ClipIntersection = 0;
2511 case D3DRS_BLENDOP :
2513 int glParm = GL_FUNC_ADD;
2515 switch ((D3DBLENDOP) Value) {
2516 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2517 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2518 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2519 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2520 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2522 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2524 TRACE("glBlendEquation(%x)\n", glParm);
2525 glBlendEquation(glParm);
2526 checkGLcall("glBlendEquation");
2530 case D3DRS_TEXTUREFACTOR :
2534 /* Note the texture color applies to all textures whereas
2535 GL_TEXTURE_ENV_COLOR applies to active only */
2537 D3DCOLORTOGLFLOAT4(Value, col);
2538 /* Set the default alpha blend color */
2539 glBlendColor(col[0], col[1], col[2], col[3]);
2540 checkGLcall("glBlendColor");
2542 /* And now the default texture color as well */
2543 for (i = 0; i < GL_LIMITS(textures); i++) {
2545 /* Note the D3DRS value applies to all textures, but GL has one
2546 per texture, so apply it now ready to be used! */
2547 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2548 #if defined(GL_VERSION_1_3)
2549 glActiveTexture(GL_TEXTURE0 + i);
2551 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2553 checkGLcall("Activate texture.. to update const color");
2555 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2558 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2559 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2564 case D3DRS_SPECULARENABLE :
2566 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2567 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2568 specular color. This is wrong:
2569 Separate specular color means the specular colour is maintained separately, whereas
2570 single color means it is merged in. However in both cases they are being used to
2572 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2573 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2577 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2578 checkGLcall("glMaterialfv");
2579 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2580 glEnable(GL_COLOR_SUM_EXT);
2582 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2584 checkGLcall("glEnable(GL_COLOR_SUM)");
2586 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2588 /* for the case of enabled lighting: */
2589 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2590 checkGLcall("glMaterialfv");
2592 /* for the case of disabled lighting: */
2593 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2594 glDisable(GL_COLOR_SUM_EXT);
2596 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2598 checkGLcall("glDisable(GL_COLOR_SUM)");
2603 case D3DRS_STENCILENABLE :
2605 glEnable(GL_STENCIL_TEST);
2606 checkGLcall("glEnable GL_STENCIL_TEST");
2608 glDisable(GL_STENCIL_TEST);
2609 checkGLcall("glDisable GL_STENCIL_TEST");
2613 case D3DRS_STENCILFUNC :
2615 int glParm = GL_ALWAYS;
2616 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2617 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2619 switch ((D3DCMPFUNC) Value) {
2620 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2621 case D3DCMP_LESS: glParm=GL_LESS; break;
2622 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2623 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2624 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2625 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2626 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2627 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2629 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2631 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2632 This->stencilfunc = glParm;
2633 glStencilFunc(glParm, ref, mask);
2634 checkGLcall("glStencilFunc");
2638 case D3DRS_STENCILREF :
2640 int glParm = This->stencilfunc;
2642 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2645 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2646 glStencilFunc(glParm, ref, mask);
2647 checkGLcall("glStencilFunc");
2651 case D3DRS_STENCILMASK :
2653 int glParm = This->stencilfunc;
2654 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2655 GLuint mask = Value;
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_STENCILFAIL :
2669 fail = StencilOp(Value);
2670 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2671 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2672 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2673 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2675 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2676 glStencilOp(fail, zfail, zpass);
2677 checkGLcall("glStencilOp(fail, zfail, zpass);");
2680 case D3DRS_STENCILZFAIL :
2686 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2687 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2688 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2689 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2690 zfail = StencilOp(Value);
2692 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2693 glStencilOp(fail, zfail, zpass);
2694 checkGLcall("glStencilOp(fail, zfail, zpass);");
2697 case D3DRS_STENCILPASS :
2703 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2704 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2705 zpass = StencilOp(Value);
2706 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2707 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2709 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2710 glStencilOp(fail, zfail, zpass);
2711 checkGLcall("glStencilOp(fail, zfail, zpass);");
2715 case D3DRS_STENCILWRITEMASK :
2717 glStencilMask(Value);
2718 TRACE("glStencilMask(%lu)\n", Value);
2719 checkGLcall("glStencilMask");
2723 case D3DRS_FOGENABLE :
2725 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2727 checkGLcall("glEnable GL_FOG");
2730 checkGLcall("glDisable GL_FOG");
2735 case D3DRS_RANGEFOGENABLE :
2738 TRACE("Enabled RANGEFOG");
2740 TRACE("Disabled RANGEFOG");
2745 case D3DRS_FOGCOLOR :
2748 D3DCOLORTOGLFLOAT4(Value, col);
2749 /* Set the default alpha blend color */
2750 glFogfv(GL_FOG_COLOR, &col[0]);
2751 checkGLcall("glFog GL_FOG_COLOR");
2755 case D3DRS_FOGTABLEMODE :
2757 glHint(GL_FOG_HINT, GL_NICEST);
2759 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2760 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2761 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2762 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2764 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2766 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2767 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2772 case D3DRS_FOGVERTEXMODE :
2774 glHint(GL_FOG_HINT, GL_FASTEST);
2776 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2777 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2778 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2779 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2781 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2783 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2784 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2789 case D3DRS_FOGSTART :
2792 glFogfv(GL_FOG_START, &tmpvalue.f);
2793 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2794 TRACE("Fog Start == %f\n", tmpvalue.f);
2801 glFogfv(GL_FOG_END, &tmpvalue.f);
2802 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2803 TRACE("Fog End == %f\n", tmpvalue.f);
2807 case D3DRS_FOGDENSITY :
2810 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2811 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2815 case D3DRS_VERTEXBLEND :
2817 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2818 TRACE("Vertex Blending state to %ld\n", Value);
2822 case D3DRS_TWEENFACTOR :
2825 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2826 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2830 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2832 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2836 case D3DRS_COLORVERTEX :
2837 case D3DRS_DIFFUSEMATERIALSOURCE :
2838 case D3DRS_SPECULARMATERIALSOURCE :
2839 case D3DRS_AMBIENTMATERIALSOURCE :
2840 case D3DRS_EMISSIVEMATERIALSOURCE :
2842 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2844 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2845 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2846 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2847 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2848 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2849 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2851 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2852 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2853 Parm = GL_AMBIENT_AND_DIFFUSE;
2857 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2859 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2861 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2868 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2870 This->tracking_color = NEEDS_TRACKING;
2871 This->tracking_parm = Parm;
2875 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2880 case D3DRS_LINEPATTERN :
2886 tmppattern.d = Value;
2888 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2890 if (tmppattern.lp.wRepeatFactor) {
2891 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2892 checkGLcall("glLineStipple(repeat, linepattern)");
2893 glEnable(GL_LINE_STIPPLE);
2894 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2896 glDisable(GL_LINE_STIPPLE);
2897 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2906 TRACE("ZBias value %f\n", tmpvalue.f);
2907 glPolygonOffset(0, -tmpvalue.f);
2908 checkGLcall("glPolygonOffset(0, -Value)");
2909 glEnable(GL_POLYGON_OFFSET_FILL);
2910 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2911 glEnable(GL_POLYGON_OFFSET_LINE);
2912 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2913 glEnable(GL_POLYGON_OFFSET_POINT);
2914 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2916 glDisable(GL_POLYGON_OFFSET_FILL);
2917 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2918 glDisable(GL_POLYGON_OFFSET_LINE);
2919 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2920 glDisable(GL_POLYGON_OFFSET_POINT);
2921 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2926 case D3DRS_NORMALIZENORMALS :
2928 glEnable(GL_NORMALIZE);
2929 checkGLcall("glEnable(GL_NORMALIZE);");
2931 glDisable(GL_NORMALIZE);
2932 checkGLcall("glDisable(GL_NORMALIZE);");
2936 case D3DRS_POINTSIZE :
2938 TRACE("Set point size to %f\n", tmpvalue.f);
2939 glPointSize(tmpvalue.f);
2940 checkGLcall("glPointSize(...);");
2943 case D3DRS_POINTSIZE_MIN :
2944 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2946 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2947 checkGLcall("glPointParameterfEXT(...);");
2949 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2953 case D3DRS_POINTSIZE_MAX :
2954 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2956 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2957 checkGLcall("glPointParameterfEXT(...);");
2959 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2963 case D3DRS_POINTSCALE_A :
2964 case D3DRS_POINTSCALE_B :
2965 case D3DRS_POINTSCALE_C :
2966 case D3DRS_POINTSCALEENABLE :
2968 /* If enabled, supply the parameters, otherwise fall back to defaults */
2969 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2970 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2971 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2972 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2973 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2975 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2976 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2977 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2979 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2982 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2983 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2984 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2985 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2987 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2993 case D3DRS_COLORWRITEENABLE :
2995 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2996 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2997 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2998 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2999 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3000 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3001 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3002 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3003 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3004 checkGLcall("glColorMask(...)");
3008 case D3DRS_LOCALVIEWER :
3010 GLint state = (Value) ? 1 : 0;
3011 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3012 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3016 case D3DRS_LASTPIXEL :
3019 TRACE("Last Pixel Drawing Enabled\n");
3021 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3026 case D3DRS_SOFTWAREVERTEXPROCESSING :
3029 TRACE("Software Processing Enabled\n");
3031 TRACE("Software Processing Disabled\n");
3036 /** not supported */
3037 case D3DRS_ZVISIBLE :
3040 return D3DERR_INVALIDCALL;
3043 /* Unhandled yet...! */
3044 case D3DRS_EDGEANTIALIAS :
3053 case D3DRS_POINTSPRITEENABLE :
3054 case D3DRS_MULTISAMPLEANTIALIAS :
3055 case D3DRS_MULTISAMPLEMASK :
3056 case D3DRS_PATCHEDGESTYLE :
3057 case D3DRS_PATCHSEGMENTS :
3058 case D3DRS_DEBUGMONITORTOKEN :
3059 case D3DRS_POSITIONORDER :
3060 case D3DRS_NORMALORDER :
3061 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3062 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3065 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3072 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3073 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3074 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3075 *pValue = This->StateBlock->renderstate[State];
3078 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3079 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3081 TRACE("(%p)\n", This);
3083 return IDirect3DDeviceImpl_BeginStateBlock(This);
3085 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3086 IDirect3DStateBlockImpl* pSB;
3087 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3090 TRACE("(%p)\n", This);
3092 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3093 *pToken = (DWORD) pSB;
3097 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3098 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3099 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3101 TRACE("(%p)\n", This);
3103 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3106 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3107 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3108 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3110 TRACE("(%p)\n", This);
3112 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3114 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3115 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3116 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3118 TRACE("(%p)\n", This);
3120 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3123 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3124 IDirect3DStateBlockImpl* pSB;
3125 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3128 TRACE("(%p) : for type %d\n", This, Type);
3130 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3131 *pToken = (DWORD) pSB;
3135 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3136 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3137 FIXME("(%p) : stub\n", This);
3138 if (NULL == pClipStatus) {
3139 return D3DERR_INVALIDCALL;
3141 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3142 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3145 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3146 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3147 FIXME("(%p) : stub\n", This);
3148 if (NULL == pClipStatus) {
3149 return D3DERR_INVALIDCALL;
3151 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3152 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3155 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3156 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3157 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3158 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3160 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3163 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3165 IDirect3DBaseTexture8 *oldTxt;
3166 BOOL reapplyStates = TRUE;
3167 INT oldTextureDimensions = -1;
3168 DWORD reapplyFlags = 0;
3170 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3171 D3DRESOURCETYPE textureType;
3173 oldTxt = This->UpdateStateBlock->textures[Stage];
3174 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3176 /* Reject invalid texture units */
3177 if (Stage >= GL_LIMITS(textures)) {
3178 TRACE("Attempt to access invalid texture rejected\n");
3179 return D3DERR_INVALIDCALL;
3182 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3183 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3184 This->UpdateStateBlock->textures[Stage] = pTexture;
3186 /* Handle recording of state blocks */
3187 if (This->isRecordingState) {
3188 TRACE("Recording... not performing anything\n");
3192 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3195 /* Make appropriate texture active */
3196 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3197 #if defined(GL_VERSION_1_3)
3198 glActiveTexture(GL_TEXTURE0 + Stage);
3199 checkGLcall("glActiveTexture");
3201 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3202 checkGLcall("glActiveTextureARB");
3204 } else if (Stage>0) {
3205 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3208 /* Decrement the count of the previous texture */
3209 if (NULL != oldTxt) {
3210 IDirect3DBaseTexture8Impl_Release(oldTxt);
3213 if (NULL != pTexture) {
3214 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3216 /* Now setup the texture appropraitly */
3217 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3219 if (textureType == D3DRTYPE_TEXTURE) {
3220 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3221 TRACE("Skipping setting texture as old == new\n");
3222 reapplyStates = FALSE;
3224 /* Standard 2D texture */
3225 TRACE("Standard 2d texture\n");
3226 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3228 /* Load up the texture now */
3229 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3231 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3232 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3233 TRACE("Skipping setting texture as old == new\n");
3234 reapplyStates = FALSE;
3236 /* Standard 3D (volume) texture */
3237 TRACE("Standard 3d texture\n");
3238 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3240 /* Load up the texture now */
3241 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3243 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3244 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3245 TRACE("Skipping setting texture as old == new\n");
3246 reapplyStates = FALSE;
3248 /* Standard Cube texture */
3249 TRACE("Standard Cube texture\n");
3250 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3252 /* Load up the texture now */
3253 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3256 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3259 TRACE("Setting to no texture (ie default texture)\n");
3260 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3261 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3262 checkGLcall("glBindTexture");
3263 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3266 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3267 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3268 glDisable(oldTextureDimensions);
3269 checkGLcall("Disable oldTextureDimensions");
3270 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3271 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3272 checkGLcall("glEnable new texture dimensions");
3275 /* If Alpha arg1 is texture then handle the special case when there changes between a
3276 texture and no texture - See comments in set_tex_op */
3277 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3278 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3280 reapplyFlags |= REAPPLY_ALPHAOP;
3285 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3286 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3287 if (reapplyStates) {
3288 setupTextureStates(iface, Stage, reapplyFlags);
3296 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3297 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3298 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3299 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3303 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3304 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3310 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3312 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3314 /* Reject invalid texture units */
3315 if (Stage >= GL_LIMITS(textures)) {
3316 TRACE("Attempt to access invalid texture rejected\n");
3317 return D3DERR_INVALIDCALL;
3320 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3321 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3322 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3324 /* Handle recording of state blocks */
3325 if (This->isRecordingState) {
3326 TRACE("Recording... not performing anything\n");
3332 /* Make appropriate texture active */
3333 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3334 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3335 #if defined(GL_VERSION_1_3)
3336 glActiveTexture(GL_TEXTURE0 + Stage);
3337 vcheckGLcall("glActiveTexture");
3339 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3340 vcheckGLcall("glActiveTextureARB");
3342 } else if (Stage > 0) {
3343 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3348 case D3DTSS_MINFILTER :
3349 case D3DTSS_MIPFILTER :
3351 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3352 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3353 GLint realVal = GL_LINEAR;
3355 if (ValueMIN == D3DTEXF_NONE) {
3356 /* Doesn't really make sense - Windows just seems to disable
3357 mipmapping when this occurs */
3358 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3359 realVal = GL_LINEAR;
3360 } else if (ValueMIN == D3DTEXF_POINT) {
3362 if (ValueMIP == D3DTEXF_NONE) {
3363 realVal = GL_NEAREST;
3364 } else if (ValueMIP == D3DTEXF_POINT) {
3365 realVal = GL_NEAREST_MIPMAP_NEAREST;
3366 } else if (ValueMIP == D3DTEXF_LINEAR) {
3367 realVal = GL_NEAREST_MIPMAP_LINEAR;
3369 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3370 realVal = GL_NEAREST;
3372 } else if (ValueMIN == D3DTEXF_LINEAR) {
3374 if (ValueMIP == D3DTEXF_NONE) {
3375 realVal = GL_LINEAR;
3376 } else if (ValueMIP == D3DTEXF_POINT) {
3377 realVal = GL_LINEAR_MIPMAP_NEAREST;
3378 } else if (ValueMIP == D3DTEXF_LINEAR) {
3379 realVal = GL_LINEAR_MIPMAP_LINEAR;
3381 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3382 realVal = GL_LINEAR;
3384 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3385 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3386 if (ValueMIP == D3DTEXF_NONE) {
3387 realVal = GL_LINEAR_MIPMAP_LINEAR;
3388 } else if (ValueMIP == D3DTEXF_POINT) {
3389 realVal = GL_LINEAR_MIPMAP_NEAREST;
3390 } else if (ValueMIP == D3DTEXF_LINEAR) {
3391 realVal = GL_LINEAR_MIPMAP_LINEAR;
3393 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3394 realVal = GL_LINEAR;
3397 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3398 realVal = GL_LINEAR;
3401 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3402 realVal = GL_LINEAR_MIPMAP_LINEAR;
3405 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3406 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3407 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3409 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3411 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3412 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3413 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3414 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3415 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3420 case D3DTSS_MAGFILTER :
3422 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3423 GLint realVal = GL_NEAREST;
3425 if (ValueMAG == D3DTEXF_POINT) {
3426 realVal = GL_NEAREST;
3427 } else if (ValueMAG == D3DTEXF_LINEAR) {
3428 realVal = GL_LINEAR;
3429 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3430 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3431 realVal = GL_LINEAR;
3433 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3434 realVal = GL_NEAREST;
3437 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3438 realVal = GL_NEAREST;
3440 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3441 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3442 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3444 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3446 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3447 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3448 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3449 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3450 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3455 case D3DTSS_MAXMIPLEVEL :
3458 * Not really the same, but the more apprioprate than nothing
3460 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3461 GL_TEXTURE_BASE_LEVEL,
3462 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3463 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3467 case D3DTSS_MAXANISOTROPY :
3469 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3470 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3471 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3472 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3473 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3478 case D3DTSS_MIPMAPLODBIAS :
3480 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3482 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3483 GL_TEXTURE_LOD_BIAS_EXT,
3485 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3490 case D3DTSS_ALPHAOP :
3491 case D3DTSS_COLOROP :
3494 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3495 /* TODO: Disable by making this and all later levels disabled */
3496 glDisable(GL_TEXTURE_1D);
3497 checkGLcall("Disable GL_TEXTURE_1D");
3498 glDisable(GL_TEXTURE_2D);
3499 checkGLcall("Disable GL_TEXTURE_2D");
3500 glDisable(GL_TEXTURE_3D);
3501 checkGLcall("Disable GL_TEXTURE_3D");
3502 break; /* Don't bother setting the texture operations */
3504 /* Enable only the appropriate texture dimension */
3505 if (Type == D3DTSS_COLOROP) {
3506 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3507 glEnable(GL_TEXTURE_1D);
3508 checkGLcall("Enable GL_TEXTURE_1D");
3510 glDisable(GL_TEXTURE_1D);
3511 checkGLcall("Disable GL_TEXTURE_1D");
3513 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3514 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3515 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3516 checkGLcall("Enable GL_TEXTURE_2D");
3518 glEnable(GL_TEXTURE_2D);
3519 checkGLcall("Enable GL_TEXTURE_2D");
3522 glDisable(GL_TEXTURE_2D);
3523 checkGLcall("Disable GL_TEXTURE_2D");
3525 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3526 glEnable(GL_TEXTURE_3D);
3527 checkGLcall("Enable GL_TEXTURE_3D");
3529 glDisable(GL_TEXTURE_3D);
3530 checkGLcall("Disable GL_TEXTURE_3D");
3532 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3533 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3534 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3536 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3537 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3541 /* Drop through... (Except disable case) */
3542 case D3DTSS_COLORARG0 :
3543 case D3DTSS_COLORARG1 :
3544 case D3DTSS_COLORARG2 :
3545 case D3DTSS_ALPHAARG0 :
3546 case D3DTSS_ALPHAARG1 :
3547 case D3DTSS_ALPHAARG2 :
3549 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3550 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3552 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3553 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3554 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3555 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3557 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3558 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3559 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3560 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3566 case D3DTSS_ADDRESSU :
3567 case D3DTSS_ADDRESSV :
3568 case D3DTSS_ADDRESSW :
3570 GLint wrapParm = GL_REPEAT;
3573 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3574 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3575 case D3DTADDRESS_BORDER:
3577 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3578 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3580 /* FIXME: Not right, but better */
3581 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3582 wrapParm = GL_REPEAT;
3586 case D3DTADDRESS_MIRROR:
3588 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3589 wrapParm = GL_MIRRORED_REPEAT_ARB;
3591 /* Unsupported in OpenGL pre-1.4 */
3592 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3593 wrapParm = GL_REPEAT;
3597 case D3DTADDRESS_MIRRORONCE:
3599 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3600 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3602 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3603 wrapParm = GL_REPEAT;
3609 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3610 wrapParm = GL_REPEAT;
3614 case D3DTSS_ADDRESSU:
3615 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3616 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3617 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3619 case D3DTSS_ADDRESSV:
3620 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3621 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3622 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3624 case D3DTSS_ADDRESSW:
3625 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3626 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3627 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3630 break; /** stupic compilator */
3635 case D3DTSS_BORDERCOLOR :
3638 D3DCOLORTOGLFLOAT4(Value, col);
3639 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3640 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3641 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3645 case D3DTSS_TEXCOORDINDEX :
3647 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3649 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3650 one flag, you can still specify an index value, which the system uses to
3651 determine the texture wrapping mode.
3652 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3653 means use the vertex position (camera-space) as the input texture coordinates
3654 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3655 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3656 to the TEXCOORDINDEX value */
3659 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3661 switch (Value & 0xFFFF0000) {
3662 case D3DTSS_TCI_PASSTHRU:
3663 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3664 glDisable(GL_TEXTURE_GEN_S);
3665 glDisable(GL_TEXTURE_GEN_T);
3666 glDisable(GL_TEXTURE_GEN_R);
3667 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3670 case D3DTSS_TCI_CAMERASPACEPOSITION:
3671 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3672 as the input texture coordinates for this stage's texture transformation. This
3673 equates roughly to EYE_LINEAR */
3675 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3676 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3677 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3678 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3679 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3681 glMatrixMode(GL_MODELVIEW);
3684 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3685 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3686 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3687 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3690 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3691 glEnable(GL_TEXTURE_GEN_S);
3692 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3693 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3694 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3695 glEnable(GL_TEXTURE_GEN_T);
3696 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3697 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3698 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3699 glEnable(GL_TEXTURE_GEN_R);
3700 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3701 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3702 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3706 case D3DTSS_TCI_CAMERASPACENORMAL:
3708 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3709 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3710 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3711 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3712 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3713 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3715 glMatrixMode(GL_MODELVIEW);
3718 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3719 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3720 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3721 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3724 glEnable(GL_TEXTURE_GEN_S);
3725 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3726 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3727 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3728 glEnable(GL_TEXTURE_GEN_T);
3729 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3730 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3731 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3732 glEnable(GL_TEXTURE_GEN_R);
3733 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3734 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3735 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3740 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3742 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3743 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3744 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3745 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3746 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3747 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3749 glMatrixMode(GL_MODELVIEW);
3752 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3753 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3754 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3755 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3758 glEnable(GL_TEXTURE_GEN_S);
3759 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3760 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3761 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3762 glEnable(GL_TEXTURE_GEN_T);
3763 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3764 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3765 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3766 glEnable(GL_TEXTURE_GEN_R);
3767 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3768 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3769 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3774 /* Unhandled types: */
3777 /* ? disable GL_TEXTURE_GEN_n ? */
3778 glDisable(GL_TEXTURE_GEN_S);
3779 glDisable(GL_TEXTURE_GEN_T);
3780 glDisable(GL_TEXTURE_GEN_R);
3781 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3788 case D3DTSS_TEXTURETRANSFORMFLAGS :
3789 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3792 case D3DTSS_BUMPENVMAT00 :
3793 case D3DTSS_BUMPENVMAT01 :
3794 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3796 case D3DTSS_BUMPENVMAT10 :
3797 case D3DTSS_BUMPENVMAT11 :
3798 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3801 case D3DTSS_BUMPENVLSCALE :
3802 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3805 case D3DTSS_BUMPENVLOFFSET :
3806 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3809 case D3DTSS_RESULTARG :
3810 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3814 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3815 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3822 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3823 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3824 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3827 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3828 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3829 FIXME("(%p) : stub\n", This);
3832 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3833 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3834 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3835 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3836 if (PaletteNumber >= MAX_PALETTES) {
3837 return D3DERR_INVALIDCALL;
3839 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3842 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3843 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3844 if (PaletteNumber >= MAX_PALETTES) {
3845 return D3DERR_INVALIDCALL;
3847 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3848 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3849 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3852 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3853 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3854 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3855 if (PaletteNumber >= MAX_PALETTES) {
3856 return D3DERR_INVALIDCALL;
3858 This->currentPalette = PaletteNumber;
3860 #if defined(GL_EXT_paletted_texture)
3861 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3865 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3866 GL_RGBA, /* internal format */
3867 256, /* table size */
3868 GL_RGBA, /* table format */
3869 GL_UNSIGNED_BYTE, /* table type */
3870 This->palettes[PaletteNumber]);
3871 checkGLcall("glColorTableEXT");
3876 /* Delayed palette handling ... waiting for software emulation into preload code */
3881 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3882 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3883 *PaletteNumber = This->currentPalette;
3884 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3887 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3889 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3890 This->StateBlock->streamIsUP = FALSE;
3892 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3893 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3897 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3898 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3900 IDirect3DIndexBuffer8 *pIB;
3901 D3DINDEXBUFFER_DESC IdxBufDsc;
3903 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3904 pIB = This->StateBlock->pIndexData;
3905 This->StateBlock->streamIsUP = FALSE;
3907 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3908 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3909 minIndex, NumVertices, startIndex, primCount);
3911 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3912 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3918 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3923 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3924 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3926 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3927 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3929 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3931 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3932 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3933 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3934 This->StateBlock->streamIsUP = TRUE;
3935 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3936 This->StateBlock->stream_stride[0] = 0;
3937 This->StateBlock->stream_source[0] = NULL;
3939 /*stream zero settings set to null at end */
3942 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3943 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3944 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3945 UINT VertexStreamZeroStride) {
3947 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3948 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),
3949 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3951 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3952 if (IndexDataFormat == D3DFMT_INDEX16) {
3958 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3959 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3960 This->StateBlock->streamIsUP = TRUE;
3961 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3962 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3964 /*stream zero settings set to null at end */
3965 This->StateBlock->stream_source[0] = NULL;
3966 This->StateBlock->stream_stride[0] = 0;
3967 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3971 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3972 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3973 FIXME("(%p) : stub\n", This); return D3D_OK;
3975 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3976 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3977 IDirect3DVertexShaderImpl* object;
3978 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3982 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3983 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3984 return D3DERR_INVALIDCALL;
3986 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3987 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3988 return D3DERR_OUTOFVIDEOMEMORY;
3991 /** Create the Vertex Shader */
3992 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3993 /** TODO: check FAILED(res) */
3995 /** Create and Bind the Vertex Shader Declaration */
3996 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3997 /** TODO: check FAILED(res) */
3999 VertexShaders[i] = object;
4000 VertexShaderDeclarations[i] = attached_decl;
4001 *pHandle = VS_HIGHESTFIXEDFXF + i;
4002 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4006 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4007 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4009 This->UpdateStateBlock->VertexShader = Handle;
4010 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4011 This->UpdateStateBlock->Set.vertexShader = TRUE;
4013 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4014 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4015 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4016 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4017 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4018 } else { /* use a fvf, so desactivate the vshader decl */
4019 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4020 This->UpdateStateBlock->vertexShaderDecl = NULL;
4021 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4022 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4024 /* Handle recording of state blocks */
4025 if (This->isRecordingState) {
4026 TRACE("Recording... not performing anything\n");
4030 * TODO: merge HAL shaders context switching from prototype
4034 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4035 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4036 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4037 *pHandle = This->StateBlock->VertexShader;
4041 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4042 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4043 IDirect3DVertexShaderImpl* object;
4044 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4046 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4047 return D3DERR_INVALIDCALL;
4051 * Delete Vertex Shader
4053 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4054 if (NULL == object) {
4055 return D3DERR_INVALIDCALL;
4057 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4058 /* TODO: check validity of object */
4059 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4060 if (object->prgId != 0) {
4061 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4063 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4064 HeapFree(GetProcessHeap(), 0, (void *)object);
4065 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4068 * Delete Vertex Shader Declaration
4070 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4071 if (NULL == attached_decl) {
4072 return D3DERR_INVALIDCALL;
4074 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4075 /* TODO: check validity of object */
4076 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4077 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4078 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4083 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4084 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4086 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4087 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4088 return D3DERR_INVALIDCALL;
4090 if (NULL == pConstantData) {
4091 return D3DERR_INVALIDCALL;
4093 if (ConstantCount > 1) {
4094 FLOAT* f = (FLOAT*)pConstantData;
4096 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4097 for (i = 0; i < ConstantCount; ++i) {
4098 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4102 FLOAT* f = (FLOAT*) pConstantData;
4103 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4105 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4106 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4109 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4110 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4112 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4113 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4114 return D3DERR_INVALIDCALL;
4116 if (NULL == pConstantData) {
4117 return D3DERR_INVALIDCALL;
4119 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4122 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4123 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4124 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4126 attached_decl = VERTEX_SHADER_DECL(Handle);
4127 if (NULL == attached_decl) {
4128 return D3DERR_INVALIDCALL;
4130 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4132 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4133 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4134 IDirect3DVertexShaderImpl* object;
4136 object = VERTEX_SHADER(Handle);
4137 if (NULL == object) {
4138 return D3DERR_INVALIDCALL;
4140 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4143 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4144 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4145 IDirect3DIndexBuffer8 *oldIdxs;
4147 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4148 oldIdxs = This->StateBlock->pIndexData;
4150 This->UpdateStateBlock->Changed.Indices = TRUE;
4151 This->UpdateStateBlock->Set.Indices = TRUE;
4152 This->UpdateStateBlock->pIndexData = pIndexData;
4153 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4155 /* Handle recording of state blocks */
4156 if (This->isRecordingState) {
4157 TRACE("Recording... not performing anything\n");
4161 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4162 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4165 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4166 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4167 FIXME("(%p) : stub\n", This);
4169 *ppIndexData = This->StateBlock->pIndexData;
4170 /* up ref count on ppindexdata */
4171 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4172 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4176 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4177 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4178 IDirect3DPixelShaderImpl* object;
4182 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4183 if (NULL == pFunction || NULL == pHandle) {
4184 return D3DERR_INVALIDCALL;
4186 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4187 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4188 return D3DERR_OUTOFVIDEOMEMORY;
4191 /** Create the Pixel Shader */
4192 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4193 if (SUCCEEDED(res)) {
4194 PixelShaders[i] = object;
4195 *pHandle = VS_HIGHESTFIXEDFXF + i;
4198 *pHandle = 0xFFFFFFFF;
4202 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4203 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4205 This->UpdateStateBlock->PixelShader = Handle;
4206 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4207 This->UpdateStateBlock->Set.pixelShader = TRUE;
4209 /* Handle recording of state blocks */
4210 if (This->isRecordingState) {
4211 TRACE_(d3d_shader)("Recording... not performing anything\n");
4216 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4218 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4224 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4225 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4226 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4227 *pHandle = This->StateBlock->PixelShader;
4231 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4232 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4233 IDirect3DPixelShaderImpl* object;
4235 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4236 return D3DERR_INVALIDCALL;
4238 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4239 if (NULL == object) {
4240 return D3DERR_INVALIDCALL;
4242 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4243 /* TODO: check validity of object before free */
4244 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
4245 if (object->prgId != 0) {
4246 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4248 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4249 HeapFree(GetProcessHeap(), 0, (void *)object);
4250 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4255 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4256 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4258 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4259 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4260 return D3DERR_INVALIDCALL;
4262 if (NULL == pConstantData) {
4263 return D3DERR_INVALIDCALL;
4265 if (ConstantCount > 1) {
4266 FLOAT* f = (FLOAT*)pConstantData;
4268 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4269 for (i = 0; i < ConstantCount; ++i) {
4270 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4274 FLOAT* f = (FLOAT*) pConstantData;
4275 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4277 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4278 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4281 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4282 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4284 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4285 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4286 return D3DERR_INVALIDCALL;
4288 if (NULL == pConstantData) {
4289 return D3DERR_INVALIDCALL;
4291 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4294 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4295 IDirect3DPixelShaderImpl* object;
4297 object = PIXEL_SHADER(Handle);
4298 if (NULL == object) {
4299 return D3DERR_INVALIDCALL;
4301 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4303 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4304 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4305 FIXME("(%p) : stub\n", This); return D3D_OK;
4307 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4308 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4309 FIXME("(%p) : stub\n", This); return D3D_OK;
4311 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4312 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4313 FIXME("(%p) : stub\n", This); return D3D_OK;
4316 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4317 IDirect3DVertexBuffer8 *oldSrc;
4318 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4320 oldSrc = This->StateBlock->stream_source[StreamNumber];
4321 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4323 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4324 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4325 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4326 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4328 /* Handle recording of state blocks */
4329 if (This->isRecordingState) {
4330 TRACE("Recording... not performing anything\n");
4334 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4335 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4338 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4339 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4340 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4341 *pStream = This->StateBlock->stream_source[StreamNumber];
4342 *pStride = This->StateBlock->stream_stride[StreamNumber];
4343 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4348 IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4350 IDirect3DDevice8Impl_QueryInterface,
4351 IDirect3DDevice8Impl_AddRef,
4352 IDirect3DDevice8Impl_Release,
4353 IDirect3DDevice8Impl_TestCooperativeLevel,
4354 IDirect3DDevice8Impl_GetAvailableTextureMem,
4355 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4356 IDirect3DDevice8Impl_GetDirect3D,
4357 IDirect3DDevice8Impl_GetDeviceCaps,
4358 IDirect3DDevice8Impl_GetDisplayMode,
4359 IDirect3DDevice8Impl_GetCreationParameters,
4360 IDirect3DDevice8Impl_SetCursorProperties,
4361 IDirect3DDevice8Impl_SetCursorPosition,
4362 IDirect3DDevice8Impl_ShowCursor,
4363 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4364 IDirect3DDevice8Impl_Reset,
4365 IDirect3DDevice8Impl_Present,
4366 IDirect3DDevice8Impl_GetBackBuffer,
4367 IDirect3DDevice8Impl_GetRasterStatus,
4368 IDirect3DDevice8Impl_SetGammaRamp,
4369 IDirect3DDevice8Impl_GetGammaRamp,
4370 IDirect3DDevice8Impl_CreateTexture,
4371 IDirect3DDevice8Impl_CreateVolumeTexture,
4372 IDirect3DDevice8Impl_CreateCubeTexture,
4373 IDirect3DDevice8Impl_CreateVertexBuffer,
4374 IDirect3DDevice8Impl_CreateIndexBuffer,
4375 IDirect3DDevice8Impl_CreateRenderTarget,
4376 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4377 IDirect3DDevice8Impl_CreateImageSurface,
4378 IDirect3DDevice8Impl_CopyRects,
4379 IDirect3DDevice8Impl_UpdateTexture,
4380 IDirect3DDevice8Impl_GetFrontBuffer,
4381 IDirect3DDevice8Impl_SetRenderTarget,
4382 IDirect3DDevice8Impl_GetRenderTarget,
4383 IDirect3DDevice8Impl_GetDepthStencilSurface,
4384 IDirect3DDevice8Impl_BeginScene,
4385 IDirect3DDevice8Impl_EndScene,
4386 IDirect3DDevice8Impl_Clear,
4387 IDirect3DDevice8Impl_SetTransform,
4388 IDirect3DDevice8Impl_GetTransform,
4389 IDirect3DDevice8Impl_MultiplyTransform,
4390 IDirect3DDevice8Impl_SetViewport,
4391 IDirect3DDevice8Impl_GetViewport,
4392 IDirect3DDevice8Impl_SetMaterial,
4393 IDirect3DDevice8Impl_GetMaterial,
4394 IDirect3DDevice8Impl_SetLight,
4395 IDirect3DDevice8Impl_GetLight,
4396 IDirect3DDevice8Impl_LightEnable,
4397 IDirect3DDevice8Impl_GetLightEnable,
4398 IDirect3DDevice8Impl_SetClipPlane,
4399 IDirect3DDevice8Impl_GetClipPlane,
4400 IDirect3DDevice8Impl_SetRenderState,
4401 IDirect3DDevice8Impl_GetRenderState,
4402 IDirect3DDevice8Impl_BeginStateBlock,
4403 IDirect3DDevice8Impl_EndStateBlock,
4404 IDirect3DDevice8Impl_ApplyStateBlock,
4405 IDirect3DDevice8Impl_CaptureStateBlock,
4406 IDirect3DDevice8Impl_DeleteStateBlock,
4407 IDirect3DDevice8Impl_CreateStateBlock,
4408 IDirect3DDevice8Impl_SetClipStatus,
4409 IDirect3DDevice8Impl_GetClipStatus,
4410 IDirect3DDevice8Impl_GetTexture,
4411 IDirect3DDevice8Impl_SetTexture,
4412 IDirect3DDevice8Impl_GetTextureStageState,
4413 IDirect3DDevice8Impl_SetTextureStageState,
4414 IDirect3DDevice8Impl_ValidateDevice,
4415 IDirect3DDevice8Impl_GetInfo,
4416 IDirect3DDevice8Impl_SetPaletteEntries,
4417 IDirect3DDevice8Impl_GetPaletteEntries,
4418 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4419 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4420 IDirect3DDevice8Impl_DrawPrimitive,
4421 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4422 IDirect3DDevice8Impl_DrawPrimitiveUP,
4423 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4424 IDirect3DDevice8Impl_ProcessVertices,
4425 IDirect3DDevice8Impl_CreateVertexShader,
4426 IDirect3DDevice8Impl_SetVertexShader,
4427 IDirect3DDevice8Impl_GetVertexShader,
4428 IDirect3DDevice8Impl_DeleteVertexShader,
4429 IDirect3DDevice8Impl_SetVertexShaderConstant,
4430 IDirect3DDevice8Impl_GetVertexShaderConstant,
4431 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4432 IDirect3DDevice8Impl_GetVertexShaderFunction,
4433 IDirect3DDevice8Impl_SetStreamSource,
4434 IDirect3DDevice8Impl_GetStreamSource,
4435 IDirect3DDevice8Impl_SetIndices,
4436 IDirect3DDevice8Impl_GetIndices,
4437 IDirect3DDevice8Impl_CreatePixelShader,
4438 IDirect3DDevice8Impl_SetPixelShader,
4439 IDirect3DDevice8Impl_GetPixelShader,
4440 IDirect3DDevice8Impl_DeletePixelShader,
4441 IDirect3DDevice8Impl_SetPixelShaderConstant,
4442 IDirect3DDevice8Impl_GetPixelShaderConstant,
4443 IDirect3DDevice8Impl_GetPixelShaderFunction,
4444 IDirect3DDevice8Impl_DrawRectPatch,
4445 IDirect3DDevice8Impl_DrawTriPatch,
4446 IDirect3DDevice8Impl_DeletePatch
4449 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4451 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4452 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4457 if (This->glCtx != This->render_ctx) {
4458 glXDestroyContext(This->display, This->render_ctx);
4459 This->render_ctx = This->glCtx;
4462 if (This->win != This->drawable) {
4463 glXDestroyPbuffer(This->display, This->drawable);
4464 This->drawable = This->win;
4473 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4474 IDirect3DSurface8* RenderSurface,
4475 IDirect3DSurface8* StencilSurface) {
4477 HRESULT ret = D3DERR_INVALIDCALL;
4479 * Currently only active for GLX >= 1.3
4480 * for others versions we'll have to use GLXPixmaps
4482 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4483 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4484 * so only check OpenGL version
4486 #if defined(GL_VERSION_1_3)
4487 GLXFBConfig* cfgs = NULL;
4491 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4492 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4493 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4494 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4495 IDirect3DSurface8Impl* tmp;
4497 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4499 #define PUSH1(att) attribs[nAttribs++] = (att);
4500 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4502 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4503 PUSH2(GLX_X_RENDERABLE, TRUE);
4504 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4506 switch (BackBufferFormat) {
4509 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4510 PUSH2(GLX_BUFFER_SIZE, 8);
4511 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4515 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4516 PUSH2(GLX_RED_SIZE, 3);
4517 PUSH2(GLX_GREEN_SIZE, 3);
4518 PUSH2(GLX_BLUE_SIZE, 2);
4521 case D3DFMT_A1R5G5B5:
4522 PUSH2(GLX_ALPHA_SIZE, 1);
4523 case D3DFMT_X1R5G5B5:
4524 PUSH2(GLX_RED_SIZE, 5);
4525 PUSH2(GLX_GREEN_SIZE, 5);
4526 PUSH2(GLX_BLUE_SIZE, 5);
4530 PUSH2(GLX_RED_SIZE, 5);
4531 PUSH2(GLX_GREEN_SIZE, 6);
4532 PUSH2(GLX_BLUE_SIZE, 5);
4535 case D3DFMT_A4R4G4B4:
4536 PUSH2(GLX_ALPHA_SIZE, 4);
4537 case D3DFMT_X4R4G4B4:
4538 PUSH2(GLX_RED_SIZE, 4);
4539 PUSH2(GLX_GREEN_SIZE, 4);
4540 PUSH2(GLX_BLUE_SIZE, 4);
4543 case D3DFMT_A8R8G8B8:
4544 PUSH2(GLX_ALPHA_SIZE, 8);
4546 case D3DFMT_X8R8G8B8:
4547 PUSH2(GLX_RED_SIZE, 8);
4548 PUSH2(GLX_GREEN_SIZE, 8);
4549 PUSH2(GLX_BLUE_SIZE, 8);
4556 switch (StencilBufferFormat) {
4557 case D3DFMT_D16_LOCKABLE:
4559 PUSH2(GLX_DEPTH_SIZE, 16);
4563 PUSH2(GLX_DEPTH_SIZE, 15);
4567 PUSH2(GLX_DEPTH_SIZE, 24);
4570 case D3DFMT_D24X4S4:
4571 PUSH2(GLX_DEPTH_SIZE, 24);
4572 PUSH2(GLX_STENCIL_SIZE, 4);
4576 PUSH2(GLX_DEPTH_SIZE, 24);
4577 PUSH2(GLX_STENCIL_SIZE, 8);
4581 PUSH2(GLX_DEPTH_SIZE, 32);
4592 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4596 for (i = 0; i < nCfgs; ++i) {
4597 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4601 if (NULL != This->renderTarget) {
4602 /*GLenum prev_read; */
4604 vcheckGLcall("glFlush");
4607 /** very very usefull debug code */
4608 glXSwapBuffers(This->display, This->drawable);
4609 printf("Hit Enter to get next frame ...\n");
4614 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4615 vcheckGLcall("glIntegerv");
4616 glReadBuffer(GL_BACK);
4617 vcheckGLcall("glReadBuffer");
4620 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4622 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4625 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4627 This->renderTarget->myDesc.Height - j - 1,
4628 This->renderTarget->myDesc.Width,
4630 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4631 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4632 This->renderTarget->allocatedMemory + j * pitch);
4633 vcheckGLcall("glReadPixels");
4636 glReadBuffer(prev_read);
4637 vcheckGLcall("glReadBuffer");
4641 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4642 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4644 PUSH2(GLX_PBUFFER_WIDTH, Width);
4645 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4647 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4649 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4650 if (NULL == This->render_ctx) {
4651 ERR("cannot create glxContext\n");
4655 glXSwapBuffers(This->display, This->drawable);
4656 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4657 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4659 checkGLcall("glXMakeContextCurrent");
4662 tmp = This->renderTarget;
4663 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4664 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4665 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4667 tmp = This->stencilBufferTarget;
4668 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4669 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4670 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4674 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4675 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4676 /* Force updating the cull mode */
4677 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4678 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4679 /* Force updating projection matrix */
4680 This->last_was_rhw = FALSE;
4681 This->proj_valid = FALSE;
4687 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));