From 1ff245b1819edbd39de17cdea0f2561d12188513 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Tue, 23 Aug 2016 15:18:55 -0700 Subject: [PATCH] Bug 1259571 - Reduce tearing with basic layers on Windows r=dvander --HG-- rename : gfx/thebes/DeviceManagerD3D11.cpp => gfx/thebes/DeviceManagerDx.cpp rename : gfx/thebes/DeviceManagerD3D11.h => gfx/thebes/DeviceManagerDx.h --- dom/media/platforms/wmf/DXVA2Manager.cpp | 4 +- dom/plugins/ipc/D3D11SurfaceHolder.cpp | 6 +- dom/plugins/ipc/PluginInstanceParent.cpp | 6 +- gfx/config/gfxFeature.h | 3 +- gfx/gl/GLScreenBuffer.cpp | 4 +- gfx/gl/SharedSurfaceANGLE.cpp | 6 +- gfx/gl/SharedSurfaceD3D11Interop.cpp | 4 +- gfx/ipc/GPUChild.cpp | 2 +- gfx/ipc/GPUParent.cpp | 10 +- gfx/layers/Compositor.h | 4 + gfx/layers/IMFYCbCrImage.cpp | 4 +- gfx/layers/basic/BasicCompositor.cpp | 57 ++++++++- gfx/layers/basic/BasicCompositor.h | 12 ++ gfx/layers/client/ClientLayerManager.cpp | 4 +- gfx/layers/client/TextureClient.cpp | 6 +- gfx/layers/d3d11/CompositorD3D11.cpp | 12 +- gfx/layers/d3d11/TextureD3D11.cpp | 12 +- gfx/layers/ipc/CompositorBridgeParent.cpp | 28 +++++ gfx/layers/ipc/CompositorBridgeParent.h | 2 + ...ceManagerD3D11.cpp => DeviceManagerDx.cpp} | 119 +++++++++++++----- ...DeviceManagerD3D11.h => DeviceManagerDx.h} | 20 +-- gfx/thebes/gfxContext.cpp | 4 +- gfx/thebes/gfxWindowsPlatform.cpp | 33 +++-- gfx/thebes/gfxWindowsPlatform.h | 5 +- gfx/thebes/moz.build | 4 +- gfx/vr/gfxVROculus.cpp | 4 +- widget/CompositorWidget.h | 10 ++ widget/windows/GfxInfo.cpp | 4 +- widget/windows/WinCompositorWidget.cpp | 50 ++++++++ widget/windows/WinCompositorWidget.h | 4 + widget/windows/moz.build | 2 +- widget/windows/nsWindow.cpp | 4 +- 32 files changed, 346 insertions(+), 103 deletions(-) rename gfx/thebes/{DeviceManagerD3D11.cpp => DeviceManagerDx.cpp} (84%) rename gfx/thebes/{DeviceManagerD3D11.h => DeviceManagerDx.h} (88%) diff --git a/dom/media/platforms/wmf/DXVA2Manager.cpp b/dom/media/platforms/wmf/DXVA2Manager.cpp index 1553f19828c6..a1e86d0d040f 100644 --- a/dom/media/platforms/wmf/DXVA2Manager.cpp +++ b/dom/media/platforms/wmf/DXVA2Manager.cpp @@ -10,7 +10,7 @@ #include "ImageContainer.h" #include "gfxWindowsPlatform.h" #include "D3D9SurfaceImage.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/D3D11ShareHandleImage.h" #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/Telemetry.h" @@ -630,7 +630,7 @@ D3D11DXVA2Manager::Init(nsACString& aFailureReason) return E_FAIL; } - mDevice = gfx::DeviceManagerD3D11::Get()->CreateDecoderDevice(); + mDevice = gfx::DeviceManagerDx::Get()->CreateDecoderDevice(); if (!mDevice) { aFailureReason.AssignLiteral("Failed to create D3D11 device for decoder"); return E_FAIL; diff --git a/dom/plugins/ipc/D3D11SurfaceHolder.cpp b/dom/plugins/ipc/D3D11SurfaceHolder.cpp index 51bf63e04b7a..6e5ee52088cc 100644 --- a/dom/plugins/ipc/D3D11SurfaceHolder.cpp +++ b/dom/plugins/ipc/D3D11SurfaceHolder.cpp @@ -5,7 +5,7 @@ #include "nsDebug.h" #include "D3D11SurfaceHolder.h" #include "mozilla/gfx/2D.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/TextureD3D11.h" #include @@ -18,7 +18,7 @@ using namespace mozilla::layers; D3D11SurfaceHolder::D3D11SurfaceHolder(ID3D11Texture2D* back, SurfaceFormat format, const IntSize& size) - : mDevice11(DeviceManagerD3D11::Get()->GetContentDevice()), + : mDevice11(DeviceManagerDx::Get()->GetContentDevice()), mBack(back), mFormat(format), mSize(size) @@ -33,7 +33,7 @@ bool D3D11SurfaceHolder::IsValid() { // If a TDR occurred, platform devices will be recreated. - if (DeviceManagerD3D11::Get()->GetContentDevice() != mDevice11) { + if (DeviceManagerDx::Get()->GetContentDevice() != mDevice11) { return false; } return true; diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 9c833c3ac593..b7300574bd16 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -45,7 +45,7 @@ #include "mozilla/layers/ImageBridgeChild.h" #if defined(XP_WIN) # include "mozilla/layers/D3D11ShareHandleImage.h" -# include "mozilla/gfx/DeviceManagerD3D11.h" +# include "mozilla/gfx/DeviceManagerDx.h" # include "mozilla/layers/TextureD3D11.h" #endif @@ -401,7 +401,7 @@ PluginInstanceParent::AnswerNPN_GetValue_PreferredDXGIAdapter(DxgiAdapterDesc* a return false; } - RefPtr device = DeviceManagerD3D11::Get()->GetContentDevice(); + RefPtr device = DeviceManagerDx::Get()->GetContentDevice(); if (!device) { return false; } @@ -682,7 +682,7 @@ PluginInstanceParent::RecvInitDXGISurface(const gfx::SurfaceFormat& format, return true; } - RefPtr d3d11 = DeviceManagerD3D11::Get()->GetContentDevice(); + RefPtr d3d11 = DeviceManagerDx::Get()->GetContentDevice(); if (!d3d11) { return true; } diff --git a/gfx/config/gfxFeature.h b/gfx/config/gfxFeature.h index e63bde6fcfd1..7e7734f6e581 100644 --- a/gfx/config/gfxFeature.h +++ b/gfx/config/gfxFeature.h @@ -22,7 +22,8 @@ namespace gfx { _(D3D9_COMPOSITING, Feature, "Direct3D9 Compositing") \ _(OPENGL_COMPOSITING, Feature, "OpenGL Compositing") \ _(DIRECT2D, Feature, "Direct2D") \ - _(D3D11_HW_ANGLE, Feature, "Direct3D11 hardware ANGLE") \ + _(D3D11_HW_ANGLE, Feature, "Direct3D11 hardware ANGLE") \ + _(DIRECT_DRAW, Feature, "DirectDraw") \ _(GPU_PROCESS, Feature, "GPU Process") \ /* Add new entries above this comment */ diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index 962688371725..a1d389c01b70 100755 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -21,7 +21,7 @@ #ifdef XP_WIN #include "SharedSurfaceANGLE.h" // for SurfaceFactory_ANGLEShareHandle #include "SharedSurfaceD3D11Interop.h" // for SurfaceFactory_D3D11Interop -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #endif #ifdef MOZ_WIDGET_GONK @@ -108,7 +108,7 @@ GLScreenBuffer::CreateFactory(GLContext* gl, #ifdef XP_WIN // Enable surface sharing only if ANGLE and compositing devices // are both WARP or both not WARP - gfx::DeviceManagerD3D11* dm = gfx::DeviceManagerD3D11::Get(); + gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get(); if (gl->IsANGLE() && (gl->IsWARP() == dm->IsWARP()) && dm->TextureSharingWorks()) diff --git a/gfx/gl/SharedSurfaceANGLE.cpp b/gfx/gl/SharedSurfaceANGLE.cpp index 1cbebfc94d9d..e499a14ccaa7 100644 --- a/gfx/gl/SharedSurfaceANGLE.cpp +++ b/gfx/gl/SharedSurfaceANGLE.cpp @@ -8,7 +8,7 @@ #include #include "GLContextEGL.h" #include "GLLibraryEGL.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc namespace mozilla { @@ -198,7 +198,7 @@ public: } RefPtr device = - gfx::DeviceManagerD3D11::Get()->GetContentDevice(); + gfx::DeviceManagerDx::Get()->GetContentDevice(); if (!device) { return; } @@ -255,7 +255,7 @@ SharedSurface_ANGLEShareHandle::ReadbackBySharedHandle(gfx::DataSourceSurface* o MOZ_ASSERT(out_surface); RefPtr device = - gfx::DeviceManagerD3D11::Get()->GetContentDevice(); + gfx::DeviceManagerDx::Get()->GetContentDevice(); if (!device) { return false; } diff --git a/gfx/gl/SharedSurfaceD3D11Interop.cpp b/gfx/gl/SharedSurfaceD3D11Interop.cpp index 2690292e4bc0..f5721928a576 100644 --- a/gfx/gl/SharedSurfaceD3D11Interop.cpp +++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp @@ -10,7 +10,7 @@ #include "GLContext.h" #include "WGLLibrary.h" #include "nsPrintfCString.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" namespace mozilla { namespace gl { @@ -128,7 +128,7 @@ public: { MOZ_ASSERT(wgl->HasDXInterop2()); - const RefPtr d3d = gfx::DeviceManagerD3D11::Get()->GetContentDevice(); + const RefPtr d3d = gfx::DeviceManagerDx::Get()->GetContentDevice(); if (!d3d) { gfxCriticalNote << "DXInterop2Device::Open: Failed to create D3D11 device."; return nullptr; diff --git a/gfx/ipc/GPUChild.cpp b/gfx/ipc/GPUChild.cpp index c0da6523c783..4c3fac55a0d6 100644 --- a/gfx/ipc/GPUChild.cpp +++ b/gfx/ipc/GPUChild.cpp @@ -9,7 +9,7 @@ #include "GPUProcessHost.h" #include "mozilla/gfx/gfxVars.h" #if defined(XP_WIN) -# include "mozilla/gfx/DeviceManagerD3D11.h" +# include "mozilla/gfx/DeviceManagerDx.h" #endif namespace mozilla { diff --git a/gfx/ipc/GPUParent.cpp b/gfx/ipc/GPUParent.cpp index c1c118ff08cf..a9a58861eedc 100644 --- a/gfx/ipc/GPUParent.cpp +++ b/gfx/ipc/GPUParent.cpp @@ -20,7 +20,7 @@ #include "VsyncBridgeParent.h" #if defined(XP_WIN) # include "DeviceManagerD3D9.h" -# include "mozilla/gfx/DeviceManagerD3D11.h" +# include "mozilla/gfx/DeviceManagerDx.h" #endif namespace mozilla { @@ -54,7 +54,7 @@ GPUParent::Init(base::ProcessId aParentPid, gfxVars::Initialize(); gfxPlatform::InitNullMetadata(); #if defined(XP_WIN) - DeviceManagerD3D11::Init(); + DeviceManagerDx::Init(); DeviceManagerD3D9::Init(); #endif if (NS_FAILED(NS_InitMinimalXPCOM())) { @@ -88,7 +88,7 @@ GPUParent::RecvInit(nsTArray&& prefs, #if defined(XP_WIN) if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { - DeviceManagerD3D11::Get()->CreateCompositorDevices(); + DeviceManagerDx::Get()->CreateCompositorDevices(); } #endif @@ -165,7 +165,7 @@ GPUParent::RecvGetDeviceStatus(GPUDeviceData* aOut) CopyFeatureChange(Feature::OPENGL_COMPOSITING, &aOut->oglCompositing()); #if defined(XP_WIN) - if (DeviceManagerD3D11* dm = DeviceManagerD3D11::Get()) { + if (DeviceManagerDx* dm = DeviceManagerDx::Get()) { dm->ExportDeviceInfo(&aOut->d3d11Device()); } #endif @@ -241,7 +241,7 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy) } CompositorThreadHolder::Shutdown(); #if defined(XP_WIN) - DeviceManagerD3D11::Shutdown(); + DeviceManagerDx::Shutdown(); DeviceManagerD3D9::Shutdown(); #endif gfxVars::Shutdown(); diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 13be8aa8f635..f67532990b38 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -481,6 +481,10 @@ public: virtual void ForcePresent() { } + virtual bool IsPendingComposite() { return false; } + + virtual void FinishPendingComposite() {} + widget::CompositorWidget* GetWidget() const { return mWidget; } virtual bool HasImageHostOverlays() { return false; } diff --git a/gfx/layers/IMFYCbCrImage.cpp b/gfx/layers/IMFYCbCrImage.cpp index e55e208b1b54..21c5d86fcc53 100644 --- a/gfx/layers/IMFYCbCrImage.cpp +++ b/gfx/layers/IMFYCbCrImage.cpp @@ -8,7 +8,7 @@ #include "mozilla/layers/TextureD3D11.h" #include "mozilla/layers/CompositableClient.h" #include "mozilla/layers/CompositableForwarder.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/gfx/Types.h" #include "mozilla/layers/TextureClient.h" #include "d3d9.h" @@ -227,7 +227,7 @@ IMFYCbCrImage::GetTextureClient(CompositableClient* aClient) } RefPtr device = - gfx::DeviceManagerD3D11::Get()->GetContentDevice(); + gfx::DeviceManagerDx::Get()->GetContentDevice(); LayersBackend backend = aClient->GetForwarder()->GetCompositorBackendType(); if (!device || backend != LayersBackend::LAYERS_D3D11) { diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index f941cc3dafe9..921aa9e3beb8 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -201,6 +201,7 @@ public: BasicCompositor::BasicCompositor(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget) : Compositor(aWidget, aParent) , mDidExternalComposition(false) + , mIsPendingEndRemoteDrawing(false) { MOZ_COUNT_CTOR(BasicCompositor); @@ -236,6 +237,11 @@ BasicCompositingRenderTarget::BindRenderTarget() void BasicCompositor::DetachWidget() { if (mWidget) { + if (mIsPendingEndRemoteDrawing) { + // Force to end previous remote drawing. + TryToEndRemoteDrawing(/* aForceToEnd */ true); + MOZ_ASSERT(!mIsPendingEndRemoteDrawing); + } mWidget->CleanupRemoteDrawing(); } Compositor::DetachWidget(); @@ -765,6 +771,12 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, gfx::IntRect *aClipRectOut /* = nullptr */, gfx::IntRect *aRenderBoundsOut /* = nullptr */) { + if (mIsPendingEndRemoteDrawing) { + // Force to end previous remote drawing. + TryToEndRemoteDrawing(/* aForceToEnd */ true); + MOZ_ASSERT(!mIsPendingEndRemoteDrawing); + } + LayoutDeviceIntRect intRect(LayoutDeviceIntPoint(), mWidget->GetClientSize()); IntRect rect = IntRect(0, 0, intRect.width, intRect.height); @@ -883,6 +895,29 @@ BasicCompositor::EndFrame() // Pop aInvalidregion mRenderTarget->mDrawTarget->PopClip(); + TryToEndRemoteDrawing(); +} + +void +BasicCompositor::TryToEndRemoteDrawing(bool aForceToEnd) +{ + if (mIsDestroyed || !mRenderTarget) { + return; + } + + // It it is not a good timing for EndRemoteDrawing, defter to call it. + if (!aForceToEnd && !mTarget && NeedsToDeferEndRemoteDrawing()) { + mIsPendingEndRemoteDrawing = true; + + const uint32_t retryMs = 2; + RefPtr self = this; + RefPtr runnable = NS_NewRunnableFunction([self]() { + self->TryToEndRemoteDrawing(); + }); + MessageLoop::current()->PostDelayedTask(runnable.forget(), retryMs); + return; + } + if (mRenderTarget->mDrawTarget != mDrawTarget) { // Note: Most platforms require us to buffer drawing to the widget surface. // That's why we don't draw to mDrawTarget directly. @@ -907,12 +942,32 @@ BasicCompositor::EndFrame() } } - if (!mTarget) { + if (aForceToEnd || !mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); } mDrawTarget = nullptr; mRenderTarget = nullptr; + mIsPendingEndRemoteDrawing = false; +} + +bool +BasicCompositor::NeedsToDeferEndRemoteDrawing() +{ + MOZ_ASSERT(mDrawTarget); + MOZ_ASSERT(mRenderTarget); + + if (mTarget || mRenderTarget->mDrawTarget == mDrawTarget) { + return false; + } + + return mWidget->NeedsToDeferEndRemoteDrawing(); +} + +void +BasicCompositor::FinishPendingComposite() +{ + TryToEndRemoteDrawing(/* aForceToEnd */ true); } void diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index ef07e4857d1c..73f3e82c36ee 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -128,8 +128,19 @@ public: gfx::DrawTarget *GetDrawTarget() { return mDrawTarget; } + virtual bool IsPendingComposite() override + { + return mIsPendingEndRemoteDrawing; + } + + virtual void FinishPendingComposite() override; + private: + void TryToEndRemoteDrawing(bool aForceToEnd = false); + + bool NeedsToDeferEndRemoteDrawing(); + // The final destination surface RefPtr mDrawTarget; // The current render target for drawing @@ -140,6 +151,7 @@ private: bool mDidExternalComposition; uint32_t mMaxTextureSize; + bool mIsPendingEndRemoteDrawing; }; BasicCompositor* AssertBasicCompositor(Compositor* aCompositor); diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index bf898b19aa8a..68d5d2ca48d9 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -35,7 +35,7 @@ #include "LayerMetricsWrapper.h" #endif #ifdef XP_WIN -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #endif namespace mozilla { @@ -783,7 +783,7 @@ ClientLayerManager::GetBackendName(nsAString& aName) case LayersBackend::LAYERS_D3D9: aName.AssignLiteral("Direct3D 9"); return; case LayersBackend::LAYERS_D3D11: { #ifdef XP_WIN - if (DeviceManagerD3D11::Get()->IsWARP()) { + if (DeviceManagerDx::Get()->IsWARP()) { aName.AssignLiteral("Direct3D 11 WARP"); } else { aName.AssignLiteral("Direct3D 11"); diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 93dce84505f2..63fd11eae3ba 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -35,7 +35,7 @@ #ifdef XP_WIN #include "DeviceManagerD3D9.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/TextureD3D9.h" #include "mozilla/layers/TextureD3D11.h" #include "mozilla/layers/TextureDIB.h" @@ -1044,7 +1044,7 @@ TextureClient::CreateForDrawing(TextureForwarder* aAllocator, (moz2DBackend == gfx::BackendType::DIRECT2D || moz2DBackend == gfx::BackendType::DIRECT2D1_1 || (!!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT) && - DeviceManagerD3D11::Get()->GetContentDevice())) && + DeviceManagerDx::Get()->GetContentDevice())) && aSize.width <= maxTextureSize && aSize.height <= maxTextureSize) { @@ -1148,7 +1148,7 @@ TextureClient::CreateFromSurface(TextureForwarder* aAllocator, (moz2DBackend == gfx::BackendType::DIRECT2D || moz2DBackend == gfx::BackendType::DIRECT2D1_1 || (!!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT) && - DeviceManagerD3D11::Get()->GetContentDevice())) && + DeviceManagerDx::Get()->GetContentDevice())) && size.width <= maxTextureSize && size.height <= maxTextureSize) { diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index 20cab7b6f5b9..f6e289254543 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -11,7 +11,7 @@ #include "gfxWindowsPlatform.h" #include "nsIWidget.h" #include "mozilla/gfx/D3D11Checks.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/ImageHost.h" #include "mozilla/layers/ContentHost.h" #include "mozilla/layers/Effects.h" @@ -182,7 +182,7 @@ CompositorD3D11::Initialize(nsCString* const out_failureReason) HRESULT hr; - mDevice = DeviceManagerD3D11::Get()->GetCompositorDevice(); + mDevice = DeviceManagerDx::Get()->GetCompositorDevice(); if (!mDevice) { *out_failureReason = "FEATURE_FAILURE_D3D11_NO_DEVICE"; return false; @@ -422,7 +422,7 @@ CanUsePartialPresents(ID3D11Device* aDevice) if (gfxPrefs::PartialPresent() < 0) { return false; } - if (DeviceManagerD3D11::Get()->IsWARP()) { + if (DeviceManagerDx::Get()->IsWARP()) { return true; } @@ -1088,7 +1088,7 @@ CompositorD3D11::EndFrame() UINT presentInterval = 0; - bool isWARP = DeviceManagerD3D11::Get()->IsWARP(); + bool isWARP = DeviceManagerDx::Get()->IsWARP(); if (isWARP) { // When we're using WARP we cannot present immediately as it causes us // to tear when rendering. When not using WARP it appears the DWM takes @@ -1323,7 +1323,7 @@ bool DeviceAttachmentsD3D11::InitSyncObject() { // Sync object is not supported on WARP. - if (DeviceManagerD3D11::Get()->IsWARP()) { + if (DeviceManagerDx::Get()->IsWARP()) { return true; } @@ -1518,7 +1518,7 @@ CompositorD3D11::HandleError(HRESULT hr, Severity aSeverity) MOZ_CRASH("GFX: Unrecoverable D3D11 error"); } - if (mDevice && DeviceManagerD3D11::Get()->GetCompositorDevice() != mDevice) { + if (mDevice && DeviceManagerDx::Get()->GetCompositorDevice() != mDevice) { gfxCriticalNote << "Out of sync D3D11 devices in HandleError, " << (int)mVerifyBuffersFailed; } diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index de0e9052fb35..dce0696ac55b 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -11,7 +11,7 @@ #include "gfx2DGlue.h" #include "gfxPrefs.h" #include "ReadbackManagerD3D11.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/gfx/Logging.h" namespace mozilla { @@ -365,7 +365,7 @@ D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, SourceSurface* aS // to use from any thread. RefPtr device = aDevice; if (!device) { - device = DeviceManagerD3D11::Get()->GetContentDevice(); + device = DeviceManagerDx::Get()->GetContentDevice(); if (!device) { return nullptr; } @@ -696,7 +696,7 @@ DXGITextureHostD3D11::GetDevice() return nullptr; } - return DeviceManagerD3D11::Get()->GetCompositorDevice(); + return DeviceManagerDx::Get()->GetCompositorDevice(); } static CompositorD3D11* AssertD3D11Compositor(Compositor* aCompositor) @@ -832,7 +832,7 @@ DXGIYCbCrTextureHostD3D11::GetDevice() return nullptr; } - return DeviceManagerD3D11::Get()->GetCompositorDevice(); + return DeviceManagerDx::Get()->GetCompositorDevice(); } void @@ -1156,7 +1156,7 @@ SyncObjectD3D11::FinalizeFrame() HRESULT hr; if (!mD3D11Texture && mD3D11SyncedTextures.size()) { - RefPtr device = DeviceManagerD3D11::Get()->GetContentDevice(); + RefPtr device = DeviceManagerDx::Get()->GetContentDevice(); hr = device->OpenSharedResource(mHandle, __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture)); @@ -1199,7 +1199,7 @@ SyncObjectD3D11::FinalizeFrame() box.front = box.top = box.left = 0; box.back = box.bottom = box.right = 1; - RefPtr dev = DeviceManagerD3D11::Get()->GetContentDevice(); + RefPtr dev = DeviceManagerDx::Get()->GetContentDevice(); if (!dev) { if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) { return; diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 09a739f488a8..d528772ffdfe 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -481,6 +481,14 @@ CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp) return; } + MOZ_ASSERT(mCompositorBridgeParent); + if (!mAsapScheduling && mCompositorBridgeParent->IsPendingComposite()) { + // If previous composite is still on going, finish it and does a next + // composite in a next vsync. + mCompositorBridgeParent->FinishPendingComposite(); + return; + } + DispatchTouchEvents(aVsyncTimestamp); DispatchVREvents(aVsyncTimestamp); @@ -1956,6 +1964,26 @@ CompositorBridgeParent::DeallocPCompositorWidgetParent(PCompositorWidgetParent* #endif } +bool +CompositorBridgeParent::IsPendingComposite() +{ + MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); + if (!mCompositor) { + return false; + } + return mCompositor->IsPendingComposite(); +} + +void +CompositorBridgeParent::FinishPendingComposite() +{ + MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); + if (!mCompositor) { + return; + } + return mCompositor->FinishPendingComposite(); +} + /** * This class handles layer updates pushed directly from child processes to * the compositor thread. It's associated with a CompositorBridgeParent on the diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h index f70f10354b39..734b8f25f933 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -557,6 +557,8 @@ protected: void ForceComposition(); void CancelCurrentCompositeTask(); void Invalidate(); + bool IsPendingComposite(); + void FinishPendingComposite(); RefPtr NewCompositor(const nsTArray& aBackendHints); void ResetCompositorTask(const nsTArray& aBackendHints, diff --git a/gfx/thebes/DeviceManagerD3D11.cpp b/gfx/thebes/DeviceManagerDx.cpp similarity index 84% rename from gfx/thebes/DeviceManagerD3D11.cpp rename to gfx/thebes/DeviceManagerDx.cpp index dfdfc63a4c9f..e5370ce60e91 100644 --- a/gfx/thebes/DeviceManagerD3D11.cpp +++ b/gfx/thebes/DeviceManagerDx.cpp @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "DeviceManagerD3D11.h" +#include "DeviceManagerDx.h" #include "D3D11Checks.h" #include "gfxConfig.h" #include "GfxDriverInfo.h" @@ -14,34 +14,41 @@ #include "mozilla/WindowsVersion.h" #include "mozilla/gfx/GraphicsMessages.h" #include "mozilla/gfx/Logging.h" +#include "mozilla/layers/CompositorThread.h" #include "nsIGfxInfo.h" #include +#include namespace mozilla { namespace gfx { using namespace mozilla::widget; -StaticAutoPtr DeviceManagerD3D11::sInstance; +StaticAutoPtr DeviceManagerDx::sInstance; // We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h, // since it doesn't include d3d11.h, so we use a static here. It should only // be used within InitializeD3D11. decltype(D3D11CreateDevice)* sD3D11CreateDeviceFn = nullptr; +// We don't have access to the DirectDrawCreateEx type in gfxWindowsPlatform.h, +// since it doesn't include ddraw.h, so we use a static here. It should only +// be used within InitializeDirectDrawConfig. +decltype(DirectDrawCreateEx)* sDirectDrawCreateExFn = nullptr; + /* static */ void -DeviceManagerD3D11::Init() +DeviceManagerDx::Init() { - sInstance = new DeviceManagerD3D11(); + sInstance = new DeviceManagerDx(); } /* static */ void -DeviceManagerD3D11::Shutdown() +DeviceManagerDx::Shutdown() { sInstance = nullptr; } -DeviceManagerD3D11::DeviceManagerD3D11() +DeviceManagerDx::DeviceManagerDx() : mDeviceLock("gfxWindowsPlatform.mDeviceLock"), mCompositorDeviceSupportsVideo(false) { @@ -55,7 +62,7 @@ DeviceManagerD3D11::DeviceManagerD3D11() } bool -DeviceManagerD3D11::LoadD3D11() +DeviceManagerDx::LoadD3D11() { FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING); MOZ_ASSERT(d3d11.IsEnabled()); @@ -85,7 +92,7 @@ DeviceManagerD3D11::LoadD3D11() } void -DeviceManagerD3D11::ReleaseD3D11() +DeviceManagerDx::ReleaseD3D11() { MOZ_ASSERT(!mCompositorDevice); MOZ_ASSERT(!mContentDevice); @@ -103,7 +110,7 @@ ProcessOwnsCompositor() } bool -DeviceManagerD3D11::CreateCompositorDevices() +DeviceManagerDx::CreateCompositorDevices() { MOZ_ASSERT(ProcessOwnsCompositor()); @@ -132,7 +139,7 @@ DeviceManagerD3D11::CreateCompositorDevices() } void -DeviceManagerD3D11::ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus) +DeviceManagerDx::ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus) { MOZ_ASSERT(!ProcessOwnsCompositor()); @@ -140,10 +147,10 @@ DeviceManagerD3D11::ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus) } void -DeviceManagerD3D11::ExportDeviceInfo(D3D11DeviceStatus* aOut) +DeviceManagerDx::ExportDeviceInfo(D3D11DeviceStatus* aOut) { // Even though the parent process might not own the compositor, we still - // populate DeviceManagerD3D11 with device statistics (for simplicity). + // populate DeviceManagerDx with device statistics (for simplicity). // That means it still gets queried for compositor information. MOZ_ASSERT(XRE_IsParentProcess() || XRE_GetProcessType() == GeckoProcessType_GPU); @@ -153,7 +160,7 @@ DeviceManagerD3D11::ExportDeviceInfo(D3D11DeviceStatus* aOut) } void -DeviceManagerD3D11::CreateContentDevices() +DeviceManagerDx::CreateContentDevices() { MOZ_ASSERT(gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)); @@ -171,7 +178,7 @@ DeviceManagerD3D11::CreateContentDevices() } IDXGIAdapter1* -DeviceManagerD3D11::GetDXGIAdapter() +DeviceManagerDx::GetDXGIAdapter() { if (mAdapter) { return mAdapter; @@ -245,7 +252,7 @@ DeviceManagerD3D11::GetDXGIAdapter() } bool -DeviceManagerD3D11::CreateCompositorDeviceHelper( +DeviceManagerDx::CreateCompositorDeviceHelper( FeatureState& aD3d11, IDXGIAdapter1* aAdapter, bool aAttemptVideoSupport, RefPtr& aOutDevice) { // Check if a failure was injected for testing. @@ -294,7 +301,7 @@ DeviceManagerD3D11::CreateCompositorDeviceHelper( } void -DeviceManagerD3D11::CreateCompositorDevice(FeatureState& d3d11) +DeviceManagerDx::CreateCompositorDevice(FeatureState& d3d11) { if (gfxPrefs::LayersD3D11ForceWARP()) { CreateWARPCompositorDevice(); @@ -356,7 +363,7 @@ DeviceManagerD3D11::CreateCompositorDevice(FeatureState& d3d11) } bool -DeviceManagerD3D11::CreateDevice(IDXGIAdapter* aAdapter, +DeviceManagerDx::CreateDevice(IDXGIAdapter* aAdapter, D3D_DRIVER_TYPE aDriverType, UINT aFlags, HRESULT& aResOut, @@ -375,7 +382,7 @@ DeviceManagerD3D11::CreateDevice(IDXGIAdapter* aAdapter, } void -DeviceManagerD3D11::CreateWARPCompositorDevice() +DeviceManagerDx::CreateWARPCompositorDevice() { ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP()); FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING); @@ -426,7 +433,7 @@ DeviceManagerD3D11::CreateWARPCompositorDevice() } FeatureStatus -DeviceManagerD3D11::CreateContentDevice() +DeviceManagerDx::CreateContentDevice() { RefPtr adapter; if (!mDeviceStatus->isWARP()) { @@ -486,7 +493,7 @@ DeviceManagerD3D11::CreateContentDevice() } RefPtr -DeviceManagerD3D11::CreateDecoderDevice() +DeviceManagerDx::CreateDecoderDevice() { if (mCompositorDevice && mCompositorDeviceSupportsVideo && !mDecoderDevice) { mDecoderDevice = mCompositorDevice; @@ -535,7 +542,7 @@ DeviceManagerD3D11::CreateDecoderDevice() } void -DeviceManagerD3D11::ResetDevices() +DeviceManagerDx::ResetDevices() { MutexAutoLock lock(mDeviceLock); @@ -546,7 +553,7 @@ DeviceManagerD3D11::ResetDevices() } bool -DeviceManagerD3D11::ContentAdapterIsParentAdapter(ID3D11Device* device) +DeviceManagerDx::ContentAdapterIsParentAdapter(ID3D11Device* device) { DXGI_ADAPTER_DESC desc; if (!D3D11Checks::GetDxgiDesc(device, &desc)) { @@ -609,7 +616,7 @@ DidDeviceReset(RefPtr aDevice, DeviceResetReason* aOutReason) } bool -DeviceManagerD3D11::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason) +DeviceManagerDx::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason) { // Note: this can be called off the main thread, so we need to use // our threadsafe getters. @@ -622,7 +629,7 @@ DeviceManagerD3D11::GetAnyDeviceRemovedReason(DeviceResetReason* aOutReason) } void -DeviceManagerD3D11::DisableD3D11AfterCrash() +DeviceManagerDx::DisableD3D11AfterCrash() { gfxConfig::Disable(Feature::D3D11_COMPOSITING, FeatureStatus::CrashedInHandler, @@ -632,21 +639,21 @@ DeviceManagerD3D11::DisableD3D11AfterCrash() } RefPtr -DeviceManagerD3D11::GetCompositorDevice() +DeviceManagerDx::GetCompositorDevice() { MutexAutoLock lock(mDeviceLock); return mCompositorDevice; } RefPtr -DeviceManagerD3D11::GetContentDevice() +DeviceManagerDx::GetContentDevice() { MutexAutoLock lock(mDeviceLock); return mContentDevice; } unsigned -DeviceManagerD3D11::GetCompositorFeatureLevel() const +DeviceManagerDx::GetCompositorFeatureLevel() const { if (!mDeviceStatus) { return 0; @@ -655,7 +662,7 @@ DeviceManagerD3D11::GetCompositorFeatureLevel() const } bool -DeviceManagerD3D11::TextureSharingWorks() +DeviceManagerDx::TextureSharingWorks() { MutexAutoLock lock(mDeviceLock); if (!mDeviceStatus) { @@ -665,7 +672,7 @@ DeviceManagerD3D11::TextureSharingWorks() } bool -DeviceManagerD3D11::IsWARP() +DeviceManagerDx::IsWARP() { MutexAutoLock lock(mDeviceLock); if (!mDeviceStatus) { @@ -674,5 +681,59 @@ DeviceManagerD3D11::IsWARP() return mDeviceStatus->isWARP(); } +void +DeviceManagerDx::InitializeDirectDraw() +{ + MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread()); + + if (mDirectDraw) { + // Already initialized. + return; + } + + FeatureState& ddraw = gfxConfig::GetFeature(Feature::DIRECT_DRAW); + if (!ddraw.IsEnabled()) { + return; + } + + // Check if DirectDraw is available on this system. + mDirectDrawDLL.own(LoadLibrarySystem32(L"ddraw.dll")); + if (!mDirectDrawDLL) { + ddraw.SetFailed(FeatureStatus::Unavailable, "DirectDraw not available on this computer", + NS_LITERAL_CSTRING("FEATURE_FAILURE_DDRAW_LIB")); + return; + } + + sDirectDrawCreateExFn = + (decltype(DirectDrawCreateEx)*)GetProcAddress(mDirectDrawDLL, "DirectDrawCreateEx"); + if (!sDirectDrawCreateExFn) { + ddraw.SetFailed(FeatureStatus::Unavailable, "DirectDraw not available on this computer", + NS_LITERAL_CSTRING("FEATURE_FAILURE_DDRAW_LIB")); + return; + } + + HRESULT hr; + MOZ_SEH_TRY { + hr = sDirectDrawCreateExFn(nullptr, getter_AddRefs(mDirectDraw), IID_IDirectDraw7, nullptr); + } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + ddraw.SetFailed(FeatureStatus::Failed, "Failed to create DirectDraw", + NS_LITERAL_CSTRING("FEATURE_FAILURE_DDRAW_LIB")); + gfxCriticalNote << "DoesCreatingDirectDrawFailed"; + return; + } + if (FAILED(hr)) { + ddraw.SetFailed(FeatureStatus::Failed, "Failed to create DirectDraw", + NS_LITERAL_CSTRING("FEATURE_FAILURE_DDRAW_LIB")); + gfxCriticalNote << "DoesCreatingDirectDrawFailed " << hexa(hr); + return; + } +} + +IDirectDraw7* +DeviceManagerDx::GetDirectDraw() +{ + return mDirectDraw; +} + } // namespace gfx } // namespace mozilla diff --git a/gfx/thebes/DeviceManagerD3D11.h b/gfx/thebes/DeviceManagerDx.h similarity index 88% rename from gfx/thebes/DeviceManagerD3D11.h rename to gfx/thebes/DeviceManagerDx.h index d5f13ff12e83..013facab947b 100644 --- a/gfx/thebes/DeviceManagerD3D11.h +++ b/gfx/thebes/DeviceManagerDx.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef mozilla_gfx_thebes_DeviceManagerD3D11_h -#define mozilla_gfx_thebes_DeviceManagerD3D11_h +#ifndef mozilla_gfx_thebes_DeviceManagerDx_h +#define mozilla_gfx_thebes_DeviceManagerDx_h #include "gfxPlatform.h" #include "gfxTelemetry.h" @@ -31,6 +31,7 @@ #endif struct ID3D11Device; +struct IDirectDraw7; namespace mozilla { class ScopedGfxFeatureReporter; @@ -38,21 +39,22 @@ class ScopedGfxFeatureReporter; namespace gfx { class FeatureState; -class DeviceManagerD3D11 final +class DeviceManagerDx final { public: static void Init(); static void Shutdown(); - DeviceManagerD3D11(); + DeviceManagerDx(); - static DeviceManagerD3D11* Get() { + static DeviceManagerDx* Get() { return sInstance; } RefPtr GetCompositorDevice(); RefPtr GetContentDevice(); RefPtr CreateDecoderDevice(); + IDirectDraw7* GetDirectDraw(); unsigned GetCompositorFeatureLevel() const; bool TextureSharingWorks(); @@ -65,6 +67,7 @@ public: void ExportDeviceInfo(D3D11DeviceStatus* aOut); void ResetDevices(); + void InitializeDirectDraw(); // Call GetDeviceRemovedReason on each device until one returns // a failure. @@ -98,7 +101,7 @@ private: void ReleaseD3D11(); private: - static StaticAutoPtr sInstance; + static StaticAutoPtr sInstance; // This is assigned during device creation. Afterwards, it is released if // devices failed, and "forgotten" if devices succeeded (meaning, we leak @@ -114,9 +117,12 @@ private: bool mCompositorDeviceSupportsVideo; Maybe mDeviceStatus; + + nsModuleHandle mDirectDrawDLL; + RefPtr mDirectDraw; }; } // namespace gfx } // namespace mozilla -#endif // mozilla_gfx_thebes_DeviceManagerD3D11_h +#endif // mozilla_gfx_thebes_DeviceManagerDx_h diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 157954b11b71..2e71fe03730b 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -26,7 +26,7 @@ #if XP_WIN #include "gfxWindowsPlatform.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #endif using namespace mozilla; @@ -1244,7 +1244,7 @@ gfxContext::PushNewDT(gfxContentType content) if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset() #ifdef XP_WIN && !(mDT->GetBackendType() == BackendType::DIRECT2D1_1 && - !DeviceManagerD3D11::Get()->GetContentDevice()) + !DeviceManagerDx::Get()->GetContentDevice()) #endif ) { // If even this fails.. we're most likely just out of memory! diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 49c8fd9f7c38..1fcebf61702b 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -72,7 +72,7 @@ #include "VsyncSource.h" #include "DriverCrashGuard.h" #include "mozilla/dom/ContentParent.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "D3D11Checks.h" using namespace mozilla; @@ -352,7 +352,7 @@ gfxWindowsPlatform::~gfxWindowsPlatform() mozilla::gfx::Factory::D2DCleanup(); DeviceManagerD3D9::Shutdown(); - DeviceManagerD3D11::Shutdown(); + DeviceManagerDx::Shutdown(); /* * Uninitialize COM @@ -382,7 +382,7 @@ gfxWindowsPlatform::InitAcceleration() mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0); mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3); - DeviceManagerD3D11::Init(); + DeviceManagerDx::Init(); DeviceManagerD3D9::Init(); InitializeConfig(); @@ -399,7 +399,7 @@ gfxWindowsPlatform::InitAcceleration() bool gfxWindowsPlatform::CanUseHardwareVideoDecoding() { - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); if (!gfxPrefs::LayersPreferD3D9() && !dm->TextureSharingWorks()) { return false; } @@ -457,7 +457,7 @@ gfxWindowsPlatform::HandleDeviceReset() } // Remove devices and adapters. - DeviceManagerD3D11::Get()->ResetDevices(); + DeviceManagerDx::Get()->ResetDevices(); // Reset local state. Note: we leave feature status variables as-is. They // will be recomputed by InitializeDevices(). @@ -956,7 +956,7 @@ gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason) *aResetReason = DeviceResetReason::OK; } - if (DeviceManagerD3D11::Get()->GetAnyDeviceRemovedReason(&mDeviceResetReason)) { + if (DeviceManagerDx::Get()->GetAnyDeviceRemovedReason(&mDeviceResetReason)) { mHasDeviceReset = true; if (aResetReason) { *aResetReason = mDeviceResetReason; @@ -1403,6 +1403,15 @@ InitializeANGLEConfig() } +void +gfxWindowsPlatform::InitializeDirectDrawConfig() +{ + MOZ_ASSERT(XRE_IsParentProcess()); + + FeatureState& ddraw = gfxConfig::GetFeature(Feature::DIRECT_DRAW); + ddraw.EnableByDefault(); +} + void gfxWindowsPlatform::InitializeConfig() { @@ -1566,7 +1575,7 @@ gfxWindowsPlatform::InitializeD3D11() return; } - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); if (XRE_IsParentProcess()) { if (!dm->CreateCompositorDevices()) { return; @@ -1615,7 +1624,7 @@ gfxWindowsPlatform::InitializeD2D() FeatureState& d2d1 = gfxConfig::GetFeature(Feature::DIRECT2D); - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); // We don't know this value ahead of time, but the user can force-override // it, so we use Disable instead of SetFailed. @@ -2002,7 +2011,7 @@ gfxWindowsPlatform::ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData gfxConfig::ImportChange(Feature::D3D11_COMPOSITING, aData.d3d11Compositing()); gfxConfig::ImportChange(Feature::D3D9_COMPOSITING, aData.d3d9Compositing()); - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { dm->ImportDeviceInfo(aData.d3d11Device()); } else { @@ -2038,7 +2047,7 @@ gfxWindowsPlatform::ImportContentDeviceData(const mozilla::gfx::ContentDeviceDat gfxConfig::Inherit(Feature::DIRECT2D, prefs.useD2D1()); if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); dm->ImportDeviceInfo(aData.d3d11()); } } @@ -2057,7 +2066,7 @@ gfxWindowsPlatform::BuildContentDeviceData(ContentDeviceData* aOut) aOut->prefs().useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D); if (d3d11.IsEnabled()) { - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); dm->ExportDeviceInfo(&aOut->d3d11()); } } @@ -2065,7 +2074,7 @@ gfxWindowsPlatform::BuildContentDeviceData(ContentDeviceData* aOut) bool gfxWindowsPlatform::SupportsPluginDirectDXGIDrawing() { - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); if (!dm->GetContentDevice() || !dm->TextureSharingWorks()) { return false; } diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 92413b3caeb1..ed0a405be1fe 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -47,7 +47,7 @@ namespace mozilla { namespace gfx { class DrawTarget; class FeatureState; -class DeviceManagerD3D11; +class DeviceManagerDx; } namespace layers { class DeviceManagerD3D9; @@ -100,7 +100,7 @@ struct ClearTypeParameterInfo { class gfxWindowsPlatform : public gfxPlatform { - friend class mozilla::gfx::DeviceManagerD3D11; + friend class mozilla::gfx::DeviceManagerDx; public: enum TextRenderingMode { @@ -275,6 +275,7 @@ private: void InitializeD3D9Config(); void InitializeD3D11Config(); void InitializeD2DConfig(); + void InitializeDirectDrawConfig(); RefPtr mDWriteFactory; RefPtr mRenderingParams[TEXT_RENDERING_COUNT]; diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build index d6ffbc04e263..488ea8391189 100644 --- a/gfx/thebes/moz.build +++ b/gfx/thebes/moz.build @@ -52,7 +52,7 @@ EXPORTS += [ EXPORTS.mozilla.gfx += [ 'D3D11Checks.h', - 'DeviceManagerD3D11.h', + 'DeviceManagerDx.h', 'PrintTarget.h', 'PrintTargetThebes.h', ] @@ -237,7 +237,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': UNIFIED_SOURCES += [ 'D3D11Checks.cpp', - 'DeviceManagerD3D11.cpp', + 'DeviceManagerDx.cpp', ] # We prefer to use ICU for normalization functions, but currently it is only diff --git a/gfx/vr/gfxVROculus.cpp b/gfx/vr/gfxVROculus.cpp index 9fef8f11cbe3..5adf6f71cd63 100644 --- a/gfx/vr/gfxVROculus.cpp +++ b/gfx/vr/gfxVROculus.cpp @@ -18,7 +18,7 @@ #include "mozilla/DebugOnly.h" #include "mozilla/Preferences.h" #include "mozilla/TimeStamp.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "ipc/VRLayerParent.h" #include "mozilla/gfx/Quaternion.h" @@ -500,7 +500,7 @@ VRDisplayOculus::StartPresentation() desc.BindFlags = ovrTextureBind_DX_RenderTarget; if (!mDevice) { - mDevice = gfx::DeviceManagerD3D11::Get()->GetCompositorDevice(); + mDevice = gfx::DeviceManagerDx::Get()->GetCompositorDevice(); if (!mDevice) { NS_WARNING("Failed to get a D3D11Device for Oculus"); return; diff --git a/widget/CompositorWidget.h b/widget/CompositorWidget.h index 461c47c7c3e6..53fcda88c946 100644 --- a/widget/CompositorWidget.h +++ b/widget/CompositorWidget.h @@ -136,6 +136,16 @@ public: EndRemoteDrawing(); } + /** + * Return true when it is better to defer EndRemoteDrawing(). + * + * Called by BasicCompositor on the compositor thread for OMTC drawing + * after each composition. + */ + virtual bool NeedsToDeferEndRemoteDrawing() { + return false; + } + /** * Called when shutting down the LayerManager to clean-up any cached resources. * diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp index 87a7bcc7f971..7298c2c956f5 100644 --- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -16,7 +16,7 @@ #include "prprf.h" #include "GfxDriverInfo.h" #include "mozilla/Preferences.h" -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/gfx/Logging.h" #include "nsPrintfCString.h" #include "jsapi.h" @@ -1353,7 +1353,7 @@ GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle aObj) return; } if (d3d11 == gfx::FeatureStatus::Available) { - DeviceManagerD3D11* dm = DeviceManagerD3D11::Get(); + DeviceManagerDx* dm = DeviceManagerDx::Get(); JS::Rooted val(aCx, JS::Int32Value(dm->GetCompositorFeatureLevel())); JS_SetProperty(aCx, obj, "version", val); diff --git a/widget/windows/WinCompositorWidget.cpp b/widget/windows/WinCompositorWidget.cpp index f6269a9b5c46..aa2f155e87e9 100644 --- a/widget/windows/WinCompositorWidget.cpp +++ b/widget/windows/WinCompositorWidget.cpp @@ -4,11 +4,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WinCompositorWidget.h" +#include "gfxPrefs.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/gfx/Point.h" +#include "mozilla/layers/Compositor.h" #include "mozilla/widget/PlatformWidgetTypes.h" #include "nsWindow.h" #include "VsyncDispatcher.h" +#include + namespace mozilla { namespace widget { @@ -23,6 +28,12 @@ WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitDa mLockedBackBufferData(nullptr) { MOZ_ASSERT(mWnd && ::IsWindow(mWnd)); + + // mNotDeferEndRemoteDrawing is set on the main thread during init, + // but is only accessed after on the compositor thread. + mNotDeferEndRemoteDrawing = gfxPrefs::LayersCompositionFrameRate() == 0 || + gfxPlatform::IsInLayoutAsapMode() || + gfxPlatform::ForceSoftwareVsync(); } void @@ -112,6 +123,36 @@ WinCompositorWidget::EndRemoteDrawing() mCompositeDC = nullptr; } +bool +WinCompositorWidget::NeedsToDeferEndRemoteDrawing() +{ + if(mNotDeferEndRemoteDrawing) { + return false; + } + + IDirectDraw7* ddraw = DeviceManagerDx::Get()->GetDirectDraw(); + if (!ddraw) { + return false; + } + + DWORD scanLine = 0; + int height = ::GetSystemMetrics(SM_CYSCREEN); + HRESULT ret = ddraw->GetScanLine(&scanLine); + if (ret == DDERR_VERTICALBLANKINPROGRESS) { + scanLine = 0; + } else if (ret != DD_OK) { + return false; + } + + // Check if there is a risk of tearing with GDI. + if (static_cast(scanLine) > height / 2) { + // No need to defer. + return false; + } + + return true; +} + already_AddRefed WinCompositorWidget::GetBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget, const LayoutDeviceIntRect& aRect, @@ -158,6 +199,15 @@ WinCompositorWidget::EndBackBufferDrawing() return CompositorWidget::EndBackBufferDrawing(); } +bool +WinCompositorWidget::InitCompositor(layers::Compositor* aCompositor) +{ + if (aCompositor->GetBackendType() == layers::LayersBackend::LAYERS_BASIC) { + DeviceManagerDx::Get()->InitializeDirectDraw(); + } + return true; +} + uintptr_t WinCompositorWidget::GetWidgetKey() { diff --git a/widget/windows/WinCompositorWidget.h b/widget/windows/WinCompositorWidget.h index 6146c0da7663..f7dd1ae40c1e 100644 --- a/widget/windows/WinCompositorWidget.h +++ b/widget/windows/WinCompositorWidget.h @@ -49,11 +49,13 @@ public: void PostRender(layers::LayerManagerComposite*) override; already_AddRefed StartRemoteDrawing() override; void EndRemoteDrawing() override; + bool NeedsToDeferEndRemoteDrawing() override; LayoutDeviceIntSize GetClientSize() override; already_AddRefed GetBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget, const LayoutDeviceIntRect& aRect, const LayoutDeviceIntRect& aClearRect) override; already_AddRefed EndBackBufferDrawing() override; + bool InitCompositor(layers::Compositor* aCompositor) override; uintptr_t GetWidgetKey() override; WinCompositorWidget* AsWindows() override { return this; @@ -100,6 +102,8 @@ private: // Locked back buffer of BasicCompositor uint8_t* mLockedBackBufferData; + + bool mNotDeferEndRemoteDrawing; }; } // namespace widget diff --git a/widget/windows/moz.build b/widget/windows/moz.build index 1f286e068075..d4f089eeac0c 100644 --- a/widget/windows/moz.build +++ b/widget/windows/moz.build @@ -61,7 +61,6 @@ UNIFIED_SOURCES += [ 'TaskbarTabPreview.cpp', 'TaskbarWindowPreview.cpp', 'WidgetTraceEvent.cpp', - 'WinCompositorWidget.cpp', 'WindowHook.cpp', 'WinIMEHandler.cpp', 'WinTaskbar.cpp', @@ -75,6 +74,7 @@ SOURCES += [ 'nsBidiKeyboard.cpp', 'nsFilePicker.cpp', 'nsWidgetFactory.cpp', + 'WinCompositorWidget.cpp', 'WindowsUIUtils.cpp', 'WinMouseScrollHandler.cpp', ] diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 6769e8751d22..5c6be94dc4b2 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -201,7 +201,7 @@ #define WM_DPICHANGED 0x02E0 #endif -#include "mozilla/gfx/DeviceManagerD3D11.h" +#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/InputAPZContext.h" #include "mozilla/layers/ScrollInputMethods.h" @@ -7768,7 +7768,7 @@ nsWindow::ComputeShouldAccelerate() // on Windows 7 where presentation fails randomly for windows with drop // shadows. if (mTransparencyMode == eTransparencyTransparent || - (IsPopup() && DeviceManagerD3D11::Get()->IsWARP())) + (IsPopup() && DeviceManagerDx::Get()->IsWARP())) { return false; }