From d170aabe2087c969dd7f2711c10810bf4895481b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Sun, 19 Aug 2007 20:40:44 +0200 Subject: [PATCH] wined3d: Non-primary stateblocks also hold an internal reference to buffers. --- dlls/wined3d/device.c | 21 +++++++++++++++++++++ dlls/wined3d/stateblock.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2b2dac5ae5c..6b537296788 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -514,6 +514,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, } } + for(i = 0; i < MAX_STREAMS; i++) { + if(object->streamSource[i]) { + IWineD3DVertexBuffer_AddRef(object->streamSource[i]); + } + } + } else if (Type == WINED3DSBT_PIXELSTATE) { TRACE("PIXELSTATE => Pretend all pixel shates have changed\n"); @@ -560,6 +566,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, } } + /* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting + * on them. This makes releasing the buffer easier + */ + for(i = 0; i < MAX_STREAMS; i++) { + object->streamSource[i] = NULL; + } + } else if (Type == WINED3DSBT_VERTEXSTATE) { TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n"); @@ -613,6 +626,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, light->enabledChanged = TRUE; } } + + for(i = 0; i < MAX_STREAMS; i++) { + if(object->streamSource[i]) { + IWineD3DVertexBuffer_AddRef(object->streamSource[i]); + } + } } else { FIXME("Unrecognized state block type %d\n", Type); } @@ -2237,6 +2256,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, /* Handle recording of state blocks */ if (This->isRecordingState) { TRACE("Recording... not performing anything\n"); + if(pStreamData) IWineD3DVertexBuffer_AddRef(pStreamData); + if(oldSrc) IWineD3DVertexBuffer_Release(oldSrc); return WINED3D_OK; } diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index dfe62c9f7d8..0362053a32b 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -262,15 +262,15 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) { } } } - for (counter = 0; counter < MAX_STREAMS; counter++) { - if(This->streamSource[counter]) { - if(0 != IWineD3DVertexBuffer_Release(This->streamSource[counter])) { - TRACE("Vertex buffer still referenced by stateblock, applications has leaked Stream %u, buffer %p\n", counter, This->streamSource[counter]); - } + if(This->pIndexData) IWineD3DIndexBuffer_Release(This->pIndexData); + } + + for (counter = 0; counter < MAX_STREAMS; counter++) { + if(This->streamSource[counter]) { + if(0 != IWineD3DVertexBuffer_Release(This->streamSource[counter])) { + TRACE("Vertex buffer still referenced by stateblock, applications has leaked Stream %u, buffer %p\n", counter, This->streamSource[counter]); } } - if(This->pIndexData) IWineD3DIndexBuffer_Release(This->pIndexData); - } for(counter = 0; counter < LIGHTMAP_SIZE; counter++) { @@ -532,6 +532,8 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) TRACE("Updating stream source %d to %p, stride to %d\n", i, targetStateBlock->streamSource[i], targetStateBlock->streamStride[i]); This->streamStride[i] = targetStateBlock->streamStride[i]; + if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]); + if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]); This->streamSource[i] = targetStateBlock->streamSource[i]; } @@ -600,7 +602,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) memcpy(This->vertexShaderConstantF, targetStateBlock->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4); memcpy(This->streamStride, targetStateBlock->streamStride, sizeof(This->streamStride)); memcpy(This->streamOffset, targetStateBlock->streamOffset, sizeof(This->streamOffset)); - memcpy(This->streamSource, targetStateBlock->streamSource, sizeof(This->streamSource)); memcpy(This->streamFreq, targetStateBlock->streamFreq, sizeof(This->streamFreq)); memcpy(This->streamFlags, targetStateBlock->streamFlags, sizeof(This->streamFlags)); This->pIndexData = targetStateBlock->pIndexData; @@ -621,6 +622,14 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) memcpy(This->textureState, targetStateBlock->textureState, sizeof(This->textureState)); memcpy(This->samplerState, targetStateBlock->samplerState, sizeof(This->samplerState)); This->scissorRect = targetStateBlock->scissorRect; + + for(i = 0; i < MAX_STREAMS; i++) { + if(targetStateBlock->streamSource[i] != This->streamSource[i]) { + if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]); + if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]); + This->streamSource[i] = targetStateBlock->streamSource[i]; + } + } } else if(This->blockType == WINED3DSBT_VERTEXSTATE) { This->vertexShader = targetStateBlock->vertexShader; memcpy(This->vertexShaderConstantB, targetStateBlock->vertexShaderConstantB, sizeof(This->vertexShaderConstantI)); @@ -640,6 +649,13 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) This->textureState[j][SavedVertexStates_R[i]] = targetStateBlock->textureState[j][SavedVertexStates_R[i]]; } } + for(i = 0; i < MAX_STREAMS; i++) { + if(targetStateBlock->streamSource[i] != This->streamSource[i]) { + if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]); + if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]); + This->streamSource[i] = targetStateBlock->streamSource[i]; + } + } } else if(This->blockType == WINED3DSBT_PIXELSTATE) { This->pixelShader = targetStateBlock->pixelShader; memcpy(This->pixelShaderConstantB, targetStateBlock->pixelShaderConstantB, sizeof(This->pixelShaderConstantI));