[1/11] WineD3D: BeginScene / EndScene tests and fixes
Stefan Dösinger
stefan at codeweavers.com
Fri Jan 26 15:29:56 CST 2007
While trying to improve StretchRect I saw a note about beginScene in the msdn.
This patch adds some test cases and fixes for BeginScene / EndScene. Reading
the depth stencil buffer is disabled at the moment(until wined3d has proper
support for that).
-------------- next part --------------
From 4d1c300a73ce8cf6d3a3a27eb85ae3aaa4ec29a4 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Fri, 19 Jan 2007 19:30:09 +0100
Subject: [PATCH] WineD3D: BeginScene and EndScene tests and fixes
---
dlls/d3d8/tests/device.c | 64 +++++++++++++++++
dlls/d3d9/tests/device.c | 153 +++++++++++++++++++++++++++++++++++++++-
dlls/ddraw/device.c | 15 +++-
dlls/ddraw/tests/d3d.c | 36 +++++++++
dlls/wined3d/device.c | 21 +++++-
dlls/wined3d/surface.c | 17 +++++
dlls/wined3d/wined3d_private.h | 4 +-
7 files changed, 300 insertions(+), 10 deletions(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 8ec237e..0baf82a 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -759,6 +759,69 @@ static void test_display_modes(void)
IDirect3D8_Release(pD3d);
}
+static void test_scene()
+{
+ HRESULT hr;
+ HWND hwnd = NULL;
+ IDirect3D8 *pD3d = NULL;
+ IDirect3DDevice8 *pDevice = NULL;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+
+ pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
+ ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
+ hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
+ ok(hwnd != NULL, "Failed to create window\n");
+ if (!pD3d || !hwnd) goto cleanup;
+
+ IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
+ ZeroMemory( &d3dpp, sizeof(d3dpp) );
+ d3dpp.Windowed = FALSE;
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ d3dpp.BackBufferWidth = 800;
+ d3dpp.BackBufferHeight = 600;
+ d3dpp.BackBufferFormat = d3ddm.Format;
+
+
+ hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
+ ok(hr == D3D_OK, "IDirect3D8_CreateDevice failed with %s\n", DXGetErrorString8(hr));
+ if(!pDevice) goto cleanup;
+
+ /* Test an EndScene without beginscene. Should return an error */
+ hr = IDirect3DDevice8_EndScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %s\n", DXGetErrorString8(hr));
+
+ /* Test a normal BeginScene / EndScene pair, this should work */
+ hr = IDirect3DDevice8_BeginScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %s\n", DXGetErrorString8(hr));
+ if(SUCCEEDED(hr))
+ {
+ hr = IDirect3DDevice8_EndScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %s\n", DXGetErrorString8(hr));
+ }
+
+ /* Test another EndScene without having begun a new scene. Should return an error */
+ hr = IDirect3DDevice8_EndScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %s\n", DXGetErrorString8(hr));
+
+ /* Two nested BeginScene and EndScene calls */
+ hr = IDirect3DDevice8_BeginScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %s\n", DXGetErrorString8(hr));
+ hr = IDirect3DDevice8_BeginScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %s\n", DXGetErrorString8(hr));
+ hr = IDirect3DDevice8_EndScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %s\n", DXGetErrorString8(hr));
+ hr = IDirect3DDevice8_EndScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %s\n", DXGetErrorString8(hr));
+
+ /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
+
+cleanup:
+ if(pD3d) IDirect3D8_Release(pD3d);
+ if(pDevice) IDirect3D8_Release(pDevice);
+ if(hwnd) DestroyWindow(hwnd);
+}
START_TEST(device)
{
@@ -780,5 +843,6 @@ START_TEST(device)
test_mipmap_levels();
test_cursor();
test_states();
+ test_scene();
}
}
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 34108d5..d01aadc 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006 Vitaliy Margolen
- * Copyright (C) 2006 Stefan Dösinger(For CodeWeavers)
* Copyright (C) 2006 Chris Robinson
+ * Copyright (C) 2006-2007 Stefan Dösinger(For CodeWeavers)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -943,6 +943,156 @@ static void test_display_modes(void)
IDirect3D9_Release(pD3d);
}
+static void test_scene()
+{
+ HRESULT hr;
+ HWND hwnd = NULL;
+ IDirect3D9 *pD3d = NULL;
+ IDirect3DDevice9 *pDevice = NULL;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ IDirect3DSurface9 *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
+ IDirect3DSurface9 *pBackBuffer = NULL, *pDepthStencil = NULL;
+ RECT rect = {0, 0, 128, 128};
+ D3DCAPS9 caps;
+
+ 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;
+
+ /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
+ memset(&caps, 0, sizeof(caps));
+ hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
+ ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %s\n", DXGetErrorString9(hr));
+ if(FAILED(hr)) goto cleanup;
+
+ /* Test an EndScene without beginscene. Should return an error */
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
+
+ /* Test a normal BeginScene / EndScene pair, this should work */
+ hr = IDirect3DDevice9_BeginScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
+ if(SUCCEEDED(hr))
+ {
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
+ }
+
+ /* Test another EndScene without having begun a new scene. Should return an error */
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
+
+ /* Two nested BeginScene and EndScene calls */
+ hr = IDirect3DDevice9_BeginScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_BeginScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
+
+ /* Create some surfaces to test stretchrect between the scenes */
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
+ ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
+ ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
+ ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
+ ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %s\n", DXGetErrorString9(hr));
+
+ hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
+ ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
+ ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %s\n", DXGetErrorString9(hr));
+
+ /* First make sure a simple StretchRect call works */
+ if(pSurface1 && pSurface2) {
+ hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
+ ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
+ }
+ if(pBackBuffer && pRenderTarget) {
+ hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
+ ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
+ }
+ if(pDepthStencil && pSurface3) {
+ HRESULT expected;
+ if(0) /* Disabled for now because it crashes in wine */ {
+ expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
+ hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
+ ok( hr == expected, "IDirect3DDevice9_StretchRect returned %s, expected %s\n", DXGetErrorString9(hr), DXGetErrorString9(expected));
+ }
+ }
+
+ /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
+ * width normal surfaces, render targets and depth stencil surfaces.
+ */
+ hr = IDirect3DDevice9_BeginScene(pDevice);
+ ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
+
+ if(pSurface1 && pSurface2)
+ {
+ hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
+ ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
+ }
+ if(pBackBuffer && pRenderTarget)
+ {
+ hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
+ ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
+ }
+ if(pDepthStencil && pSurface3)
+ {
+ /* This is supposed to fail inside a BeginScene - EndScene pair. */
+ hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
+ ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %s, expected D3DERR_INVALIDCALL\n", DXGetErrorString9(hr));
+ }
+
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
+
+ /* Does a SetRenderTarget influence BeginScene / EndScene ?
+ * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
+ * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
+ */
+ hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_BeginScene(pDevice);
+ ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
+ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %s\n", DXGetErrorString9(hr));
+ hr = IDirect3DDevice9_EndScene(pDevice);
+ ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
+
+cleanup:
+ if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
+ if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
+ if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
+ if(pSurface1) IDirect3DSurface9_Release(pSurface1);
+ if(pSurface2) IDirect3DSurface9_Release(pSurface2);
+ if(pSurface3) IDirect3DSurface9_Release(pSurface3);
+ if(pD3d) IDirect3D9_Release(pD3d);
+ if(pDevice) IDirect3D9_Release(pDevice);
+ if(hwnd) DestroyWindow(hwnd);
+}
START_TEST(device)
{
@@ -963,5 +1113,6 @@ START_TEST(device)
test_mipmap_levels();
test_cursor();
test_reset();
+ test_scene();
}
}
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index d0f81f3..12455fd 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -1428,15 +1428,20 @@ IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
*
* Returns:
* D3D_OK on success, for details see IWineD3DDevice::BeginScene
+ * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
+ * started scene).
*
*****************************************************************************/
static HRESULT WINAPI
IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
+ HRESULT hr;
TRACE("(%p): Relay\n", This);
- return IWineD3DDevice_BeginScene(This->wineD3DDevice);
+ hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
+ if(hr == WINED3D_OK) return D3D_OK;
+ else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
}
static HRESULT WINAPI
@@ -1473,16 +1478,20 @@ Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
*
* Returns:
* D3D_OK on success, for details see IWineD3DDevice::EndScene
+ * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
+ * that only if the scene was already ended.
*
*****************************************************************************/
static HRESULT WINAPI
IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
+ HRESULT hr;
TRACE("(%p): Relay\n", This);
- IWineD3DDevice_EndScene(This->wineD3DDevice);
- return D3D_OK;
+ hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
+ if(hr == WINED3D_OK) return D3D_OK;
+ else return D3DERR_SCENE_NOT_IN_SCENE;
}
static HRESULT WINAPI
diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c
index 661efb3..e0de0fb 100644
--- a/dlls/ddraw/tests/d3d.c
+++ b/dlls/ddraw/tests/d3d.c
@@ -486,6 +486,41 @@ static void StateTest( void )
ok(rc == D3D_OK, "IDirect3DDevice7_SetRenderState(D3DRENDERSTATE_ZVISIBLE, FALSE) returned %08x\n", rc);
}
+
+static void SceneTest()
+{
+ HRESULT hr;
+
+ /* Test an EndScene without beginscene. Should return an error */
+ hr = IDirect3DDevice7_EndScene(lpD3DDevice);
+ ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
+
+ /* Test a normal BeginScene / EndScene pair, this should work */
+ hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
+ if(SUCCEEDED(hr))
+ {
+ hr = IDirect3DDevice7_EndScene(lpD3DDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
+ }
+
+ /* Test another EndScene without having begun a new scene. Should return an error */
+ hr = IDirect3DDevice7_EndScene(lpD3DDevice);
+ ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
+
+ /* Two nested BeginScene and EndScene calls */
+ hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
+ hr = IDirect3DDevice7_BeginScene(lpD3DDevice);
+ ok(hr == D3DERR_SCENE_IN_SCENE, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
+ hr = IDirect3DDevice7_EndScene(lpD3DDevice);
+ ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
+ hr = IDirect3DDevice7_EndScene(lpD3DDevice);
+ ok(hr == D3DERR_SCENE_NOT_IN_SCENE, "IDirect3DDevice7_EndScene returned %08x\n", hr);
+
+ /* TODO: Verify that blitting works in the same way as in d3d9 */
+}
+
START_TEST(d3d)
{
init_function_pointers();
@@ -501,5 +536,6 @@ START_TEST(d3d)
LightTest();
ProcessVerticesTest();
StateTest();
+ SceneTest();
ReleaseDirect3D();
}
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 2f95fb1..623d525 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4547,13 +4547,25 @@ static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
/* At the moment we have no need for any functionality at the beginning
of a scene */
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- TRACE("(%p) : stub\n", This);
+ TRACE("(%p)\n", This);
+
+ if(This->inScene) {
+ TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+ This->inScene = TRUE;
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
TRACE("(%p)\n", This);
+
+ if(!This->inScene) {
+ TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
ENTER_GL();
/* We only have to do this if we need to read the, swapbuffers performs a flush for us */
glFlush();
@@ -4579,8 +4591,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
IUnknown_Release(targetContainer);
}
}
- This->sceneEnded = TRUE;
LEAVE_GL();
+ This->inScene = FALSE;
return WINED3D_OK;
}
@@ -5713,8 +5725,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
} else {
/* Otherwise, set the render target up */
- if (!This->sceneEnded) {
+ if (This->inScene) {
+ /* EndScene takes care for loading the pbuffer into the texture. Call EndScene and BeginScene until we have better offscreen handling */
IWineD3DDevice_EndScene(iface);
+ IWineD3DDevice_BeginScene(iface);
}
TRACE("clearing renderer\n");
/* IWineD3DDeviceImpl_CleanRender(iface); */
@@ -5752,7 +5766,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
} else {
FIXME("Unknown error setting the render target\n");
}
- This->sceneEnded = FALSE;
return hr;
}
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index ca9900a..bcb49f1 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2759,9 +2759,18 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
+ IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
+ /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair */
+ if(myDevice->inScene &&
+ (iface == myDevice->stencilBufferTarget ||
+ (SrcSurface && SrcSurface == myDevice->stencilBufferTarget))) {
+ TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
/* Special cases for RenderTargets */
if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
@@ -2823,8 +2832,16 @@ HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
+ IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
+ if(myDevice->inScene &&
+ (iface == myDevice->stencilBufferTarget ||
+ (Source && Source == myDevice->stencilBufferTarget))) {
+ TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
+ return WINED3DERR_INVALIDCALL;
+ }
+
/* Special cases for RenderTargets */
if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 5fc8871..c1c36b0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -642,8 +642,8 @@ typedef struct IWineD3DDeviceImpl
/* Screen buffer resources */
glContext contextCache[CONTEXT_CACHE];
- /* A flag to check if endscene has been called before changing the render tartet */
- BOOL sceneEnded;
+ /* A flag to check for proper BeginScene / EndScene call pairs */
+ BOOL inScene;
/* process vertex shaders using software or hardware */
BOOL softwareVertexProcessing;
--
1.4.4.3
More information about the wine-patches
mailing list