Bug 1317935 - Use GetCompositeUntilTime() to trigger next composition r=nical?

This commit is contained in:
sotaro 2016-11-24 15:48:01 +09:00
Родитель 2deb064663
Коммит a450a2754f
15 изменённых файлов: 204 добавлений и 21 удалений

Просмотреть файл

@ -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;

Просмотреть файл

@ -239,6 +239,8 @@ public:
/// is is destroyed.
virtual void CleanupResources() {}
virtual void BindTextureSource() {}
protected:
TextureInfo mTextureInfo;
uint64_t mAsyncID;

Просмотреть файл

@ -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)
{

Просмотреть файл

@ -89,6 +89,8 @@ public:
virtual void CleanupResources() override;
virtual void BindTextureSource() override;
int32_t GetFrameID()
{
const TimedImage* img = ChooseImage();

Просмотреть файл

@ -1552,7 +1552,7 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId)
RefPtr<gl::GLContext> glc(gl::GLContextProvider::CreateForCompositorWidget(mWidget, true));
RefPtr<Compositor> 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);

Просмотреть файл

@ -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;

Просмотреть файл

@ -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__();
};

Просмотреть файл

@ -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<uint32_t>(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

Просмотреть файл

@ -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() {}

Просмотреть файл

@ -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

Просмотреть файл

@ -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<uint8_t>* 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<WebRenderBridgeParent> mParent;
uint64_t mPipelineId;
RefPtr<widget::CompositorWidget> mWidget;
wrstate* mWRState;
@ -93,6 +94,7 @@ private:
RefPtr<layers::Compositor> mCompositor;
RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
std::vector<WRImageKey> mKeysToDelete;
nsDataHashtable<nsUint64HashKey, uint64_t> mExternalImageIds;
};
} // namespace layers

Просмотреть файл

@ -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<CompositableHost>& 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

Просмотреть файл

@ -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<DataTextureSource>
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<GLContext> mGLContext;
RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
// Holds CompositableHosts that are bound to external image ids.
nsDataHashtable<nsUint64HashKey, RefPtr<CompositableHost> > mCompositableHosts;
bool mDestroyed;
};

Просмотреть файл

@ -13,6 +13,14 @@ namespace layers {
using namespace gfx;
WebRenderImageLayer::~WebRenderImageLayer()
{
MOZ_COUNT_DTOR(WebRenderImageLayer);
if (mImageId) {
WRBridge()->DeallocExternalImageId(mImageId);
}
}
already_AddRefed<gfx::SourceSurface>
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<gfx::SourceSurface> surface = GetAsSourceSurface();
if (!surface)
return;

Просмотреть файл

@ -17,16 +17,14 @@ class WebRenderImageLayer : public WebRenderLayer,
public:
explicit WebRenderImageLayer(WebRenderLayerManager* aLayerManager)
: ImageLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
, mImageId(0)
{
MOZ_COUNT_CTOR(WebRenderImageLayer);
}
virtual already_AddRefed<gfx::SourceSurface> 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