Implement resource tracking, require for reset and evict managed
resources and provides extra sanity checks.
This commit is contained in:
parent
ef1da879df
commit
ea6189e04b
|
@ -59,6 +59,10 @@ BOOL pbuffer_support = TRUE;
|
||||||
/* allocate one pbuffer per surface */
|
/* allocate one pbuffer per surface */
|
||||||
BOOL pbuffer_per_surface = FALSE;
|
BOOL pbuffer_per_surface = FALSE;
|
||||||
|
|
||||||
|
/* static function declarations */
|
||||||
|
static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
|
||||||
|
|
||||||
|
|
||||||
/* helper macros */
|
/* helper macros */
|
||||||
#define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
|
#define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
|
||||||
|
|
||||||
|
@ -102,6 +106,7 @@ BOOL pbuffer_per_surface = FALSE;
|
||||||
return D3DERR_OUTOFVIDEOMEMORY; \
|
return D3DERR_OUTOFVIDEOMEMORY; \
|
||||||
} \
|
} \
|
||||||
*pp##type = (IWineD3D##type *) object; \
|
*pp##type = (IWineD3D##type *) object; \
|
||||||
|
IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
|
||||||
TRACE("(%p) : Created resource %p\n", This, object); \
|
TRACE("(%p) : Created resource %p\n", This, object); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5724,6 +5729,176 @@ void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapCha
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************************
|
||||||
|
* Notification functions
|
||||||
|
** ********************************************************/
|
||||||
|
/** This function must be called in the release of a resource when ref == 0,
|
||||||
|
* the contents of resource must still be correct,
|
||||||
|
* any handels to other resource held by the caller must be closed
|
||||||
|
* (e.g. a texture should release all held surfaces because telling the device that it's been released.)
|
||||||
|
*****************************************************/
|
||||||
|
static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
ResourceList* resourceList;
|
||||||
|
|
||||||
|
TRACE("(%p) : resource %p\n", This, resource);
|
||||||
|
#if 0
|
||||||
|
EnterCriticalSection(&resourceStoreCriticalSection);
|
||||||
|
#endif
|
||||||
|
/* add a new texture to the frot of the linked list */
|
||||||
|
resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
|
||||||
|
resourceList->resource = resource;
|
||||||
|
|
||||||
|
/* Get the old head */
|
||||||
|
resourceList->next = This->resources;
|
||||||
|
|
||||||
|
This->resources = resourceList;
|
||||||
|
TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LeaveCriticalSection(&resourceStoreCriticalSection);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
ResourceList* resourceList = NULL;
|
||||||
|
ResourceList* previousResourceList = NULL;
|
||||||
|
|
||||||
|
TRACE("(%p) : resource %p\n", This, resource);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
EnterCriticalSection(&resourceStoreCriticalSection);
|
||||||
|
#endif
|
||||||
|
resourceList = This->resources;
|
||||||
|
|
||||||
|
while (resourceList != NULL) {
|
||||||
|
if(resourceList->resource == resource) break;
|
||||||
|
previousResourceList = resourceList;
|
||||||
|
resourceList = resourceList->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resourceList == NULL) {
|
||||||
|
FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
|
||||||
|
#if 0
|
||||||
|
LeaveCriticalSection(&resourceStoreCriticalSection);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
|
||||||
|
}
|
||||||
|
/* make sure we don't leave a hole in the list */
|
||||||
|
if (previousResourceList != NULL) {
|
||||||
|
previousResourceList->next = resourceList->next;
|
||||||
|
} else {
|
||||||
|
This->resources = resourceList->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LeaveCriticalSection(&resourceStoreCriticalSection);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
|
||||||
|
int counter;
|
||||||
|
|
||||||
|
TRACE("(%p) : resource %p\n", This, resource);
|
||||||
|
switch(IWineD3DResource_GetType(resource)){
|
||||||
|
case D3DRTYPE_SURFACE:
|
||||||
|
/* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
|
||||||
|
break;
|
||||||
|
case D3DRTYPE_TEXTURE:
|
||||||
|
case D3DRTYPE_CUBETEXTURE:
|
||||||
|
case D3DRTYPE_VOLUMETEXTURE:
|
||||||
|
for (counter = 0; counter < GL_LIMITS(textures); counter++) {
|
||||||
|
if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
|
||||||
|
IUnknown *textureParent;
|
||||||
|
IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
|
||||||
|
/* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
|
||||||
|
FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
|
||||||
|
IUnknown_Release(textureParent);
|
||||||
|
This->stateBlock->textures[counter] = NULL;
|
||||||
|
}
|
||||||
|
if (This->updateStateBlock != This->stateBlock ){
|
||||||
|
if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
|
||||||
|
IUnknown *textureParent;
|
||||||
|
IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
|
||||||
|
/* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
|
||||||
|
FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
|
||||||
|
IUnknown_Release(textureParent);
|
||||||
|
This->updateStateBlock->textures[counter] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case D3DRTYPE_VOLUME:
|
||||||
|
/* TODO: nothing really? */
|
||||||
|
break;
|
||||||
|
case D3DRTYPE_VERTEXBUFFER:
|
||||||
|
/* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
|
||||||
|
{
|
||||||
|
int streamNumber;
|
||||||
|
TRACE("Cleaning up stream pointers\n");
|
||||||
|
|
||||||
|
for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
|
||||||
|
/* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
|
||||||
|
FINDOUT: should changes.streamSource[StreamNumber] be set ?
|
||||||
|
*/
|
||||||
|
if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
|
||||||
|
if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
|
||||||
|
FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
|
||||||
|
This->updateStateBlock->streamSource[streamNumber] = 0;
|
||||||
|
/* Set changed flag? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
|
||||||
|
if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
|
||||||
|
TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
|
||||||
|
This->stateBlock->streamSource[streamNumber] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
|
||||||
|
else { /* This shouldn't happen */
|
||||||
|
FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case D3DRTYPE_INDEXBUFFER:
|
||||||
|
/* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
|
||||||
|
if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
|
||||||
|
if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
|
||||||
|
This->updateStateBlock->pIndexData = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
|
||||||
|
if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
|
||||||
|
This->stateBlock->pIndexData = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove the resoruce from the resourceStore */
|
||||||
|
IWineD3DDeviceImpl_RemoveResource(iface, resource);
|
||||||
|
|
||||||
|
TRACE("Resource released\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************
|
/**********************************************************
|
||||||
* IWineD3DDevice VTbl follows
|
* IWineD3DDevice VTbl follows
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
|
@ -5859,7 +6034,9 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
|
||||||
IWineD3DDeviceImpl_GetRenderTargetData,
|
IWineD3DDeviceImpl_GetRenderTargetData,
|
||||||
IWineD3DDeviceImpl_GetFrontBufferData,
|
IWineD3DDeviceImpl_GetFrontBufferData,
|
||||||
/*** Internal use IWineD3DDevice methods ***/
|
/*** Internal use IWineD3DDevice methods ***/
|
||||||
IWineD3DDeviceImpl_SetupTextureStates
|
IWineD3DDeviceImpl_SetupTextureStates,
|
||||||
|
/*** object tracking ***/
|
||||||
|
IWineD3DDeviceImpl_ResourceReleased
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,11 @@ void IWineD3DResourceImpl_CleanUp(IWineD3DResource *iface){
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
|
HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
|
||||||
This->resource.allocatedMemory = 0;
|
This->resource.allocatedMemory = 0;
|
||||||
|
|
||||||
|
if (This->resource.wineD3DDevice != NULL) {
|
||||||
|
IWineD3DDevice_ResourceReleased((IWineD3DDevice *)This->resource.wineD3DDevice, iface);
|
||||||
|
}/* NOTE: this is not really an error for systemmem resoruces */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IWineD3DResource Interface follow: */
|
/* IWineD3DResource Interface follow: */
|
||||||
|
|
|
@ -411,6 +411,10 @@ this needs to be migrated to a list and some option availalbe for controle the c
|
||||||
*/
|
*/
|
||||||
#define CONTEXT_CACHE 100
|
#define CONTEXT_CACHE 100
|
||||||
|
|
||||||
|
typedef struct ResourceList {
|
||||||
|
IWineD3DResource *resource;
|
||||||
|
struct ResourceList *next;
|
||||||
|
} ResourceList;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* IWineD3DDevice implementation structure
|
* IWineD3DDevice implementation structure
|
||||||
|
@ -459,6 +463,8 @@ typedef struct IWineD3DDeviceImpl
|
||||||
IWineD3DSwapChain *swapchains[MAX_SWAPCHAINS]; /* no-one wil ever need more that MAX_SWAPCHAINS swapchains */
|
IWineD3DSwapChain *swapchains[MAX_SWAPCHAINS]; /* no-one wil ever need more that MAX_SWAPCHAINS swapchains */
|
||||||
int numberOfSwapChains;
|
int numberOfSwapChains;
|
||||||
|
|
||||||
|
ResourceList *resources; /* a linked list to track resources created by the device */
|
||||||
|
|
||||||
/* Render Target Support */
|
/* Render Target Support */
|
||||||
IWineD3DSurface *depthStencilBuffer;
|
IWineD3DSurface *depthStencilBuffer;
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,8 @@ DECLARE_INTERFACE_(IWineD3DDevice,IUnknown)
|
||||||
STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IWineD3DSurface* pSurface) PURE;
|
STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IWineD3DSurface* pSurface) PURE;
|
||||||
/*** Internal use IWineD3Device methods ***/
|
/*** Internal use IWineD3Device methods ***/
|
||||||
STDMETHOD_(void, SetupTextureStates)(THIS_ DWORD Stage, DWORD Flags);
|
STDMETHOD_(void, SetupTextureStates)(THIS_ DWORD Stage, DWORD Flags);
|
||||||
|
/*** object tracking ***/
|
||||||
|
STDMETHOD_(void, ResourceReleased)(THIS_ IWineD3DResource *resource);
|
||||||
};
|
};
|
||||||
#undef INTERFACE
|
#undef INTERFACE
|
||||||
|
|
||||||
|
@ -514,6 +516,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IUnknown)
|
||||||
#define IWineD3DDevice_GetRenderTargetData(p,a,b) (p)->lpVtbl->GetRenderTargetData(p,a,b)
|
#define IWineD3DDevice_GetRenderTargetData(p,a,b) (p)->lpVtbl->GetRenderTargetData(p,a,b)
|
||||||
#define IWineD3DDevice_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b)
|
#define IWineD3DDevice_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b)
|
||||||
#define IWineD3DDevice_SetupTextureStates(p,a,b) (p)->lpVtbl->SetupTextureStates(p,a,b)
|
#define IWineD3DDevice_SetupTextureStates(p,a,b) (p)->lpVtbl->SetupTextureStates(p,a,b)
|
||||||
|
#define IWineD3DDevice_ResourceReleased(p,a) (p)->lpVtbl->ResourceReleased(p,a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
Loading…
Reference in New Issue