author | Barret Rennie <barret@brennie.ca> |
Mon, 21 Jan 2019 17:42:21 +0000 | |
changeset 454715 | a115176a8faa34bb59da329fc5d458f5ab7f9267 |
parent 454714 | 53d1b01b992467d1ab77ab9023444098280ba7a6 |
child 454716 | 28e336f7b9da63ef319650a7bd698289574a4f11 |
push id | 35411 |
push user | csabou@mozilla.com |
push date | Tue, 22 Jan 2019 03:53:40 +0000 |
treeherder | mozilla-central@ada22b635f8d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mstange |
bugs | 1444447 |
milestone | 66.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
gfx/layers/basic/BasicCompositor.cpp | file | annotate | diff | comparison | revisions | |
gfx/layers/basic/BasicCompositor.h | file | annotate | diff | comparison | revisions |
--- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -1,27 +1,29 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * 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 "BasicCompositor.h" #include "BasicLayersImpl.h" // for FillRectWithMask +#include "GeckoProfiler.h" #include "TextureHostBasic.h" #include "mozilla/layers/Effects.h" #include "nsIWidget.h" #include "gfx2DGlue.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/Helpers.h" #include "mozilla/gfx/Tools.h" #include "mozilla/gfx/ssse3-scaler.h" #include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/SSE.h" +#include "gfxPlatform.h" #include "gfxUtils.h" #include "YCbCrUtils.h" #include <algorithm> #include "ImageContainer.h" #include "gfxPrefs.h" namespace mozilla { using namespace mozilla::gfx; @@ -174,17 +176,19 @@ class WrappingTextureSourceYCbCrBasic : BufferTextureHost* mTexture; const gfx::IntSize mSize; RefPtr<gfx::DataSourceSurface> mSurface; bool mNeedsUpdate; }; BasicCompositor::BasicCompositor(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget) - : Compositor(aWidget, aParent), mIsPendingEndRemoteDrawing(false) { + : Compositor(aWidget, aParent), + mIsPendingEndRemoteDrawing(false), + mFullWindowRenderTarget(nullptr) { MOZ_COUNT_CTOR(BasicCompositor); mMaxTextureSize = Factory::GetMaxSurfaceSize(gfxVars::ContentBackend()); } BasicCompositor::~BasicCompositor() { MOZ_COUNT_DTOR(BasicCompositor); } bool BasicCompositor::Initialize(nsCString* const out_failureReason) { @@ -276,16 +280,20 @@ BasicCompositor::CreateRenderTargetForWi // Adjust bounds rect to account for new origin at (0, 0). if (windowRect.Size() != mDrawTarget->GetSize()) { windowRect.ExpandToEnclose(IntPoint(0, 0)); } rt = new BasicCompositingRenderTarget(mDrawTarget, windowRect); if (!aClearRect.IsEmpty()) { IntRect clearRect = aClearRect.ToUnknownRect(); mDrawTarget->ClearRect(Rect(clearRect - rt->GetOrigin())); + + if (mFullWindowRenderTarget) { + mFullWindowRenderTarget->mDrawTarget->ClearRect(Rect(clearRect)); + } } } return rt.forget(); } already_AddRefed<DataTextureSource> BasicCompositor::CreateDataTextureSource( TextureFlags aFlags) { @@ -802,38 +810,57 @@ void BasicCompositor::DrawGeometry( } } buffer->PopClip(); } void BasicCompositor::ClearRect(const gfx::Rect& aRect) { mRenderTarget->mDrawTarget->ClearRect(aRect); + + if (mFullWindowRenderTarget) { + mFullWindowRenderTarget->mDrawTarget->ClearRect(aRect); + } } void BasicCompositor::BeginFrame( const nsIntRegion& aInvalidRegion, const gfx::IntRect* aClipRectIn, const gfx::IntRect& aRenderBounds, const nsIntRegion& aOpaqueRegion, 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()); - LayoutDeviceIntRegion invalidRegionSafe; - // Sometimes the invalid region is larger than we want to draw. - invalidRegionSafe.And( - LayoutDeviceIntRegion::FromUnknownRegion(aInvalidRegion), intRect); +#ifdef MOZ_GECKO_PROFILER + const bool shouldInvalidateWindow = + (profiler_feature_active(ProfilerFeature::Screenshots) && + (!mFullWindowRenderTarget || + mFullWindowRenderTarget->mDrawTarget->GetSize() != + rect.ToUnknownRect().Size())); +#else + const bool shouldInvalidateWindow = false; +#endif // MOZ_GECKO_PROFILER - mInvalidRegion = invalidRegionSafe; + if (shouldInvalidateWindow) { + mInvalidRegion = intRect; + } else { + LayoutDeviceIntRegion invalidRegionSafe; + // Sometimes the invalid region is larger than we want to draw. + invalidRegionSafe.And( + LayoutDeviceIntRegion::FromUnknownRegion(aInvalidRegion), intRect); + + mInvalidRegion = invalidRegionSafe; + } + mInvalidRect = mInvalidRegion.GetBounds(); if (aRenderBoundsOut) { *aRenderBoundsOut = IntRect(); } BufferMode bufferMode = BufferMode::BUFFERED; if (mTarget) { @@ -874,16 +901,37 @@ void BasicCompositor::BeginFrame( // Prevent CreateRenderTargetForWindow from clearing unwanted area. gfxUtils::ClipToRegion(mDrawTarget, mInvalidRegion.ToUnknownRegion()); // Setup an intermediate render target to buffer all compositing. We will // copy this into mDrawTarget (the widget), and/or mTarget in EndFrame() RefPtr<CompositingRenderTarget> target = CreateRenderTargetForWindow(mInvalidRect, clearRect, bufferMode); +#ifdef MOZ_GECKO_PROFILER + if (profiler_feature_active(ProfilerFeature::Screenshots)) { + IntSize windowSize = rect.ToUnknownRect().Size(); + + // On some platforms (notably Linux with X11) we do not always have a + // full-size draw target. While capturing profiles with screenshots, we need + // access to a full-size target so we can record the contents. + if (!mFullWindowRenderTarget || + mFullWindowRenderTarget->mDrawTarget->GetSize() != windowSize) { + // We have either (1) just started recording and not yet allocated a + // buffer or (2) are already recording and have resized the window. In + // either case, we need a new render target. + RefPtr<gfx::DrawTarget> drawTarget = mDrawTarget->CreateSimilarDrawTarget( + windowSize, mDrawTarget->GetFormat()); + + mFullWindowRenderTarget = + new BasicCompositingRenderTarget(drawTarget, rect); + } + } +#endif // MOZ_GECKO_PROFILER + mDrawTarget->PopClip(); if (!target) { if (!mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); } return; } @@ -926,16 +974,25 @@ void BasicCompositor::EndFrame() { IntRectToRect(mInvalidRegion.GetBounds()).ToUnknownRect(), ColorPattern(Color(r, g, b, 0.2f))); } // Pop aInvalidregion mRenderTarget->mDrawTarget->PopClip(); TryToEndRemoteDrawing(); + +#ifdef MOZ_GECKO_PROFILER + // If we are no longer recording a profile, we can drop the render target if + // it exists. + if (mFullWindowRenderTarget && + !profiler_feature_active(ProfilerFeature::Screenshots)) { + mFullWindowRenderTarget = nullptr; + } +#endif // MOZ_GECKO_PROFILER } void BasicCompositor::TryToEndRemoteDrawing(bool aForceToEnd) { if (mIsDestroyed || !mRenderTarget) { return; } // It it is not a good timing for EndRemoteDrawing, defter to call it. @@ -946,31 +1003,47 @@ void BasicCompositor::TryToEndRemoteDraw RefPtr<BasicCompositor> self = this; RefPtr<Runnable> runnable = NS_NewRunnableFunction("layers::BasicCompositor::TryToEndRemoteDrawing", [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. - RefPtr<SourceSurface> source = mWidget->EndBackBufferDrawing(); + if (mRenderTarget->mDrawTarget != mDrawTarget || mFullWindowRenderTarget) { + RefPtr<SourceSurface> source; - nsIntPoint offset = mTarget ? mTargetBounds.TopLeft() : nsIntPoint(); + if (mRenderTarget->mDrawTarget != mDrawTarget) { + source = mWidget->EndBackBufferDrawing(); + + // Note: Most platforms require us to buffer drawing to the widget + // surface. That's why we don't draw to mDrawTarget directly. + 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 - // pixels. - for (auto iter = mInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - mDrawTarget->CopySurface(source, - r.ToUnknownRect() - mRenderTarget->GetOrigin(), - r.TopLeft().ToUnknownPoint() - offset); + // 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 pixels. + for (auto iter = mInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { + const LayoutDeviceIntRect& r = iter.Get(); + mDrawTarget->CopySurface(source, + r.ToUnknownRect() - mRenderTarget->GetOrigin(), + r.TopLeft().ToUnknownPoint() - offset); + } + } else { + source = mRenderTarget->mDrawTarget->Snapshot(); + } + + if (mFullWindowRenderTarget) { + for (auto iter = mInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { + const LayoutDeviceIntRect& r = iter.Get(); + mFullWindowRenderTarget->mDrawTarget->CopySurface( + source, r.ToUnknownRect(), r.TopLeft().ToUnknownPoint()); + } + + mFullWindowRenderTarget->mDrawTarget->Flush(); } } if (aForceToEnd || !mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); } mDrawTarget = nullptr;
--- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -82,16 +82,21 @@ class BasicCompositor : public Composito virtual bool SupportsEffect(EffectTypes aEffect) override; bool SupportsLayerGeometry() const override; virtual void SetRenderTarget(CompositingRenderTarget* aSource) override { mRenderTarget = static_cast<BasicCompositingRenderTarget*>(aSource); mRenderTarget->BindRenderTarget(); } + + virtual CompositingRenderTarget* GetWindowRenderTarget() const override { + return mFullWindowRenderTarget; + } + virtual CompositingRenderTarget* GetCurrentRenderTarget() const override { return mRenderTarget; } virtual void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect, const EffectChain& aEffectChain, gfx::Float aOpacity, const gfx::Matrix4x4& aTransform, const gfx::Rect& aVisibleRect) override; @@ -156,16 +161,21 @@ class BasicCompositor : public Composito // The current render target for drawing RefPtr<BasicCompositingRenderTarget> mRenderTarget; LayoutDeviceIntRect mInvalidRect; LayoutDeviceIntRegion mInvalidRegion; uint32_t mMaxTextureSize; bool mIsPendingEndRemoteDrawing; + + // mDrawTarget will not be the full window on all platforms. We therefore need + // to keep a full window render target around when we are capturing + // screenshots on those platforms. + RefPtr<BasicCompositingRenderTarget> mFullWindowRenderTarget; }; BasicCompositor* AssertBasicCompositor(Compositor* aCompositor); } // namespace layers } // namespace mozilla #endif /* MOZILLA_GFX_BASICCOMPOSITOR_H */