Bug 1013767 - Restrict BasicCompositor snapshots to the bounds of the invalid region. r=nical

This commit is contained in:
Matt Woodrow 2014-05-28 13:21:32 +12:00
parent a566c9094a
commit f6d3bf9e86
15 changed files with 76 additions and 85 deletions

View File

@ -238,7 +238,15 @@ public:
* If this method is not used, or we pass in nullptr, we target the compositor's
* usual swap chain and render to the screen.
*/
virtual void SetTargetContext(gfx::DrawTarget* aTarget) = 0;
void SetTargetContext(gfx::DrawTarget* aTarget, const nsIntRect& aRect)
{
mTarget = aTarget;
mTargetBounds = aRect;
}
void ClearTargetContext()
{
mTarget = nullptr;
}
typedef uint32_t MakeCurrentFlags;
static const MakeCurrentFlags ForceMakeCurrent = 0x1;
@ -522,6 +530,9 @@ protected:
virtual gfx::IntSize GetWidgetSize() const = 0;
RefPtr<gfx::DrawTarget> mTarget;
nsIntRect mTargetBounds;
private:
static LayersBackend sBackend;

View File

@ -412,7 +412,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
return;
}
if (mCopyTarget) {
if (mTarget) {
// If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Create a dummy
// placeholder so that CreateRenderTarget() works.
mDrawTarget = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(1,1), SurfaceFormat::B8G8R8A8);
@ -424,7 +424,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
}
// Setup an intermediate render target to buffer all compositing. We will
// copy this into mDrawTarget (the widget), and/or mCopyTarget in EndFrame()
// copy this into mDrawTarget (the widget), and/or mTarget in EndFrame()
RefPtr<CompositingRenderTarget> target = CreateRenderTarget(mInvalidRect, INIT_MODE_CLEAR);
SetRenderTarget(target);
@ -471,7 +471,9 @@ BasicCompositor::EndFrame()
// Note: Most platforms require us to buffer drawing to the widget surface.
// That's why we don't draw to mDrawTarget directly.
RefPtr<SourceSurface> source = mRenderTarget->mDrawTarget->Snapshot();
RefPtr<DrawTarget> dest(mCopyTarget ? mCopyTarget : mDrawTarget);
RefPtr<DrawTarget> dest(mTarget ? mTarget : mDrawTarget);
nsIntPoint offset = mTarget ? mTargetBounds.TopLeft() : nsIntPoint();
// The source DrawTarget is clipped to the invalidation region, so we have
// to copy the individual rectangles in the region or else we'll draw blank
@ -480,9 +482,9 @@ BasicCompositor::EndFrame()
for (const nsIntRect *r = iter.Next(); r; r = iter.Next()) {
dest->CopySurface(source,
IntRect(r->x - mInvalidRect.x, r->y - mInvalidRect.y, r->width, r->height),
IntPoint(r->x, r->y));
IntPoint(r->x - offset.x, r->y - offset.y));
}
if (!mCopyTarget) {
if (!mTarget) {
mWidget->EndRemoteDrawing();
}

View File

@ -103,10 +103,6 @@ public:
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE { return true; }
virtual int32_t GetMaxTextureSize() const MOZ_OVERRIDE { return INT32_MAX; }
virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE { }
virtual void SetTargetContext(gfx::DrawTarget* aTarget) MOZ_OVERRIDE
{
mCopyTarget = aTarget;
}
virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) MOZ_OVERRIDE {
}
@ -138,9 +134,6 @@ private:
RefPtr<gfx::DrawTarget> mDrawTarget;
// The current render target for drawing
RefPtr<BasicCompositingRenderTarget> mRenderTarget;
// An optional destination target to copy the results
// to after drawing is completed.
RefPtr<gfx::DrawTarget> mCopyTarget;
gfx::IntRect mInvalidRect;
nsIntRegion mInvalidRegion;

View File

@ -337,6 +337,14 @@ ClientLayerManager::RunOverfillCallback(const uint32_t aOverfill)
mOverfillCallbacks.Clear();
}
static nsIntRect
ToOutsideIntRect(const gfxRect &aRect)
{
gfxRect r = aRect;
r.RoundOut();
return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
}
void
ClientLayerManager::MakeSnapshotIfRequired()
{
@ -345,27 +353,22 @@ ClientLayerManager::MakeSnapshotIfRequired()
}
if (mWidget) {
if (CompositorChild* remoteRenderer = GetRemoteRenderer()) {
nsIntRect bounds;
mWidget->GetBounds(bounds);
IntSize widgetSize = bounds.Size().ToIntSize();
SurfaceDescriptor inSnapshot, snapshot;
if (mForwarder->AllocSurfaceDescriptor(widgetSize,
nsIntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
SurfaceDescriptor inSnapshot;
if (!bounds.IsEmpty() &&
mForwarder->AllocSurfaceDescriptor(bounds.Size().ToIntSize(),
gfxContentType::COLOR_ALPHA,
&inSnapshot) &&
// The compositor will usually reuse |snapshot| and return
// it through |outSnapshot|, but if it doesn't, it's
// responsible for freeing |snapshot|.
remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(snapshot);
remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(inSnapshot);
DrawTarget* dt = mShadowTarget->GetDrawTarget();
Rect widgetRect(Point(0, 0), Size(widgetSize.width, widgetSize.height));
dt->DrawSurface(surf, widgetRect, widgetRect,
Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
Rect srcRect(0, 0, bounds.width, bounds.height);
dt->DrawSurface(surf, dstRect, srcRect,
DrawSurfaceOptions(),
DrawOptions(1.0f, CompositionOp::OP_OVER));
}
if (IsSurfaceDescriptorValid(snapshot)) {
mForwarder->DestroySharedSurface(&snapshot);
}
mForwarder->DestroySharedSurface(&inSnapshot);
}
}
mShadowTarget = nullptr;

View File

@ -161,7 +161,7 @@ LayerManagerComposite::BeginTransaction()
}
void
LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget, const nsIntRect& aRect)
{
mInTransaction = true;
@ -180,8 +180,9 @@ LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
}
mIsCompositorReady = true;
mCompositor->SetTargetContext(aTarget);
mCompositor->SetTargetContext(aTarget, aRect);
mTarget = aTarget;
mTargetBounds = aRect;
}
bool
@ -223,12 +224,13 @@ LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
}
if (mRoot && mClonedLayerTreeProperties) {
MOZ_ASSERT(!mTarget);
nsIntRegion invalid =
mClonedLayerTreeProperties->ComputeDifferences(mRoot, nullptr, &mGeometryChanged);
mClonedLayerTreeProperties = nullptr;
mInvalidRegion.Or(mInvalidRegion, invalid);
} else {
} else if (!mTarget) {
mInvalidRegion.Or(mInvalidRegion, mRenderBounds);
}
@ -247,7 +249,7 @@ LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
mGeometryChanged = false;
}
mCompositor->SetTargetContext(nullptr);
mCompositor->ClearTargetContext();
mTarget = nullptr;
#ifdef MOZ_LAYERS_HAVE_LOG
@ -405,6 +407,15 @@ LayerManagerComposite::Render()
}
}
nsIntRegion invalid;
if (mTarget) {
invalid = mTargetBounds;
} else {
invalid = mInvalidRegion;
// Reset the invalid region now that we've begun compositing.
mInvalidRegion.SetEmpty();
}
nsIntRect clipRect;
Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
Rect actualBounds;
@ -415,16 +426,13 @@ LayerManagerComposite::Render()
clipRect = *mRoot->GetClipRect();
WorldTransformRect(clipRect);
Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
mCompositor->BeginFrame(mInvalidRegion, &rect, mWorldMatrix, bounds, nullptr, &actualBounds);
mCompositor->BeginFrame(invalid, &rect, mWorldMatrix, bounds, nullptr, &actualBounds);
} else {
gfx::Rect rect;
mCompositor->BeginFrame(mInvalidRegion, nullptr, mWorldMatrix, bounds, &rect, &actualBounds);
mCompositor->BeginFrame(invalid, nullptr, mWorldMatrix, bounds, &rect, &actualBounds);
clipRect = nsIntRect(rect.x, rect.y, rect.width, rect.height);
}
// Reset the invalid region now that we've begun compositing.
mInvalidRegion.SetEmpty();
if (actualBounds.IsEmpty()) {
mCompositor->GetWidget()->PostRender(this);
return;

View File

@ -111,7 +111,7 @@ public:
{
MOZ_CRASH("Use BeginTransactionWithDrawTarget");
}
void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget);
void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget, const nsIntRect& aRect);
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) MOZ_OVERRIDE;
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
@ -271,6 +271,7 @@ private:
* Context target, nullptr when drawing directly to our swap chain.
*/
RefPtr<gfx::DrawTarget> mTarget;
nsIntRect mTargetBounds;
gfx::Matrix mWorldMatrix;
nsIntRegion mInvalidRegion;

View File

@ -1019,7 +1019,7 @@ CompositorD3D11::PaintToTarget()
SurfaceFormat::B8G8R8A8);
mTarget->CopySurface(sourceSurface,
IntRect(0, 0, bbDesc.Width, bbDesc.Height),
IntPoint());
IntPoint(-mTargetBounds.x, -mTargetBounds.y));
mTarget->Flush();
mContext->Unmap(readTexture, 0);
}

View File

@ -55,11 +55,6 @@ public:
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) MOZ_OVERRIDE;
virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
virtual void SetTargetContext(gfx::DrawTarget* aTarget) MOZ_OVERRIDE
{
mTarget = aTarget;
}
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE {}
virtual TemporaryRef<CompositingRenderTarget>
@ -168,8 +163,6 @@ private:
DeviceAttachmentsD3D11* mAttachments;
RefPtr<gfx::DrawTarget> mTarget;
nsIWidget* mWidget;
nsIntSize mSize;

View File

@ -743,7 +743,7 @@ CompositorD3D9::PaintToTarget()
SurfaceFormat::B8G8R8A8);
mTarget->CopySurface(sourceSurface,
IntRect(0, 0, desc.Width, desc.Height),
IntPoint());
IntPoint(-mTargetBounds.x, -mTargetBounds.y));
mTarget->Flush();
destSurf->UnlockRect();
}

View File

@ -32,11 +32,6 @@ public:
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE;
virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
virtual void SetTargetContext(gfx::DrawTarget *aTarget) MOZ_OVERRIDE
{
mTarget = aTarget;
}
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE {}
virtual TemporaryRef<CompositingRenderTarget>
@ -168,11 +163,6 @@ private:
/* Widget associated with this layer manager */
nsIWidget *mWidget;
/*
* Context target, nullptr when drawing directly to our swap chain.
*/
RefPtr<gfx::DrawTarget> mTarget;
RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
RefPtr<CompositingRenderTargetD3D9> mCurrentRT;

View File

@ -328,11 +328,10 @@ CompositorParent::RecvResume()
bool
CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
SurfaceDescriptor* aOutSnapshot)
const nsIntRect& aRect)
{
RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
ForceComposeToTarget(target);
*aOutSnapshot = aInSnapshot;
ForceComposeToTarget(target, &aRect);
return true;
}
@ -609,7 +608,7 @@ CompositorParent::Composite()
}
void
CompositorParent::CompositeToTarget(DrawTarget* aTarget)
CompositorParent::CompositeToTarget(DrawTarget* aTarget, const nsIntRect* aRect)
{
profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
PROFILER_LABEL("CompositorParent", "Composite");
@ -639,7 +638,7 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget)
AutoResolveRefLayers resolve(mCompositionManager);
if (aTarget) {
mLayerManager->BeginTransactionWithDrawTarget(aTarget);
mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect);
} else {
mLayerManager->BeginTransaction();
}
@ -720,13 +719,13 @@ CompositorParent::DidComposite()
}
void
CompositorParent::ForceComposeToTarget(DrawTarget* aTarget)
CompositorParent::ForceComposeToTarget(DrawTarget* aTarget, const nsIntRect* aRect)
{
PROFILER_LABEL("CompositorParent", "ForceComposeToTarget");
AutoRestore<bool> override(mOverrideComposeReadiness);
mOverrideComposeReadiness = true;
CompositeToTarget(aTarget);
CompositeToTarget(aTarget, aRect);
}
bool
@ -1136,7 +1135,7 @@ public:
virtual bool RecvResume() MOZ_OVERRIDE { return true; }
virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE;
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
SurfaceDescriptor* aOutSnapshot)
const nsIntRect& aRect)
{ return true; }
virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; }
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) { return true; }

View File

@ -86,7 +86,7 @@ public:
virtual bool RecvResume() MOZ_OVERRIDE;
virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE;
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
SurfaceDescriptor* aOutSnapshot) MOZ_OVERRIDE;
const nsIntRect& aRect) MOZ_OVERRIDE;
virtual bool RecvFlushRendering() MOZ_OVERRIDE;
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) MOZ_OVERRIDE;
@ -254,8 +254,8 @@ private:
virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
virtual void ScheduleTask(CancelableTask*, int);
void Composite();
void CompositeToTarget(gfx::DrawTarget* aTarget);
void ForceComposeToTarget(gfx::DrawTarget* aTarget);
void CompositeToTarget(gfx::DrawTarget* aTarget, const nsIntRect* aRect = nullptr);
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const nsIntRect* aRect = nullptr);
void SetEGLSurfaceSize(int width, int height);

View File

@ -72,8 +72,7 @@ parent:
//
// NB: this message will result in animations, transforms, effects,
// and so forth being interpolated. That's what we want to happen.
sync MakeSnapshot(SurfaceDescriptor inSnapshot)
returns (SurfaceDescriptor outSnapshot);
sync MakeSnapshot(SurfaceDescriptor inSnapshot, nsIntRect dirtyRect);
// Make sure any pending composites are started immediately and
// block until they are completed.

View File

@ -1250,7 +1250,7 @@ CompositorOGL::EndFrame()
mWidget->GetBounds(rect);
}
RefPtr<DrawTarget> target = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(rect.width, rect.height), SurfaceFormat::B8G8R8A8);
CopyToTarget(target, mCurrentRenderTarget->GetTransform());
CopyToTarget(target, nsIntPoint(), mCurrentRenderTarget->GetTransform());
WriteSnapshotToDumpFile(this, target);
}
@ -1261,7 +1261,7 @@ CompositorOGL::EndFrame()
LayerScope::EndFrame(mGLContext);
if (mTarget) {
CopyToTarget(mTarget, mCurrentRenderTarget->GetTransform());
CopyToTarget(mTarget, mTargetBounds.TopLeft(), mCurrentRenderTarget->GetTransform());
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
mCurrentRenderTarget = nullptr;
return;
@ -1360,7 +1360,7 @@ CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
// This lets us reftest and screenshot content rendered externally
if (mTarget) {
MakeCurrent();
CopyToTarget(mTarget, aTransform);
CopyToTarget(mTarget, mTargetBounds.TopLeft(), aTransform);
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
if (mTexturePool) {
@ -1388,7 +1388,7 @@ CompositorOGL::SetDestinationSurfaceSize(const gfx::IntSize& aSize)
}
void
CompositorOGL::CopyToTarget(DrawTarget *aTarget, const gfx::Matrix& aTransform)
CompositorOGL::CopyToTarget(DrawTarget* aTarget, const nsIntPoint& aTopLeft, const gfx::Matrix& aTransform)
{
IntRect rect;
if (mUseExternalSurfaceSize) {
@ -1423,6 +1423,8 @@ CompositorOGL::CopyToTarget(DrawTarget *aTarget, const gfx::Matrix& aTransform)
glToCairoTransform.Scale(1.0, -1.0);
glToCairoTransform.Translate(0.0, -height);
glToCairoTransform.PostTranslate(-aTopLeft.x, -aTopLeft.y);
Matrix oldMatrix = aTarget->GetTransform();
aTarget->SetTransform(glToCairoTransform);
Rect floatRect = Rect(rect.x, rect.y, rect.width, rect.height);

View File

@ -235,11 +235,6 @@ public:
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE;
virtual void SetTargetContext(gfx::DrawTarget* aTarget) MOZ_OVERRIDE
{
mTarget = aTarget;
}
virtual void PrepareViewport(const gfx::IntSize& aSize,
const gfx::Matrix& aWorldTransform) MOZ_OVERRIDE;
@ -279,11 +274,6 @@ private:
return gfx::ToIntSize(mWidgetSize);
}
/**
* Context target, nullptr when drawing directly to our swap chain.
*/
RefPtr<gfx::DrawTarget> mTarget;
/** Widget associated with this compositor */
nsIWidget *mWidget;
nsIntSize mWidgetSize;
@ -382,7 +372,7 @@ private:
* Copies the content of our backbuffer to the set transaction target.
* Does not restore the target FBO, so only call from EndFrame.
*/
void CopyToTarget(gfx::DrawTarget* aTarget, const gfx::Matrix& aWorldMatrix);
void CopyToTarget(gfx::DrawTarget* aTarget, const nsIntPoint& aTopLeft, const gfx::Matrix& aWorldMatrix);
/**
* Implements the flipping of the y-axis to convert from layers/compositor