Bug 1163440: Behind a preference, off by default, use a mutex around present calls. This makes it easier to test with users that can reproduce some problems. r?bas
MozReview-Commit-ID: 9PTO3ntOFuR
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -62,19 +62,21 @@ namespace TexSlot {
}
CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget)
: Compositor(aWidget, aParent)
, mAttachments(nullptr)
, mHwnd(nullptr)
, mDisableSequenceForNextFrame(false)
, mAllowPartialPresents(false)
+ , mIsDoubleBuffered(false)
, mVerifyBuffersFailed(false)
- , mIsDoubleBuffered(false)
+ , mUseMutexOnPresent(false)
{
+ mUseMutexOnPresent = gfxPrefs::UseMutexOnPresent();
}
CompositorD3D11::~CompositorD3D11()
{
}
template<typename VertexType>
void
@@ -1170,16 +1172,22 @@ CompositorD3D11::Present()
// This must be called before present so our back buffer has the validated window content.
if (mTarget) {
PaintToTarget();
}
RefPtr<IDXGISwapChain1> chain;
HRESULT hr = mSwapChain->QueryInterface((IDXGISwapChain1**)getter_AddRefs(chain));
+ RefPtr<IDXGIKeyedMutex> mutex;
+ if (mUseMutexOnPresent && mAttachments->mSyncTexture) {
+ mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
+ MOZ_ASSERT(mutex);
+ }
+
if (SUCCEEDED(hr) && mAllowPartialPresents) {
DXGI_PRESENT_PARAMETERS params;
PodZero(¶ms);
params.DirtyRectsCount = mBackBufferInvalid.GetNumRects();
StackArray<RECT, 4> rects(params.DirtyRectsCount);
uint32_t i = 0;
for (auto iter = mBackBufferInvalid.RectIter(); !iter.Done(); iter.Next()) {
@@ -1187,19 +1195,39 @@ CompositorD3D11::Present()
rects[i].left = r.x;
rects[i].top = r.y;
rects[i].bottom = r.YMost();
rects[i].right = r.XMost();
i++;
}
params.pDirtyRects = params.DirtyRectsCount ? rects.data() : nullptr;
+
+ if (mutex) {
+ hr = mutex->AcquireSync(0, 2000);
+ NS_ENSURE_TRUE_VOID(SUCCEEDED(hr));
+ }
+
chain->Present1(presentInterval, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0, ¶ms);
+
+ if (mutex) {
+ mutex->ReleaseSync(0);
+ }
} else {
- HRESULT hr = mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
+ if (mutex) {
+ hr = mutex->AcquireSync(0, 2000);
+ NS_ENSURE_TRUE_VOID(SUCCEEDED(hr));
+ }
+
+ hr = mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
+
+ if (mutex) {
+ mutex->ReleaseSync(0);
+ }
+
if (FAILED(hr)) {
gfxCriticalNote << "D3D11 swap chain preset failed " << hexa(hr);
HandleError(hr);
}
}
if (mIsDoubleBuffered) {
mBackBufferInvalid = mFrontBufferInvalid;
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -231,14 +231,15 @@ private:
bool mIsDoubleBuffered;
gfx::IntRegion mFrontBufferInvalid;
gfx::IntRegion mBackBufferInvalid;
// This is the clip rect applied to the default DrawTarget (i.e. the window)
gfx::IntRect mCurrentClip;
bool mVerifyBuffersFailed;
+ bool mUseMutexOnPresent;
};
}
}
#endif
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -464,19 +464,18 @@ private:
DECL_GFX_PREF(Live, "gfx.testing.device-reset", DeviceResetForTesting, int32_t, 0);
DECL_GFX_PREF(Live, "gfx.testing.device-fail", DeviceFailForTesting, bool, false);
DECL_GFX_PREF(Once, "gfx.text.disable-aa", DisableAllTextAA, bool, false);
DECL_GFX_PREF(Live, "gfx.ycbcr.accurate-conversion", YCbCrAccurateConversion, bool, false);
// Disable surface sharing due to issues with compatible FBConfigs on
// NVIDIA drivers as described in bug 1193015.
DECL_GFX_PREF(Live, "gfx.use-glx-texture-from-pixmap", UseGLXTextureFromPixmap, bool, false);
-
DECL_GFX_PREF(Once, "gfx.use-iosurface-textures", UseIOSurfaceTextures, bool, false);
-
+ DECL_GFX_PREF(Once, "gfx.use-mutex-on-present", UseMutexOnPresent, bool, false);
// These times should be in milliseconds
DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold", TouchResampleVsyncDelayThreshold, int32_t, 20);
DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict", TouchResampleMaxPredict, int32_t, 8);
DECL_GFX_PREF(Once, "gfx.touch.resample.min-delta", TouchResampleMinDelta, int32_t, 2);
DECL_GFX_PREF(Once, "gfx.touch.resample.old-touch-threshold",TouchResampleOldTouchThreshold, int32_t, 17);
DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust", TouchVsyncSampleAdjust, int32_t, 5);
DECL_GFX_PREF(Live, "gfx.vsync.collect-scroll-transforms", CollectScrollTransforms, bool, false);