зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1365196 - Throttle GenerateFrame() r=kats,nical
This commit is contained in:
Родитель
8545f35670
Коммит
cbec0e500e
|
@ -122,6 +122,7 @@ WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompos
|
|||
, mIdNameSpace(AllocIdNameSpace())
|
||||
, mPaused(false)
|
||||
, mDestroyed(false)
|
||||
, mIsSnapshotting(false)
|
||||
{
|
||||
MOZ_ASSERT(mCompositableHolder);
|
||||
mCompositableHolder->AddPipeline(mPipelineId);
|
||||
|
@ -616,6 +617,8 @@ WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
|
|||
// Assert the stride of the buffer is what webrender expects
|
||||
MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
|
||||
|
||||
mIsSnapshotting = true;
|
||||
|
||||
if (mCompositorScheduler->NeedsComposite()) {
|
||||
mCompositorScheduler->CancelCurrentCompositeTask();
|
||||
mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
|
||||
|
@ -623,6 +626,8 @@ WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
|
|||
|
||||
mApi->Readback(size, buffer, buffer_size);
|
||||
|
||||
mIsSnapshotting = false;
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -762,6 +767,15 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
|
|||
return;
|
||||
}
|
||||
|
||||
const uint32_t maxPendingFrameCount = 2;
|
||||
|
||||
if (!mIsSnapshotting &&
|
||||
wr::RenderThread::Get()->GetPendingFrameCount(mApi->GetId()) > maxPendingFrameCount) {
|
||||
// Render thread is busy, try next time.
|
||||
ScheduleComposition();
|
||||
return;
|
||||
}
|
||||
|
||||
if (PushAPZStateToWR()) {
|
||||
ScheduleComposition();
|
||||
}
|
||||
|
|
|
@ -236,6 +236,7 @@ private:
|
|||
|
||||
bool mPaused;
|
||||
bool mDestroyed;
|
||||
bool mIsSnapshotting;
|
||||
|
||||
// Can only be accessed on the compositor thread.
|
||||
WebRenderScrollData mScrollData;
|
||||
|
|
|
@ -20,6 +20,7 @@ static StaticRefPtr<RenderThread> sRenderThread;
|
|||
|
||||
RenderThread::RenderThread(base::Thread* aThread)
|
||||
: mThread(aThread)
|
||||
, mPendingFrameCountMapLock("RenderThread.mPendingFrameCountMapLock")
|
||||
, mRenderTextureMapLock("RenderThread.mRenderTextureMapLock")
|
||||
{
|
||||
|
||||
|
@ -88,6 +89,9 @@ RenderThread::AddRenderer(wr::WindowId aWindowId, UniquePtr<RendererOGL> aRender
|
|||
{
|
||||
MOZ_ASSERT(IsInRenderThread());
|
||||
mRenderers[aWindowId] = Move(aRenderer);
|
||||
|
||||
MutexAutoLock lock(mPendingFrameCountMapLock);
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -95,6 +99,9 @@ RenderThread::RemoveRenderer(wr::WindowId aWindowId)
|
|||
{
|
||||
MOZ_ASSERT(IsInRenderThread());
|
||||
mRenderers.erase(aWindowId);
|
||||
|
||||
MutexAutoLock lock(mPendingFrameCountMapLock);
|
||||
mPendingFrameCounts.Remove(AsUint64(aWindowId));
|
||||
}
|
||||
|
||||
RendererOGL*
|
||||
|
@ -123,6 +130,7 @@ RenderThread::NewFrameReady(wr::WindowId aWindowId)
|
|||
}
|
||||
|
||||
UpdateAndRender(aWindowId);
|
||||
DecPendingFrameCount(aWindowId);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -224,6 +232,48 @@ RenderThread::Resume(wr::WindowId aWindowId)
|
|||
return renderer->Resume();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RenderThread::GetPendingFrameCount(wr::WindowId aWindowId)
|
||||
{
|
||||
MutexAutoLock lock(mPendingFrameCountMapLock);
|
||||
uint32_t count = 0;
|
||||
MOZ_ASSERT(mPendingFrameCounts.Get(AsUint64(aWindowId), &count));
|
||||
mPendingFrameCounts.Get(AsUint64(aWindowId), &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
RenderThread::IncPendingFrameCount(wr::WindowId aWindowId)
|
||||
{
|
||||
MutexAutoLock lock(mPendingFrameCountMapLock);
|
||||
// Get the old count.
|
||||
uint32_t oldCount = 0;
|
||||
if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &oldCount)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
// Update pending frame count.
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), oldCount + 1);
|
||||
}
|
||||
|
||||
void
|
||||
RenderThread::DecPendingFrameCount(wr::WindowId aWindowId)
|
||||
{
|
||||
MutexAutoLock lock(mPendingFrameCountMapLock);
|
||||
// Get the old count.
|
||||
uint32_t oldCount = 0;
|
||||
if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &oldCount)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(oldCount > 0);
|
||||
if (oldCount <= 0) {
|
||||
return;
|
||||
}
|
||||
// Update pending frame count.
|
||||
mPendingFrameCounts.Put(AsUint64(aWindowId), oldCount - 1);
|
||||
}
|
||||
|
||||
void
|
||||
RenderThread::RegisterExternalImage(uint64_t aExternalImageId, RenderTextureHost* aTexture)
|
||||
{
|
||||
|
@ -255,6 +305,7 @@ extern "C" {
|
|||
|
||||
void wr_notifier_new_frame_ready(WrWindowId aWindowId)
|
||||
{
|
||||
mozilla::wr::RenderThread::Get()->IncPendingFrameCount(aWindowId);
|
||||
mozilla::wr::RenderThread::Get()->NewFrameReady(mozilla::wr::WindowId(aWindowId));
|
||||
}
|
||||
|
||||
|
|
|
@ -111,16 +111,25 @@ public:
|
|||
|
||||
RenderTextureHost* GetRenderTexture(WrExternalImageId aExternalImageId);
|
||||
|
||||
/// Can be called from any thread.
|
||||
uint32_t GetPendingFrameCount(wr::WindowId aWindowId);
|
||||
/// Can be called from any thread.
|
||||
void IncPendingFrameCount(wr::WindowId aWindowId);
|
||||
/// Can be called from any thread.
|
||||
void DecPendingFrameCount(wr::WindowId aWindowId);
|
||||
|
||||
private:
|
||||
explicit RenderThread(base::Thread* aThread);
|
||||
|
||||
~RenderThread();
|
||||
|
||||
|
||||
base::Thread* const mThread;
|
||||
|
||||
std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers;
|
||||
|
||||
Mutex mPendingFrameCountMapLock;
|
||||
nsDataHashtable<nsUint64HashKey, uint32_t> mPendingFrameCounts;
|
||||
|
||||
Mutex mRenderTextureMapLock;
|
||||
nsDataHashtable<nsUint64HashKey, RefPtr<RenderTextureHost> > mRenderTextures;
|
||||
};
|
||||
|
|
|
@ -103,6 +103,11 @@ struct ImageDescriptor: public WrImageDescriptor {
|
|||
}
|
||||
};
|
||||
|
||||
// Whenever possible, use wr::WindowId instead of manipulating uint64_t.
|
||||
inline uint64_t AsUint64(const WindowId& aId) {
|
||||
return static_cast<uint64_t>(aId.mHandle);
|
||||
}
|
||||
|
||||
// Whenever possible, use wr::ImageKey instead of manipulating uint64_t.
|
||||
inline uint64_t AsUint64(const ImageKey& aId) {
|
||||
return (static_cast<uint64_t>(aId.mNamespace) << 32)
|
||||
|
|
Загрузка…
Ссылка в новой задаче