Bug 1044975 - Don't crash if mapping D3D11 shader constant buffers fails. r=Bas
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -548,17 +548,20 @@ CompositorD3D11::ClearRect(const gfx::Re
mContext->VSSetShader(mAttachments->mVSQuadShader[MaskType::MaskNone], nullptr, 0);
mContext->PSSetShader(mAttachments->mSolidColorShader[MaskType::MaskNone], nullptr, 0);
mPSConstants.layerColor[0] = 0;
mPSConstants.layerColor[1] = 0;
mPSConstants.layerColor[2] = 0;
mPSConstants.layerColor[3] = 0;
- UpdateConstantBuffers();
+ if (!UpdateConstantBuffers()) {
+ NS_WARNING("Failed to update shader constant buffers");
+ return;
+ }
mContext->Draw(4, 0);
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
}
void
CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
@@ -734,17 +737,20 @@ CompositorD3D11::DrawQuad(const gfx::Rec
mContext->OMSetBlendState(mAttachments->mComponentBlendState, sBlendFactor, 0xFFFFFFFF);
restoreBlendMode = true;
}
break;
default:
NS_WARNING("Unknown shader type");
return;
}
- UpdateConstantBuffers();
+ if (!UpdateConstantBuffers()) {
+ NS_WARNING("Failed to update shader constant buffers");
+ return;
+ }
mContext->Draw(4, 0);
if (restoreBlendMode) {
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
}
}
void
@@ -961,33 +967,72 @@ CompositorD3D11::CreateShaders()
byRef(mAttachments->mRGBAShader[MaskType::Mask3d]));
if (FAILED(hr)) {
return false;
}
return true;
}
-void
+static
+bool ShouldRecoverFromMapFailure(HRESULT hr, ID3D11Device* device)
+{
+ // XXX - it would be nice to use gfxCriticalError, but it needs to
+ // be made to work off the main thread first.
+ if (SUCCEEDED(hr)) {
+ return true;
+ }
+ if (hr == DXGI_ERROR_DEVICE_REMOVED) {
+ switch (device->GetDeviceRemovedReason()) {
+ case DXGI_ERROR_DEVICE_HUNG:
+ case DXGI_ERROR_DEVICE_REMOVED:
+ case DXGI_ERROR_DEVICE_RESET:
+ case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
+ return true;
+ case DXGI_ERROR_INVALID_CALL:
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+bool
CompositorD3D11::UpdateConstantBuffers()
{
+ HRESULT hr;
D3D11_MAPPED_SUBRESOURCE resource;
- mContext->Map(mAttachments->mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+
+ hr = mContext->Map(mAttachments->mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+ if (FAILED(hr)) {
+ if (ShouldRecoverFromMapFailure(hr, GetDevice())) {
+ return false;
+ }
+ MOZ_CRASH();
+ }
*(VertexShaderConstants*)resource.pData = mVSConstants;
mContext->Unmap(mAttachments->mVSConstantBuffer, 0);
- mContext->Map(mAttachments->mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+
+ hr = mContext->Map(mAttachments->mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+ if (FAILED(hr)) {
+ if (ShouldRecoverFromMapFailure(hr, GetDevice())) {
+ return false;
+ }
+ MOZ_CRASH();
+ }
*(PixelShaderConstants*)resource.pData = mPSConstants;
mContext->Unmap(mAttachments->mPSConstantBuffer, 0);
ID3D11Buffer *buffer = mAttachments->mVSConstantBuffer;
mContext->VSSetConstantBuffers(0, 1, &buffer);
buffer = mAttachments->mPSConstantBuffer;
mContext->PSSetConstantBuffers(0, 1, &buffer);
+ return true;
}
void
CompositorD3D11::SetSamplerForFilter(Filter aFilter)
{
ID3D11SamplerState *sampler;
switch (aFilter) {
default:
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -143,17 +143,17 @@ public:
ID3D11DeviceContext* GetDC() { return mContext; }
private:
// ensure mSize is up to date with respect to mWidget
void EnsureSize();
void VerifyBufferSize();
void UpdateRenderTarget();
bool CreateShaders();
- void UpdateConstantBuffers();
+ bool UpdateConstantBuffers();
void SetSamplerForFilter(gfx::Filter aFilter);
void SetPSForEffect(Effect *aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat);
void PaintToTarget();
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE { return gfx::ToIntSize(mSize); }
RefPtr<ID3D11DeviceContext> mContext;
RefPtr<ID3D11Device> mDevice;