From a450a2754fa36c4e727fa895be5e3520e5b51f71 Mon Sep 17 00:00:00 2001 From: sotaro Date: Thu, 24 Nov 2016 15:48:01 +0900 Subject: [PATCH] Bug 1317935 - Use GetCompositeUntilTime() to trigger next composition r=nical? --- gfx/layers/Compositor.h | 4 +- gfx/layers/composite/CompositableHost.h | 2 + gfx/layers/composite/ImageHost.cpp | 25 +++++++++ gfx/layers/composite/ImageHost.h | 2 + gfx/layers/ipc/CompositorBridgeParent.cpp | 2 +- .../CrossProcessCompositorBridgeParent.cpp | 2 +- gfx/layers/ipc/PWebRenderBridge.ipdl | 2 + gfx/layers/wr/WebRenderBridgeChild.cpp | 24 ++++++++ gfx/layers/wr/WebRenderBridgeChild.h | 3 + gfx/layers/wr/WebRenderBridgeParent.cpp | 56 +++++++++++++++---- gfx/layers/wr/WebRenderBridgeParent.h | 10 ++-- gfx/layers/wr/WebRenderCompositorOGL.cpp | 53 ++++++++++++++++++ gfx/layers/wr/WebRenderCompositorOGL.h | 17 ++++++ gfx/layers/wr/WebRenderImageLayer.cpp | 14 +++++ gfx/layers/wr/WebRenderImageLayer.h | 9 +-- 15 files changed, 204 insertions(+), 21 deletions(-) diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 97495ceb392e..8d8f54a8ce80 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -135,6 +135,7 @@ class CompositorD3D11; class BasicCompositor; class TextureHost; class TextureReadLock; +class WebRenderCompositorOGL; enum SurfaceInitMode { @@ -466,6 +467,7 @@ public: virtual CompositorD3D9* AsCompositorD3D9() { return nullptr; } virtual CompositorD3D11* AsCompositorD3D11() { return nullptr; } virtual BasicCompositor* AsBasicCompositor() { return nullptr; } + virtual WebRenderCompositorOGL* AsWebRenderCompositorOGL() { return nullptr; } /** * Each Compositor has a unique ID. @@ -546,7 +548,7 @@ public: } } - void CompositeUntil(TimeStamp aTimeStamp) { + virtual void CompositeUntil(TimeStamp aTimeStamp) { if (mCompositeUntilTime.IsNull() || mCompositeUntilTime < aTimeStamp) { mCompositeUntilTime = aTimeStamp; diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index d8a967732181..3f46ee7b9af8 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -239,6 +239,8 @@ public: /// is is destroyed. virtual void CleanupResources() {} + virtual void BindTextureSource() {} + protected: TextureInfo mTextureInfo; uint64_t mAsyncID; diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index 841b12d9a727..6b793a116db3 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -433,6 +433,31 @@ ImageHost::Composite(LayerComposite* aLayer, mBias); } +void +ImageHost::BindTextureSource() +{ + int imageIndex = ChooseImageIndex(); + if (imageIndex < 0) { + return; + } + + if (uint32_t(imageIndex) + 1 < mImages.Length()) { + GetCompositor()->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS)); + } + + TimedImage* img = &mImages[imageIndex]; + img->mTextureHost->SetCompositor(GetCompositor()); + SetCurrentTextureHost(img->mTextureHost); + + // XXX Add TextureSource binding + + mBias = UpdateBias( + GetCompositor()->GetCompositionTime(), mImages[imageIndex].mTimeStamp, + uint32_t(imageIndex + 1) < mImages.Length() ? + mImages[imageIndex + 1].mTimeStamp : TimeStamp(), + mBias); +} + void ImageHost::SetCompositor(Compositor* aCompositor) { diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index 15064d210ef7..1b72976f2ea5 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -89,6 +89,8 @@ public: virtual void CleanupResources() override; + virtual void BindTextureSource() override; + int32_t GetFrameID() { const TimedImage* img = ChooseImage(); diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 1e04868860d1..dce783010234 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -1552,7 +1552,7 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId) RefPtr glc(gl::GLContextProvider::CreateForCompositorWidget(mWidget, true)); RefPtr compositor = new WebRenderCompositorOGL(glc.get()); - WebRenderBridgeParent* parent = new WebRenderBridgeParent(nullptr, aPipelineId, + WebRenderBridgeParent* parent = new WebRenderBridgeParent(aPipelineId, mWidget, glc.get(), nullptr, compositor.get()); parent->AddRef(); // IPDL reference MonitorAutoLock lock(*sIndirectLayerTreesLock); diff --git a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp index 1bbb90bf2f3e..4a648dc1e3c0 100644 --- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp @@ -212,7 +212,7 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWRBridge.get(); WebRenderBridgeParent* parent = new WebRenderBridgeParent( - root, aPipelineId, nullptr, root->GLContext(), root->WindowState(), root->Compositor()); + aPipelineId, nullptr, root->GLContext(), root->WindowState(), root->Compositor()); parent->AddRef(); // IPDL reference sIndirectLayerTrees[aPipelineId].mWRBridge = parent; diff --git a/gfx/layers/ipc/PWebRenderBridge.ipdl b/gfx/layers/ipc/PWebRenderBridge.ipdl index 677059fc48a0..e76d92d39372 100644 --- a/gfx/layers/ipc/PWebRenderBridge.ipdl +++ b/gfx/layers/ipc/PWebRenderBridge.ipdl @@ -35,6 +35,8 @@ parent: sync DPSyncEnd(WebRenderCommand[] commands); sync DPGetSnapshot(uint32_t aWidth, uint32_t aHeight) returns (uint8_t[] aOutImageSnapshot); + async AddExternalImageId(uint64_t aImageId, uint64_t aAsyncContainerId); + async RemoveExternalImageId(uint64_t aImageId); async __delete__(); }; diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp index f7746cfa66fc..a78e6acb89fd 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -51,5 +51,29 @@ WebRenderBridgeChild::DPEnd(bool aIsSync) mIsInTransaction = false; } +uint64_t +WebRenderBridgeChild::AllocExternalImageId(uint64_t aAsyncContainerID) +{ + static uint32_t sNextID = 1; + ++sNextID; + MOZ_RELEASE_ASSERT(sNextID != UINT32_MAX); + + // XXX replace external image id allocation with webrender's id allocation. + // Use proc id as IdNamespace for now. + uint32_t procId = static_cast(base::GetCurrentProcId()); + uint64_t imageId = procId; + imageId = imageId << 32 | sNextID; + + SendAddExternalImageId(imageId, aAsyncContainerID); + return imageId; +} + +void +WebRenderBridgeChild::DeallocExternalImageId(uint64_t aImageId) +{ + MOZ_ASSERT(aImageId); + SendRemoveExternalImageId(aImageId); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/wr/WebRenderBridgeChild.h b/gfx/layers/wr/WebRenderBridgeChild.h index 552b59b3cdc2..715510de7748 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.h +++ b/gfx/layers/wr/WebRenderBridgeChild.h @@ -30,6 +30,9 @@ public: bool DPBegin(uint32_t aWidth, uint32_t aHeight); void DPEnd(bool aIsSync = false); + + uint64_t AllocExternalImageId(uint64_t aAsyncContainerID); + void DeallocExternalImageId(uint64_t aImageId); protected: ~WebRenderBridgeChild() {} diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 0310669f82b3..023c857a1e63 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -6,23 +6,23 @@ #include "mozilla/layers/WebRenderBridgeParent.h" +#include "CompositableHost.h" #include "GLContext.h" #include "GLContextProvider.h" #include "mozilla/layers/Compositor.h" #include "mozilla/layers/CompositorVsyncScheduler.h" #include "mozilla/widget/CompositorWidget.h" +#include "mozilla/layers/WebRenderCompositorOGL.h" namespace mozilla { namespace layers { -WebRenderBridgeParent::WebRenderBridgeParent(WebRenderBridgeParent* aParent, - const uint64_t& aPipelineId, +WebRenderBridgeParent::WebRenderBridgeParent(const uint64_t& aPipelineId, widget::CompositorWidget* aWidget, gl::GLContext* aGlContext, wrwindowstate* aWrWindowState, layers::Compositor* aCompositor) - : mParent(aParent) - , mPipelineId(aPipelineId) + : mPipelineId(aPipelineId) , mWidget(aWidget) , mWRState(nullptr) , mGLContext(aGlContext) @@ -40,6 +40,7 @@ WebRenderBridgeParent::WebRenderBridgeParent(WebRenderBridgeParent* aParent, } if (mWidget) { mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget); + mCompositor->AsWebRenderCompositorOGL()->SetVsyncScheduler(mCompositorScheduler); } } @@ -186,9 +187,48 @@ WebRenderBridgeParent::RecvDPGetSnapshot(const uint32_t& aWidth, return IPC_OK(); } +mozilla::ipc::IPCResult +WebRenderBridgeParent::RecvAddExternalImageId(const uint64_t& aImageId, + const uint64_t& aAsyncContainerId) +{ + MOZ_ASSERT(!mExternalImageIds.Get(aImageId)); + + PCompositableParent* compositableParent = CompositableMap::Get(aAsyncContainerId); + if (!compositableParent) { + NS_ERROR("CompositableParent not found in the map"); + return IPC_OK(); + } + + CompositableHost* host = CompositableHost::FromIPDLActor(compositableParent); + if (host->GetType() != CompositableType::IMAGE) { + NS_ERROR("Incompatible CompositableHost"); + return IPC_OK(); + } + + host->SetCompositor(mCompositor); + mCompositor->AsWebRenderCompositorOGL()->AddExternalImageId(aImageId, host); + mExternalImageIds.Put(aImageId, aImageId); + return IPC_OK(); +} + +mozilla::ipc::IPCResult +WebRenderBridgeParent::RecvRemoveExternalImageId(const uint64_t& aImageId) +{ + MOZ_ASSERT(mExternalImageIds.Get(aImageId)); + mExternalImageIds.Remove(aImageId); + mCompositor->AsWebRenderCompositorOGL()->RemoveExternalImageId(aImageId); + return IPC_OK(); +} + void WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { + for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) { + uint64_t externalImageId = iter.Data(); + mCompositor->AsWebRenderCompositorOGL()->RemoveExternalImageId(externalImageId); + } + mExternalImageIds.Clear(); + ClearResources(); } @@ -204,6 +244,7 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In } mCompositor->SetCompositionTime(TimeStamp::Now()); + mCompositor->AsWebRenderCompositorOGL()->UpdateExternalImages(); MOZ_ASSERT(mWRState); mozilla::widget::WidgetRenderingContext widgetContext; @@ -235,11 +276,7 @@ WebRenderBridgeParent::DeleteOldImages() void WebRenderBridgeParent::ScheduleComposition() { - if (mCompositorScheduler) { - mCompositorScheduler->ScheduleComposition(); - } else if (mParent) { - mParent->ScheduleComposition(); - } + mCompositor->AsWebRenderCompositorOGL()->ScheduleComposition(); } void @@ -259,7 +296,6 @@ WebRenderBridgeParent::ClearResources() mCompositorScheduler = nullptr; } mGLContext = nullptr; - mParent = nullptr; } } // namespace layers diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index c80ddf568151..89df865c0361 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -33,8 +33,7 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeParent) public: - WebRenderBridgeParent(WebRenderBridgeParent* aParent, - const uint64_t& aPipelineId, + WebRenderBridgeParent(const uint64_t& aPipelineId, widget::CompositorWidget* aWidget, gl::GLContext* aGlContext, wrwindowstate* aWrWindowState, @@ -68,6 +67,10 @@ public: const uint32_t& aHeight, InfallibleTArray* aOutImageSnapshot) override; + mozilla::ipc::IPCResult RecvAddExternalImageId(const uint64_t& aImageId, + const uint64_t& aAsyncContainerId) override; + mozilla::ipc::IPCResult RecvRemoveExternalImageId(const uint64_t& aImageId) override; + void ActorDestroy(ActorDestroyReason aWhy) override; // CompositorVsyncSchedulerOwner @@ -83,8 +86,6 @@ protected: void ClearResources(); private: - // XXX remove mParent in Bug 1317935 - RefPtr mParent; uint64_t mPipelineId; RefPtr mWidget; wrstate* mWRState; @@ -93,6 +94,7 @@ private: RefPtr mCompositor; RefPtr mCompositorScheduler; std::vector mKeysToDelete; + nsDataHashtable mExternalImageIds; }; } // namespace layers diff --git a/gfx/layers/wr/WebRenderCompositorOGL.cpp b/gfx/layers/wr/WebRenderCompositorOGL.cpp index c4b02bd2eb6d..7c386ef4bd60 100644 --- a/gfx/layers/wr/WebRenderCompositorOGL.cpp +++ b/gfx/layers/wr/WebRenderCompositorOGL.cpp @@ -5,8 +5,10 @@ #include "WebRenderCompositorOGL.h" +#include "CompositableHost.h" #include "GLContext.h" // for GLContext #include "GLUploadHelpers.h" +#include "mozilla/layers/CompositorVsyncScheduler.h" #include "mozilla/layers/TextureHost.h" // for TextureSource, etc #include "mozilla/layers/TextureHostOGL.h" // for TextureSourceOGL, etc @@ -35,6 +37,9 @@ WebRenderCompositorOGL::Destroy() { Compositor::Destroy(); + mCompositableHosts.Clear(); + mCompositorScheduler = nullptr; + if (!mDestroyed) { mDestroyed = true; mGLContext = nullptr;; @@ -80,5 +85,53 @@ WebRenderCompositorOGL::MakeCurrent(MakeCurrentFlags aFlags) { mGLContext->MakeCurrent(aFlags & ForceMakeCurrent); } +void +WebRenderCompositorOGL::CompositeUntil(TimeStamp aTimeStamp) +{ + Compositor::CompositeUntil(aTimeStamp); + // We're not really taking advantage of the stored composite-again-time here. + // We might be able to skip the next few composites altogether. However, + // that's a bit complex to implement and we'll get most of the advantage + // by skipping compositing when we detect there's nothing invalid. This is why + // we do "composite until" rather than "composite again at". + ScheduleComposition(); +} + +void +WebRenderCompositorOGL::AddExternalImageId(uint64_t aExternalImageId, CompositableHost* aHost) +{ + MOZ_ASSERT(!mCompositableHosts.Get(aExternalImageId)); + mCompositableHosts.Put(aExternalImageId, aHost); +} + +void +WebRenderCompositorOGL::RemoveExternalImageId(uint64_t aExternalImageId) +{ + MOZ_ASSERT(mCompositableHosts.Get(aExternalImageId)); + mCompositableHosts.Remove(aExternalImageId); +} + +void +WebRenderCompositorOGL::UpdateExternalImages() +{ + for (auto iter = mCompositableHosts.Iter(); !iter.Done(); iter.Next()) { + RefPtr& host = iter.Data(); + // XXX Change to correct TextrueSource handling here. + host->BindTextureSource(); + } +} + +void +WebRenderCompositorOGL::ScheduleComposition() +{ + mCompositorScheduler->ScheduleComposition(); +} + +void +WebRenderCompositorOGL::SetVsyncScheduler(CompositorVsyncScheduler* aScheduler) +{ + mCompositorScheduler = aScheduler; +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/wr/WebRenderCompositorOGL.h b/gfx/layers/wr/WebRenderCompositorOGL.h index eb384c6f4f4f..ab0e55266c78 100644 --- a/gfx/layers/wr/WebRenderCompositorOGL.h +++ b/gfx/layers/wr/WebRenderCompositorOGL.h @@ -9,10 +9,14 @@ #include "GLContextTypes.h" // for GLContext, etc #include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc #include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc +#include "nsDataHashtable.h" namespace mozilla { namespace layers { +class CompositableHost; +class CompositorVsyncScheduler; + class WebRenderCompositorOGL final : public Compositor { typedef mozilla::gl::GLContext GLContext; @@ -24,6 +28,8 @@ protected: virtual ~WebRenderCompositorOGL(); public: + virtual WebRenderCompositorOGL* AsWebRenderCompositorOGL() override { return this; } + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; @@ -106,10 +112,21 @@ public: virtual bool IsValid() const override { return true; } + virtual void CompositeUntil(TimeStamp aTimeStamp) override; + GLContext* gl() const { return mGLContext; } + void AddExternalImageId(uint64_t aExternalImageId, CompositableHost* aHost); + void RemoveExternalImageId(uint64_t aExternalImageId); + void UpdateExternalImages(); + + void ScheduleComposition(); + void SetVsyncScheduler(CompositorVsyncScheduler* aScheduler); private: RefPtr mGLContext; + RefPtr mCompositorScheduler; + // Holds CompositableHosts that are bound to external image ids. + nsDataHashtable > mCompositableHosts; bool mDestroyed; }; diff --git a/gfx/layers/wr/WebRenderImageLayer.cpp b/gfx/layers/wr/WebRenderImageLayer.cpp index a2325f904b2b..b10cae5d129e 100644 --- a/gfx/layers/wr/WebRenderImageLayer.cpp +++ b/gfx/layers/wr/WebRenderImageLayer.cpp @@ -13,6 +13,14 @@ namespace layers { using namespace gfx; +WebRenderImageLayer::~WebRenderImageLayer() +{ + MOZ_COUNT_DTOR(WebRenderImageLayer); + if (mImageId) { + WRBridge()->DeallocExternalImageId(mImageId); + } +} + already_AddRefed WebRenderImageLayer::GetAsSourceSurface() { @@ -31,6 +39,12 @@ WebRenderImageLayer::GetAsSourceSurface() void WebRenderImageLayer::RenderLayer() { + // XXX update async ImageContainer rendering path + if (mContainer->IsAsync() && !mImageId) { + mImageId = WRBridge()->AllocExternalImageId(mContainer->GetAsyncContainerID()); + MOZ_ASSERT(mImageId); + } + RefPtr surface = GetAsSourceSurface(); if (!surface) return; diff --git a/gfx/layers/wr/WebRenderImageLayer.h b/gfx/layers/wr/WebRenderImageLayer.h index 86e19d2dce05..18773c24b9e9 100644 --- a/gfx/layers/wr/WebRenderImageLayer.h +++ b/gfx/layers/wr/WebRenderImageLayer.h @@ -17,16 +17,14 @@ class WebRenderImageLayer : public WebRenderLayer, public: explicit WebRenderImageLayer(WebRenderLayerManager* aLayerManager) : ImageLayer(aLayerManager, static_cast(this)) + , mImageId(0) { MOZ_COUNT_CTOR(WebRenderImageLayer); } virtual already_AddRefed GetAsSourceSurface() override; protected: - virtual ~WebRenderImageLayer() - { - MOZ_COUNT_DTOR(WebRenderImageLayer); - } + virtual ~WebRenderImageLayer(); WebRenderLayerManager* Manager() { @@ -36,6 +34,9 @@ protected: public: Layer* GetLayer() override { return this; } void RenderLayer() override; + +protected: + uint64_t mImageId; }; } // namespace layers