d3d9: Reject IDirect3DDevice9::Reset with active default pool resources.
This commit is contained in:
parent
8bb5d13fe2
commit
80953d62d7
|
@ -230,13 +230,110 @@ static BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9 iface,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI reset_enum_callback(IWineD3DResource *resource, void *data) {
|
||||
BOOL *resources_ok = (BOOL *) data;
|
||||
WINED3DRESOURCETYPE type;
|
||||
HRESULT ret = S_OK;
|
||||
WINED3DSURFACE_DESC surface_desc;
|
||||
WINED3DVOLUME_DESC volume_desc;
|
||||
WINED3DINDEXBUFFER_DESC index_desc;
|
||||
WINED3DVERTEXBUFFER_DESC vertex_desc;
|
||||
WINED3DFORMAT dummy_format;
|
||||
DWORD dummy_dword;
|
||||
WINED3DPOOL pool = WINED3DPOOL_SCRATCH; /* a harmless pool */
|
||||
IUnknown *parent;
|
||||
|
||||
type = IWineD3DResource_GetType(resource);
|
||||
switch(type) {
|
||||
case WINED3DRTYPE_SURFACE:
|
||||
surface_desc.Format = &dummy_format;
|
||||
surface_desc.Type = &type;
|
||||
surface_desc.Usage = &dummy_dword;
|
||||
surface_desc.Pool = &pool;
|
||||
surface_desc.Size = &dummy_dword;
|
||||
surface_desc.MultiSampleType = &dummy_dword;
|
||||
surface_desc.MultiSampleQuality = &dummy_dword;
|
||||
surface_desc.Width = &dummy_dword;
|
||||
surface_desc.Height = &dummy_dword;
|
||||
|
||||
IWineD3DSurface_GetDesc((IWineD3DSurface *) resource, &surface_desc);
|
||||
break;
|
||||
|
||||
case WINED3DRTYPE_VOLUME:
|
||||
volume_desc.Format = &dummy_format;
|
||||
volume_desc.Type = &type;
|
||||
volume_desc.Usage = &dummy_dword;
|
||||
volume_desc.Pool = &pool;
|
||||
volume_desc.Size = &dummy_dword;
|
||||
volume_desc.Width = &dummy_dword;
|
||||
volume_desc.Height = &dummy_dword;
|
||||
volume_desc.Depth = &dummy_dword;
|
||||
IWineD3DVolume_GetDesc((IWineD3DVolume *) resource, &volume_desc);
|
||||
break;
|
||||
|
||||
case WINED3DRTYPE_INDEXBUFFER:
|
||||
IWineD3DIndexBuffer_GetDesc((IWineD3DIndexBuffer *) resource, &index_desc);
|
||||
pool = index_desc.Pool;
|
||||
break;
|
||||
|
||||
case WINED3DRTYPE_VERTEXBUFFER:
|
||||
IWineD3DVertexBuffer_GetDesc((IWineD3DVertexBuffer *) resource, &vertex_desc);
|
||||
pool = index_desc.Pool;
|
||||
break;
|
||||
|
||||
/* No need to check for textures. If there is a D3DPOOL_DEFAULT texture, there
|
||||
* is a D3DPOOL_DEFAULT surface or volume as well
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(pool == WINED3DPOOL_DEFAULT) {
|
||||
IWineD3DResource_GetParent(resource, &parent);
|
||||
if(IUnknown_Release(parent) == 0) {
|
||||
TRACE("Parent %p is an implicit resource with ref 0\n", parent);
|
||||
} else {
|
||||
WARN("Resource %p(wineD3D %p) with pool D3DPOOL_DEFAULT blocks the Reset call\n", parent, resource);
|
||||
ret = S_FALSE;
|
||||
*resources_ok = FALSE;
|
||||
}
|
||||
}
|
||||
IWineD3DResource_Release(resource);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
|
||||
IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
|
||||
WINED3DPRESENT_PARAMETERS localParameters;
|
||||
HRESULT hr;
|
||||
BOOL resources_ok = TRUE;
|
||||
UINT i;
|
||||
|
||||
TRACE("(%p) Relay pPresentationParameters(%p)\n", This, pPresentationParameters);
|
||||
|
||||
/* Reset states that hold a COM object. WineD3D holds an internal reference to set objects, because
|
||||
* such objects can still be used for rendering after their external d3d9 object has been destroyed.
|
||||
* These objects must not be enumerated. Unsetting them tells WineD3D that the application will not
|
||||
* make use of the hidden reference and destroys the objects.
|
||||
*
|
||||
* Unsetting them is no problem, because the states are supposed to be reset anyway. If the validation
|
||||
* below fails, the device is considered "lost", and _Reset and _Release are the only allowed calls
|
||||
*/
|
||||
IWineD3DDevice_SetIndices(This->WineD3DDevice, NULL);
|
||||
for(i = 0; i < 16; i++) {
|
||||
IWineD3DDevice_SetStreamSource(This->WineD3DDevice, i, NULL, 0, 0);
|
||||
}
|
||||
for(i = 0; i < 16; i++) {
|
||||
IWineD3DDevice_SetTexture(This->WineD3DDevice, i, NULL);
|
||||
}
|
||||
|
||||
IWineD3DDevice_EnumResources(This->WineD3DDevice, reset_enum_callback, &resources_ok);
|
||||
if(!resources_ok) {
|
||||
WARN("The application is holding D3DPOOL_DEFAULT resources, rejecting reset\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
localParameters.BackBufferWidth = pPresentationParameters->BackBufferWidth;
|
||||
localParameters.BackBufferHeight = pPresentationParameters->BackBufferHeight;
|
||||
localParameters.BackBufferFormat = pPresentationParameters->BackBufferFormat;
|
||||
|
|
|
@ -279,6 +279,15 @@ static void test_swapchain(void)
|
|||
DestroyWindow( hwnd );
|
||||
}
|
||||
|
||||
/* Shared between two functions */
|
||||
static const DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
|
||||
0x0000001F, 0x80000000, 0x900F0000, /* dcl_position0 v0 */
|
||||
0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
|
||||
0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
|
||||
0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
|
||||
0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
|
||||
0x0000FFFF}; /* END */
|
||||
|
||||
static void test_refcount(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -313,13 +322,6 @@ static void test_refcount(void)
|
|||
{
|
||||
D3DDECL_END()
|
||||
};
|
||||
static DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
|
||||
0x0000001F, 0x80000000, 0x900F0000, /* dcl_position0 v0 */
|
||||
0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
|
||||
0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
|
||||
0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
|
||||
0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
|
||||
0x0000FFFF}; /* END */
|
||||
static DWORD simple_ps[] = {0xFFFF0101, /* ps_1_1 */
|
||||
0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
|
||||
0x00000042, 0xB00F0000, /* tex t0 */
|
||||
|
@ -719,6 +721,9 @@ static void test_reset(void)
|
|||
DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
|
||||
DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
|
||||
IDirect3DSwapChain9 *pSwapchain;
|
||||
IDirect3DSurface9 *surface;
|
||||
IDirect3DTexture9 *texture;
|
||||
IDirect3DVertexShader9 *shader;
|
||||
|
||||
pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
|
||||
ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
|
||||
|
@ -849,6 +854,55 @@ static void test_reset(void)
|
|||
IDirect3DSwapChain9_Release(pSwapchain);
|
||||
}
|
||||
|
||||
ZeroMemory( &d3dpp, sizeof(d3dpp) );
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.Windowed = TRUE;
|
||||
d3dpp.BackBufferWidth = 400;
|
||||
d3dpp.BackBufferHeight = 300;
|
||||
|
||||
/* _Reset fails if there is a resource in the default pool */
|
||||
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DSurface9_Release(surface);
|
||||
/* Reset again to get the device out of the lost state */
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
|
||||
/* Scratch, sysmem and managed pools are fine */
|
||||
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DSurface9_Release(surface);
|
||||
hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DSurface9_Release(surface);
|
||||
hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DTexture9_Release(texture);
|
||||
|
||||
/* A reference held to an implicit surface causes failures as well */
|
||||
hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DSurface9_Release(surface);
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
|
||||
/* Shaders are fine as well */
|
||||
hr = IDirect3DDevice9_CreateVertexShader(pDevice, simple_vs, &shader);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DVertexShader9_Release(shader);
|
||||
|
||||
cleanup:
|
||||
if(pD3d) IDirect3D9_Release(pD3d);
|
||||
if(pDevice) IDirect3D9_Release(pDevice);
|
||||
|
|
|
@ -6824,6 +6824,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
|
|||
if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
|
||||
ERR("What do do about a changed auto depth stencil parameter?\n");
|
||||
}
|
||||
TRACE("Checks done\n");
|
||||
|
||||
if(pPresentationParameters->Windowed) {
|
||||
mode.Width = swapchain->orig_width;
|
||||
|
@ -7095,6 +7096,24 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW
|
|||
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
|
||||
IWineD3DResourceImpl *resource, *cursor;
|
||||
HRESULT ret;
|
||||
TRACE("(%p)->(%p,%p)\n", This, pCallback, pData);
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
|
||||
TRACE("enumerating resource %p\n", resource);
|
||||
IWineD3DResource_AddRef((IWineD3DResource *) resource);
|
||||
ret = pCallback((IWineD3DResource *) resource, pData);
|
||||
if(ret == S_FALSE) {
|
||||
TRACE("Canceling enumeration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* IWineD3DDevice VTbl follows
|
||||
**********************************************************/
|
||||
|
@ -7241,7 +7260,8 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
|
|||
IWineD3DDeviceImpl_UpdateSurface,
|
||||
IWineD3DDeviceImpl_GetFrontBufferData,
|
||||
/*** object tracking ***/
|
||||
IWineD3DDeviceImpl_ResourceReleased
|
||||
IWineD3DDeviceImpl_ResourceReleased,
|
||||
IWineD3DDeviceImpl_EnumResources
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -247,6 +247,10 @@ typedef HRESULT (WINAPI *D3DCB_CREATEADDITIONALSWAPCHAIN) (IUnknown *pDevice,
|
|||
struct IWineD3DSwapChain **pSwapChain
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *D3DCB_ENUMRESOURCES) (struct IWineD3DResource *resource,
|
||||
void *pData
|
||||
);
|
||||
|
||||
/*****************************************************************************
|
||||
* Callback functions for custom implicit object destruction.
|
||||
*/
|
||||
|
@ -482,6 +486,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase)
|
|||
STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,struct IWineD3DSurface* pSurface) PURE;
|
||||
/*** object tracking ***/
|
||||
STDMETHOD_(void, ResourceReleased)(THIS_ struct IWineD3DResource *resource);
|
||||
STDMETHOD(EnumResources)(THIS_ D3DCB_ENUMRESOURCES pCallback, void *pData);
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
|
@ -621,6 +626,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase)
|
|||
#define IWineD3DDevice_UpdateSurface(p,a,b,c,d) (p)->lpVtbl->UpdateSurface(p,a,b,c,d)
|
||||
#define IWineD3DDevice_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b)
|
||||
#define IWineD3DDevice_ResourceReleased(p,a) (p)->lpVtbl->ResourceReleased(p,a)
|
||||
#define IWineD3DDevice_EnumResources(p,a,b) (p)->lpVtbl->EnumResources(p,a,b)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
Loading…
Reference in New Issue