mirror of
https://github.com/reactos/wine.git
synced 2024-11-26 05:00:30 +00:00
wined3d: Hold an internal reference on pixel and vertex shaders.
This commit is contained in:
parent
c52a190a88
commit
36aef3dc54
@ -522,6 +522,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
|
||||
if(object->pIndexData) {
|
||||
IWineD3DIndexBuffer_AddRef(object->pIndexData);
|
||||
}
|
||||
if(object->vertexShader) {
|
||||
IWineD3DVertexShader_AddRef(object->vertexShader);
|
||||
}
|
||||
if(object->pixelShader) {
|
||||
IWineD3DPixelShader_AddRef(object->pixelShader);
|
||||
}
|
||||
|
||||
} else if (Type == WINED3DSBT_PIXELSTATE) {
|
||||
|
||||
@ -568,6 +574,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
|
||||
object->num_contained_sampler_states++;
|
||||
}
|
||||
}
|
||||
if(object->pixelShader) {
|
||||
IWineD3DPixelShader_AddRef(object->pixelShader);
|
||||
}
|
||||
|
||||
/* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting
|
||||
* on them. This makes releasing the buffer easier
|
||||
@ -576,6 +585,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
|
||||
object->streamSource[i] = NULL;
|
||||
}
|
||||
object->pIndexData = NULL;
|
||||
object->vertexShader = NULL;
|
||||
|
||||
} else if (Type == WINED3DSBT_VERTEXSTATE) {
|
||||
|
||||
@ -636,7 +646,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
|
||||
IWineD3DVertexBuffer_AddRef(object->streamSource[i]);
|
||||
}
|
||||
}
|
||||
if(object->vertexShader) {
|
||||
IWineD3DVertexShader_AddRef(object->vertexShader);
|
||||
}
|
||||
object->pIndexData = NULL;
|
||||
object->pixelShader = NULL;
|
||||
} else {
|
||||
FIXME("Unrecognized state block type %d\n", Type);
|
||||
}
|
||||
@ -3091,6 +3105,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface,
|
||||
This->updateStateBlock->changed.vertexShader = TRUE;
|
||||
|
||||
if (This->isRecordingState) {
|
||||
if(pShader) IWineD3DVertexShader_AddRef(pShader);
|
||||
if(oldShader) IWineD3DVertexShader_Release(oldShader);
|
||||
TRACE("Recording... not performing anything\n");
|
||||
return WINED3D_OK;
|
||||
} else if(oldShader == pShader) {
|
||||
@ -3100,6 +3116,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface,
|
||||
}
|
||||
|
||||
TRACE("(%p) : setting pShader(%p)\n", This, pShader);
|
||||
if(pShader) IWineD3DVertexShader_AddRef(pShader);
|
||||
if(oldShader) IWineD3DVertexShader_Release(oldShader);
|
||||
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
|
||||
|
||||
@ -3478,6 +3496,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, I
|
||||
|
||||
if (This->isRecordingState) {
|
||||
TRACE("Recording... not performing anything\n");
|
||||
if(pShader) IWineD3DPixelShader_AddRef(pShader);
|
||||
if(oldShader) IWineD3DPixelShader_Release(oldShader);
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
@ -3486,6 +3506,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, I
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
if(pShader) IWineD3DPixelShader_AddRef(pShader);
|
||||
if(oldShader) IWineD3DPixelShader_Release(oldShader);
|
||||
|
||||
TRACE("(%p) : setting pShader(%p)\n", This, pShader);
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
|
||||
|
||||
|
@ -73,18 +73,6 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface)
|
||||
TRACE("(%p) : Releasing from %d\n", This, This->ref);
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
if (ref == 0) {
|
||||
/* SetPixelShader does not AddRef. If the bound pixel shader is destroyed, the pointer in the stateblock remains
|
||||
* unchanged. Drawing again will most likely crash, even on windows. A problem can occur if the application creates
|
||||
* a new pixel shader which resides at the same address. Then SetPixelShader will think it is a NOP change, and won't
|
||||
* dirtify the state.
|
||||
*
|
||||
* Do NOT call GetPixelShader here. This will addRef and cause a recursion. And do NOT set the pixel shader to NULL,
|
||||
* Windows does not do that(Although no test exists since they'd crash randomly)
|
||||
*/
|
||||
if(iface == ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->pixelShader) {
|
||||
IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *) This->baseShader.device, STATE_PIXELSHADER);
|
||||
}
|
||||
|
||||
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
||||
struct list *linked_programs = &This->baseShader.linked_programs;
|
||||
|
||||
|
@ -272,6 +272,8 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
|
||||
}
|
||||
}
|
||||
if(This->pIndexData) IWineD3DIndexBuffer_Release(This->pIndexData);
|
||||
if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
|
||||
if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
|
||||
|
||||
for(counter = 0; counter < LIGHTMAP_SIZE; counter++) {
|
||||
struct list *e1, *e2;
|
||||
@ -386,9 +388,11 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
if (This->blockType == WINED3DSBT_RECORDED) {
|
||||
|
||||
/* Recorded => Only update 'changed' values */
|
||||
if (This->vertexShader != targetStateBlock->vertexShader) {
|
||||
if (This->changed.vertexShader && This->vertexShader != targetStateBlock->vertexShader) {
|
||||
TRACE("Updating vertex shader from %p to %p\n", This->vertexShader, targetStateBlock->vertexShader);
|
||||
|
||||
if(targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
|
||||
if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
|
||||
This->vertexShader = targetStateBlock->vertexShader;
|
||||
}
|
||||
|
||||
@ -431,13 +435,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
This->vertexShaderConstantB[i] = targetStateBlock->vertexShaderConstantB[i];
|
||||
}
|
||||
|
||||
/* Recorded => Only update 'changed' values */
|
||||
if (This->pixelShader != targetStateBlock->pixelShader) {
|
||||
TRACE("Updating pixel shader from %p to %p\n", This->pixelShader, targetStateBlock->pixelShader);
|
||||
|
||||
This->pixelShader = targetStateBlock->pixelShader;
|
||||
}
|
||||
|
||||
/* Pixel Shader Float Constants */
|
||||
for (j = 0; j < This->num_contained_ps_consts_f; ++j) {
|
||||
i = This->contained_ps_consts_f[j];
|
||||
@ -594,11 +591,15 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
This->samplerState[stage][state]);
|
||||
This->samplerState[stage][state] = targetStateBlock->samplerState[stage][state];
|
||||
}
|
||||
if(This->changed.pixelShader && This->pixelShader != targetStateBlock->pixelShader) {
|
||||
if(targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
|
||||
if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
|
||||
This->pixelShader = targetStateBlock->pixelShader;
|
||||
}
|
||||
|
||||
record_lights(This, targetStateBlock);
|
||||
} else if(This->blockType == WINED3DSBT_ALL) {
|
||||
This->vertexDecl = targetStateBlock->vertexDecl;
|
||||
This->vertexShader = targetStateBlock->vertexShader;
|
||||
memcpy(This->vertexShaderConstantB, targetStateBlock->vertexShaderConstantB, sizeof(This->vertexShaderConstantI));
|
||||
memcpy(This->vertexShaderConstantI, targetStateBlock->vertexShaderConstantI, sizeof(This->vertexShaderConstantF));
|
||||
memcpy(This->vertexShaderConstantF, targetStateBlock->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
|
||||
@ -613,7 +614,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
This->clip_status = targetStateBlock->clip_status;
|
||||
This->viewport = targetStateBlock->viewport;
|
||||
This->material = targetStateBlock->material;
|
||||
This->pixelShader = targetStateBlock->pixelShader;
|
||||
memcpy(This->pixelShaderConstantB, targetStateBlock->pixelShaderConstantB, sizeof(This->pixelShaderConstantI));
|
||||
memcpy(This->pixelShaderConstantI, targetStateBlock->pixelShaderConstantI, sizeof(This->pixelShaderConstantF));
|
||||
memcpy(This->pixelShaderConstantF, targetStateBlock->pixelShaderConstantF, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
|
||||
@ -636,8 +636,17 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
This->streamSource[i] = targetStateBlock->streamSource[i];
|
||||
}
|
||||
}
|
||||
if(This->vertexShader != targetStateBlock->vertexShader) {
|
||||
if(targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
|
||||
if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
|
||||
This->vertexShader = targetStateBlock->vertexShader;
|
||||
}
|
||||
if(This->pixelShader != targetStateBlock->pixelShader) {
|
||||
if(targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
|
||||
if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
|
||||
This->pixelShader = targetStateBlock->pixelShader;
|
||||
}
|
||||
} else if(This->blockType == WINED3DSBT_VERTEXSTATE) {
|
||||
This->vertexShader = targetStateBlock->vertexShader;
|
||||
memcpy(This->vertexShaderConstantB, targetStateBlock->vertexShaderConstantB, sizeof(This->vertexShaderConstantI));
|
||||
memcpy(This->vertexShaderConstantI, targetStateBlock->vertexShaderConstantI, sizeof(This->vertexShaderConstantF));
|
||||
memcpy(This->vertexShaderConstantF, targetStateBlock->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
|
||||
@ -662,8 +671,12 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
This->streamSource[i] = targetStateBlock->streamSource[i];
|
||||
}
|
||||
}
|
||||
if(This->vertexShader != targetStateBlock->vertexShader) {
|
||||
if(targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
|
||||
if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
|
||||
This->vertexShader = targetStateBlock->vertexShader;
|
||||
}
|
||||
} else if(This->blockType == WINED3DSBT_PIXELSTATE) {
|
||||
This->pixelShader = targetStateBlock->pixelShader;
|
||||
memcpy(This->pixelShaderConstantB, targetStateBlock->pixelShaderConstantB, sizeof(This->pixelShaderConstantI));
|
||||
memcpy(This->pixelShaderConstantI, targetStateBlock->pixelShaderConstantI, sizeof(This->pixelShaderConstantF));
|
||||
memcpy(This->pixelShaderConstantF, targetStateBlock->pixelShaderConstantF, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
|
||||
@ -680,6 +693,11 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
|
||||
This->textureState[j][SavedPixelStates_R[i]] = targetStateBlock->textureState[j][SavedPixelStates_R[i]];
|
||||
}
|
||||
}
|
||||
if(This->pixelShader != targetStateBlock->pixelShader) {
|
||||
if(targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
|
||||
if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
|
||||
This->pixelShader = targetStateBlock->pixelShader;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("(%p) : Updated state block %p ------------------^\n", targetStateBlock, This);
|
||||
|
@ -460,11 +460,6 @@ static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface
|
||||
TRACE("(%p) : Releasing from %d\n", This, This->ref);
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
if (ref == 0) {
|
||||
if(iface == ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->vertexShader) {
|
||||
/* See comment in PixelShader::Release */
|
||||
IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *) This->baseShader.device, STATE_VSHADER);
|
||||
}
|
||||
|
||||
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
||||
struct list *linked_programs = &This->baseShader.linked_programs;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user