Module: wine Branch: master Commit: 5f159452ef4d7ca75122a8d812008a3a19e0fdb7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5f159452ef4d7ca75122a8d812...
Author: Stefan Dösinger stefan@codeweavers.com Date: Tue Mar 6 13:35:56 2007 +0100
wined3d: Clearing the depth stencil buffer fails without a depth stencil buffer.
---
dlls/d3d9/tests/device.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/device.c | 18 ++++++---- 2 files changed, 92 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 19862db..365b783 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -1157,6 +1157,87 @@ cleanup: if(hwnd) DestroyWindow(hwnd); }
+static void test_depthstenciltest(void) +{ + HRESULT hr; + HWND hwnd = NULL; + IDirect3D9 *pD3d = NULL; + IDirect3DDevice9 *pDevice = NULL; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + IDirect3DSurface9 *pDepthStencil = NULL; + DWORD state; + + pD3d = pDirect3DCreate9( D3D_SDK_VERSION ); + ok(pD3d != NULL, "Failed to create IDirect3D9 object\n"); + hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL ); + ok(hwnd != NULL, "Failed to create window\n"); + if (!pD3d || !hwnd) goto cleanup; + + IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm ); + ZeroMemory( &d3dpp, sizeof(d3dpp) ); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.BackBufferWidth = 800; + d3dpp.BackBufferHeight = 600; + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.EnableAutoDepthStencil = TRUE; + d3dpp.AutoDepthStencilFormat = D3DFMT_D16; + + hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice ); + ok(hr == D3D_OK, "IDirect3D9_CreateDevice failed with %s\n", DXGetErrorString9(hr)); + if(!pDevice) goto cleanup; + + hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil); + ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %s\n", DXGetErrorString9(hr)); + + /* Try to clear */ + hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %s\n", DXGetErrorString9(hr)); + + /* This left the render states untouched! */ + hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state); + ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr)); + ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW")); + hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state); + ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr)); + ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE"); + hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state); + ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr)); + ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE"); + hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state); + ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr)); + ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state); + + /* This is supposed to fail now */ + hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE); + ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil); + ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state); + ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr)); + ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW")); + + /* Now it works again */ + hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr)); + +cleanup: + if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil); + if(pD3d) IDirect3D9_Release(pD3d); + if(pDevice) IDirect3D9_Release(pDevice); + if(hwnd) DestroyWindow(hwnd); +} + START_TEST(device) { HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" ); @@ -1178,5 +1259,6 @@ START_TEST(device) test_reset(); test_scene(); test_limits(); + test_depthstenciltest(); } } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 6a78b23..7436ecb 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1744,7 +1744,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR LEAVE_GL();
/* Clear the screen */ - IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0); + IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, + WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0, + 0x00, 1.0, 0);
This->d3d_initialized = TRUE; return WINED3D_OK; @@ -4123,9 +4125,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the - render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag - when the depth-buffer format does not contain stencil buffer information, this method fails. */ GLbitfield glMask = 0; unsigned int i; CONST WINED3DRECT* curRect; @@ -4133,6 +4132,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This, Count, pRects, Flags, Z, Stencil);
+ if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) { + WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n"); + /* TODO: What about depth stencil buffers without stencil bits? */ + return WINED3DERR_INVALIDCALL; + } + ENTER_GL();
glEnable(GL_SCISSOR_TEST); @@ -5160,16 +5165,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice * * stencil buffer and incure an extra memory overhead ******************************************************/
- tmp = This->stencilBufferTarget; This->stencilBufferTarget = pNewZStencil; /* should we be calling the parent or the wined3d surface? */ if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget); if (NULL != tmp) IWineD3DSurface_Release(tmp); hr = WINED3D_OK; - /** TODO: glEnable/glDisable on depth/stencil depending on - * pNewZStencil is NULL and the depth/stencil is enabled in d3d - **********************************************************/ + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { set_depth_stencil_fbo(iface, pNewZStencil); }