wined3d: Internal reference counting.

Change most references to resources parent into references to the
resource, so that external reference counts match DirectX but object
aren't released if they are still referenced by the stateblock.
This commit is contained in:
Oliver Stieber 2005-12-15 10:25:47 +01:00 committed by Alexandre Julliard
parent 49f137b666
commit e76969b0d6
2 changed files with 47 additions and 70 deletions

View File

@ -1511,6 +1511,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* ifac
} else { /* something went wrong so clean up */
IUnknown* bufferParent;
if (object->frontBuffer) {
IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
IUnknown_Release(bufferParent); /* once for the get parent */
if (IUnknown_Release(bufferParent) > 0) {
@ -1785,15 +1786,10 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT St
which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
so for now, just count internally */
if (pStreamData != NULL) {
IUnknown *newVertexBufferParent;
/* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
IWineD3DVertexBuffer_AddRef(pStreamData);
}
if (oldSrc != NULL) {
IUnknown *oldVertexBufferParent;
IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
IUnknown_Release(oldVertexBufferParent);
IUnknown_Release(oldVertexBufferParent);
IWineD3DVertexBuffer_Release(oldSrc);
}
return D3D_OK;
@ -2653,16 +2649,11 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DInde
return D3D_OK;
}
if (pIndexData) {
IUnknown *indexBufferParent;
/* Getting the parent causes a addRef... it gets released when the indicies are clear */
IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
if (NULL != pIndexData) {
IWineD3DIndexBuffer_AddRef(pIndexData);
}
if (oldIdxs) {
IUnknown *indexBufferParent;
IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
IUnknown_Release(indexBufferParent);
IUnknown_Release(indexBufferParent);
if (NULL != oldIdxs) {
IWineD3DIndexBuffer_Release(oldIdxs);
}
return D3D_OK;
}
@ -3760,17 +3751,25 @@ HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IW
}
HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
This->updateStateBlock->vertexShader = pShader;
This->updateStateBlock->vertexShader = pShader;
This->updateStateBlock->changed.vertexShader = TRUE;
This->updateStateBlock->set.vertexShader = TRUE;
This->updateStateBlock->set.vertexShader = TRUE;
if (This->isRecordingState) {
TRACE("Recording... not performing anything\n");
return D3D_OK;
}
if (NULL != pShader) {
IWineD3DVertexShader_AddRef(pShader);
}
if (NULL != oldShader) {
IWineD3DVertexShader_Release(oldShader);
}
TRACE("(%p) : setting pShader(%p)\n", This, pShader);
/**
* TODO: merge HAL shaders context switching from prototype
@ -3934,7 +3933,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice *iface
HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
This->updateStateBlock->pixelShader = pShader;
This->updateStateBlock->changed.pixelShader = TRUE;
This->updateStateBlock->set.pixelShader = TRUE;
@ -3945,6 +3944,13 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3D
return D3D_OK;
}
if (NULL != pShader) {
IWineD3DPixelShader_AddRef(pShader);
}
if (NULL != oldShader) {
IWineD3DPixelShader_Release(oldShader);
}
TRACE("(%p) : setting pShader(%p)\n", This, pShader);
/**
* TODO: merge HAL shaders context switching from prototype
@ -4411,17 +4417,11 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage,
* This means we should pass the refcount up to the parent
*******************************/
if (NULL != This->updateStateBlock->textures[Stage]) {
IUnknown *textureParent;
IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
/** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
}
if (NULL != oldTexture) {
IUnknown *textureParent;
IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
IUnknown_Release(textureParent);
IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
oldTexture = NULL;
IWineD3DBaseTexture_Release(oldTexture);
}
return D3D_OK;
@ -4777,11 +4777,9 @@ HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIM
debug_d3dprimitivetype(PrimitiveType),
PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
/* release the stream source */
if (This->stateBlock->streamSource[0] != NULL) {
IUnknown *vertexBufferParent;
IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
IUnknown_Release(vertexBufferParent);
IUnknown_Release(vertexBufferParent);
IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
}
/* Note in the following, it's not this type, but that's the purpose of streamIsUP */
@ -4820,20 +4818,12 @@ HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
idxStride = 4;
}
/* release the stream and index data */
if (This->stateBlock->streamSource[0] != NULL) {
IUnknown *vertexBufferParent;
IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
This->stateBlock->streamSource[0] = NULL;
IUnknown_Release(vertexBufferParent);
IUnknown_Release(vertexBufferParent);
IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
}
if (This->stateBlock->pIndexData) {
IUnknown *indexBufferParent;
IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
This->stateBlock->pIndexData = NULL;
IUnknown_Release(indexBufferParent);
IUnknown_Release(indexBufferParent);
IWineD3DIndexBuffer_Release(This->stateBlock->pIndexData);
}
/* Note in the following, it's not this type, but that's the purpose of streamIsUP */
@ -6279,20 +6269,12 @@ void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DR
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);
WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
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);
WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
This->updateStateBlock->textures[counter] = NULL;
}
}

View File

@ -64,36 +64,31 @@ ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
/* Free any streams still bound */
for (counter = 0 ; counter < MAX_STREAMS ; counter++) {
if (This->streamSource[counter] != NULL) {
IUnknown *vertexBufferParent;
IWineD3DVertexBuffer_GetParent(This->streamSource[counter], &vertexBufferParent);
/* Set to NULL here so that Device_ResourceReleased can give a warning if This->streamSource[counter] == ResourceReleased */
IWineD3DVertexBuffer_Release(This->streamSource[counter]);
This->streamSource[counter] = NULL;
IUnknown_Release(vertexBufferParent);
IUnknown_Release(vertexBufferParent);
}
}
/* free any index data */
if (This->pIndexData) {
IUnknown *indexBufferParent;
IWineD3DIndexBuffer_GetParent(This->pIndexData, &indexBufferParent);
IWineD3DIndexBuffer_Release(This->pIndexData);
This->pIndexData = NULL;
TRACE("Releasing index buffer %p p(%p)", This->pIndexData, indexBufferParent);
IUnknown_Release(indexBufferParent);
IUnknown_Release(indexBufferParent);
}
if (NULL != This->pixelShader) {
IWineD3DPixelShader_Release(This->pixelShader);
}
if (NULL != This->vertexShader) {
IWineD3DVertexShader_Release(This->vertexShader);
}
/* NOTE: according to MSDN: The applicaion is responsible for making sure the texture references are cleared down */
for (counter = 0; counter < GL_LIMITS(textures); counter++) {
if (This->textures[counter]) {
IUnknown *textureParent;
IWineD3DBaseTexture_GetParent(This->textures[counter], &textureParent);
/* FIXME: Were not using internal counting properly, so were making up for it here by releasing the object anyway */
IUnknown_Release(textureParent);
/* release our 'internal' hold on the texture */
if(0 != IUnknown_Release(textureParent)) {
TRACE("Texture still referenced by stateblock, applications has leaked Stage = %u Texture = %p Parent = %p\n", counter, This->textures[counter], textureParent);
if(0 != IWineD3DBaseTexture_Release(This->textures[counter])) {
TRACE("Texture still referenced by stateblock, applications has leaked Stage = %u Texture = %p \n", counter, This->textures[counter]);
}
}
}