mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-04 11:26:09 +00:00
Bug 1592031 - Rename CompositorScreenshotGrabber to ScreenshotGrabber and give it a more generic interface. r=mattwoodrow
There already exist 3 implementations of this stuff and I don't want to add another one for the WR OS compositor path. (The three implementations are: CompositorScreenshotGrabber, MLGPUScreenshotGrabber and RendererScreenshotGrabber.) The interface has been designed in such a way that the MLGPU and WR implementations should be able to use it but I haven't written the code to convert them. Differential Revision: https://phabricator.services.mozilla.com/D59157
This commit is contained in:
parent
686ff6882f
commit
a941eccf36
@ -4,7 +4,7 @@
|
||||
* 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 "CompositorScreenshotGrabber.h"
|
||||
#include "ScreenshotGrabber.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
@ -21,37 +21,38 @@ namespace mozilla {
|
||||
using namespace gfx;
|
||||
|
||||
namespace layers {
|
||||
namespace profiler_screenshots {
|
||||
|
||||
/**
|
||||
* The actual implementation of screenshot grabbing.
|
||||
* The CompositorScreenshotGrabberImpl object is destroyed if the profiler is
|
||||
* The ScreenshotGrabberImpl object is destroyed if the profiler is
|
||||
* disabled and MaybeGrabScreenshot notices it.
|
||||
*/
|
||||
class CompositorScreenshotGrabberImpl final {
|
||||
class ScreenshotGrabberImpl final {
|
||||
public:
|
||||
explicit CompositorScreenshotGrabberImpl(const IntSize& aBufferSize);
|
||||
~CompositorScreenshotGrabberImpl();
|
||||
explicit ScreenshotGrabberImpl(const IntSize& aBufferSize);
|
||||
~ScreenshotGrabberImpl();
|
||||
|
||||
void GrabScreenshot(Compositor* aCompositor);
|
||||
void GrabScreenshot(Window& aWindow);
|
||||
void ProcessQueue();
|
||||
|
||||
private:
|
||||
struct QueueItem final {
|
||||
mozilla::TimeStamp mTimeStamp;
|
||||
RefPtr<AsyncReadbackBuffer> mScreenshotBuffer;
|
||||
gfx::IntSize mScreenshotSize;
|
||||
gfx::IntSize mWindowSize;
|
||||
IntSize mScreenshotSize;
|
||||
IntSize mWindowSize;
|
||||
uintptr_t mWindowIdentifier;
|
||||
};
|
||||
|
||||
RefPtr<CompositingRenderTarget> ScaleDownWindowTargetToSize(
|
||||
Compositor* aCompositor, const gfx::IntSize& aDestSize,
|
||||
CompositingRenderTarget* aWindowTarget, size_t aLevel);
|
||||
RefPtr<RenderSource> ScaleDownWindowRenderSourceToSize(
|
||||
Window& aWindow, const IntSize& aDestSize,
|
||||
RenderSource* aWindowRenderSource, size_t aLevel);
|
||||
|
||||
already_AddRefed<AsyncReadbackBuffer> TakeNextBuffer(Compositor* aCompositor);
|
||||
already_AddRefed<AsyncReadbackBuffer> TakeNextBuffer(Window& aWindow);
|
||||
void ReturnBuffer(AsyncReadbackBuffer* aBuffer);
|
||||
|
||||
nsTArray<RefPtr<CompositingRenderTarget>> mTargets;
|
||||
nsTArray<RefPtr<DownscaleTarget>> mCachedLevels;
|
||||
nsTArray<RefPtr<AsyncReadbackBuffer>> mAvailableBuffers;
|
||||
Maybe<QueueItem> mCurrentFrameQueueItem;
|
||||
nsTArray<QueueItem> mQueue;
|
||||
@ -59,26 +60,29 @@ class CompositorScreenshotGrabberImpl final {
|
||||
const IntSize mBufferSize;
|
||||
};
|
||||
|
||||
CompositorScreenshotGrabber::CompositorScreenshotGrabber() = default;
|
||||
} // namespace profiler_screenshots
|
||||
|
||||
CompositorScreenshotGrabber::~CompositorScreenshotGrabber() = default;
|
||||
ScreenshotGrabber::ScreenshotGrabber() = default;
|
||||
|
||||
void CompositorScreenshotGrabber::MaybeGrabScreenshot(Compositor* aCompositor) {
|
||||
ScreenshotGrabber::~ScreenshotGrabber() = default;
|
||||
|
||||
void ScreenshotGrabber::MaybeGrabScreenshot(
|
||||
profiler_screenshots::Window& aWindow) {
|
||||
if (ProfilerScreenshots::IsEnabled()) {
|
||||
if (!mImpl) {
|
||||
mImpl = MakeUnique<CompositorScreenshotGrabberImpl>(
|
||||
mImpl = MakeUnique<profiler_screenshots::ScreenshotGrabberImpl>(
|
||||
ProfilerScreenshots::ScreenshotSize());
|
||||
}
|
||||
mImpl->GrabScreenshot(aCompositor);
|
||||
mImpl->GrabScreenshot(aWindow);
|
||||
} else if (mImpl) {
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void CompositorScreenshotGrabber::MaybeProcessQueue() {
|
||||
void ScreenshotGrabber::MaybeProcessQueue() {
|
||||
if (ProfilerScreenshots::IsEnabled()) {
|
||||
if (!mImpl) {
|
||||
mImpl = MakeUnique<CompositorScreenshotGrabberImpl>(
|
||||
mImpl = MakeUnique<profiler_screenshots::ScreenshotGrabberImpl>(
|
||||
ProfilerScreenshots::ScreenshotSize());
|
||||
}
|
||||
mImpl->ProcessQueue();
|
||||
@ -87,66 +91,62 @@ void CompositorScreenshotGrabber::MaybeProcessQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
void CompositorScreenshotGrabber::NotifyEmptyFrame() {
|
||||
void ScreenshotGrabber::NotifyEmptyFrame() {
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
PROFILER_ADD_MARKER("NoCompositorScreenshot because nothing changed",
|
||||
GRAPHICS);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CompositorScreenshotGrabber::Destroy() { mImpl = nullptr; }
|
||||
void ScreenshotGrabber::Destroy() { mImpl = nullptr; }
|
||||
|
||||
CompositorScreenshotGrabberImpl::CompositorScreenshotGrabberImpl(
|
||||
const IntSize& aBufferSize)
|
||||
namespace profiler_screenshots {
|
||||
|
||||
ScreenshotGrabberImpl::ScreenshotGrabberImpl(const IntSize& aBufferSize)
|
||||
: mBufferSize(aBufferSize) {}
|
||||
|
||||
CompositorScreenshotGrabberImpl::~CompositorScreenshotGrabberImpl() {
|
||||
ScreenshotGrabberImpl::~ScreenshotGrabberImpl() {
|
||||
// Any queue items in mQueue or mCurrentFrameQueueItem will be lost.
|
||||
// That's ok: Either the profiler has stopped and we don't care about these
|
||||
// screenshots, or the window is closing and we don't really need the last
|
||||
// few frames from the window.
|
||||
}
|
||||
|
||||
// Scale down aWindowTarget into a CompositingRenderTarget of size
|
||||
// mBufferSize * (1 << aLevel) and return that CompositingRenderTarget.
|
||||
// Scale down aWindowRenderSource into a RenderSource of size
|
||||
// mBufferSize * (1 << aLevel) and return that RenderSource.
|
||||
// Don't scale down by more than a factor of 2 with a single scaling operation,
|
||||
// because it'll look bad. If higher scales are needed, use another
|
||||
// intermediate target by calling this function recursively with aLevel + 1.
|
||||
RefPtr<CompositingRenderTarget>
|
||||
CompositorScreenshotGrabberImpl::ScaleDownWindowTargetToSize(
|
||||
Compositor* aCompositor, const IntSize& aDestSize,
|
||||
CompositingRenderTarget* aWindowTarget, size_t aLevel) {
|
||||
if (aLevel == mTargets.Length()) {
|
||||
mTargets.AppendElement(aCompositor->CreateRenderTarget(
|
||||
IntRect(IntPoint(), mBufferSize * (1 << aLevel)), INIT_MODE_NONE));
|
||||
RefPtr<RenderSource> ScreenshotGrabberImpl::ScaleDownWindowRenderSourceToSize(
|
||||
Window& aWindow, const IntSize& aDestSize,
|
||||
RenderSource* aWindowRenderSource, size_t aLevel) {
|
||||
if (aLevel == mCachedLevels.Length()) {
|
||||
mCachedLevels.AppendElement(
|
||||
aWindow.CreateDownscaleTarget(mBufferSize * (1 << aLevel)));
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(aLevel < mTargets.Length());
|
||||
MOZ_RELEASE_ASSERT(aLevel < mCachedLevels.Length());
|
||||
|
||||
RefPtr<CompositingRenderTarget> sourceTarget = aWindowTarget;
|
||||
IntSize sourceSize = aWindowTarget->GetSize();
|
||||
if (aWindowTarget->GetSize().width > aDestSize.width * 2) {
|
||||
RefPtr<RenderSource> renderSource = aWindowRenderSource;
|
||||
IntSize sourceSize = aWindowRenderSource->Size();
|
||||
if (sourceSize.width > aDestSize.width * 2) {
|
||||
sourceSize = aDestSize * 2;
|
||||
sourceTarget = ScaleDownWindowTargetToSize(aCompositor, sourceSize,
|
||||
aWindowTarget, aLevel + 1);
|
||||
renderSource = ScaleDownWindowRenderSourceToSize(
|
||||
aWindow, sourceSize, aWindowRenderSource, aLevel + 1);
|
||||
}
|
||||
|
||||
if (sourceTarget) {
|
||||
aCompositor->SetRenderTarget(mTargets[aLevel]);
|
||||
if (aCompositor->BlitRenderTarget(sourceTarget, sourceSize, aDestSize)) {
|
||||
return mTargets[aLevel];
|
||||
if (renderSource) {
|
||||
if (mCachedLevels[aLevel]->DownscaleFrom(
|
||||
renderSource, IntRect({}, sourceSize), IntRect({}, aDestSize))) {
|
||||
return mCachedLevels[aLevel]->AsRenderSource();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CompositorScreenshotGrabberImpl::GrabScreenshot(Compositor* aCompositor) {
|
||||
RefPtr<CompositingRenderTarget> previousTarget =
|
||||
aCompositor->GetCurrentRenderTarget();
|
||||
void ScreenshotGrabberImpl::GrabScreenshot(Window& aWindow) {
|
||||
RefPtr<RenderSource> windowRenderSource = aWindow.GetWindowContents();
|
||||
|
||||
RefPtr<CompositingRenderTarget> windowTarget =
|
||||
aCompositor->GetWindowRenderTarget();
|
||||
|
||||
if (!windowTarget) {
|
||||
if (!windowRenderSource) {
|
||||
PROFILER_ADD_MARKER(
|
||||
"NoCompositorScreenshot because of unsupported compositor "
|
||||
"configuration",
|
||||
@ -154,24 +154,22 @@ void CompositorScreenshotGrabberImpl::GrabScreenshot(Compositor* aCompositor) {
|
||||
return;
|
||||
}
|
||||
|
||||
Size windowSize(windowTarget->GetSize());
|
||||
Size windowSize(windowRenderSource->Size());
|
||||
float scale = std::min(mBufferSize.width / windowSize.width,
|
||||
mBufferSize.height / windowSize.height);
|
||||
IntSize scaledSize = IntSize::Round(windowSize * scale);
|
||||
RefPtr<CompositingRenderTarget> scaledTarget =
|
||||
ScaleDownWindowTargetToSize(aCompositor, scaledSize, windowTarget, 0);
|
||||
|
||||
// Restore the old render target.
|
||||
aCompositor->SetRenderTarget(previousTarget);
|
||||
RefPtr<RenderSource> scaledTarget = ScaleDownWindowRenderSourceToSize(
|
||||
aWindow, scaledSize, windowRenderSource, 0);
|
||||
|
||||
if (!scaledTarget) {
|
||||
PROFILER_ADD_MARKER(
|
||||
"NoCompositorScreenshot because ScaleDownWindowTargetToSize failed",
|
||||
"NoCompositorScreenshot because ScaleDownWindowRenderSourceToSize "
|
||||
"failed",
|
||||
GRAPHICS);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<AsyncReadbackBuffer> buffer = TakeNextBuffer(aCompositor);
|
||||
RefPtr<AsyncReadbackBuffer> buffer = TakeNextBuffer(aWindow);
|
||||
if (!buffer) {
|
||||
PROFILER_ADD_MARKER(
|
||||
"NoCompositorScreenshot because AsyncReadbackBuffer creation failed",
|
||||
@ -179,32 +177,32 @@ void CompositorScreenshotGrabberImpl::GrabScreenshot(Compositor* aCompositor) {
|
||||
return;
|
||||
}
|
||||
|
||||
aCompositor->ReadbackRenderTarget(scaledTarget, buffer);
|
||||
buffer->CopyFrom(scaledTarget);
|
||||
|
||||
// This QueueItem will be added to the queue at the end of the next call to
|
||||
// ProcessQueue(). This ensures that the buffer isn't mapped into main memory
|
||||
// until the next frame. If we did it in this frame, we'd block on the GPU.
|
||||
mCurrentFrameQueueItem = Some(QueueItem{
|
||||
TimeStamp::Now(), std::move(buffer), scaledSize, windowTarget->GetSize(),
|
||||
reinterpret_cast<uintptr_t>(static_cast<void*>(this))});
|
||||
mCurrentFrameQueueItem =
|
||||
Some(QueueItem{TimeStamp::Now(), std::move(buffer), scaledSize,
|
||||
windowRenderSource->Size(),
|
||||
reinterpret_cast<uintptr_t>(static_cast<void*>(this))});
|
||||
}
|
||||
|
||||
already_AddRefed<AsyncReadbackBuffer>
|
||||
CompositorScreenshotGrabberImpl::TakeNextBuffer(Compositor* aCompositor) {
|
||||
already_AddRefed<AsyncReadbackBuffer> ScreenshotGrabberImpl::TakeNextBuffer(
|
||||
Window& aWindow) {
|
||||
if (!mAvailableBuffers.IsEmpty()) {
|
||||
RefPtr<AsyncReadbackBuffer> buffer = mAvailableBuffers[0];
|
||||
mAvailableBuffers.RemoveElementAt(0);
|
||||
return buffer.forget();
|
||||
}
|
||||
return aCompositor->CreateAsyncReadbackBuffer(mBufferSize);
|
||||
return aWindow.CreateAsyncReadbackBuffer(mBufferSize);
|
||||
}
|
||||
|
||||
void CompositorScreenshotGrabberImpl::ReturnBuffer(
|
||||
AsyncReadbackBuffer* aBuffer) {
|
||||
void ScreenshotGrabberImpl::ReturnBuffer(AsyncReadbackBuffer* aBuffer) {
|
||||
mAvailableBuffers.AppendElement(aBuffer);
|
||||
}
|
||||
|
||||
void CompositorScreenshotGrabberImpl::ProcessQueue() {
|
||||
void ScreenshotGrabberImpl::ProcessQueue() {
|
||||
if (!mQueue.IsEmpty()) {
|
||||
if (!mProfilerScreenshots) {
|
||||
mProfilerScreenshots = new ProfilerScreenshots();
|
||||
@ -227,5 +225,6 @@ void CompositorScreenshotGrabberImpl::ProcessQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace profiler_screenshots
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
132
gfx/layers/ScreenshotGrabber.h
Normal file
132
gfx/layers/ScreenshotGrabber.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_layers_ScreenshotGrabber_h
|
||||
#define mozilla_layers_ScreenshotGrabber_h
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
namespace profiler_screenshots {
|
||||
class Window;
|
||||
class RenderSource;
|
||||
class DownscaleTarget;
|
||||
class AsyncReadbackBuffer;
|
||||
|
||||
class ScreenshotGrabberImpl;
|
||||
} // namespace profiler_screenshots
|
||||
|
||||
/**
|
||||
* Used by various renderers / layer managers to grab snapshots from the window
|
||||
* and submit them to the Gecko profiler.
|
||||
* Doesn't do any work if the profiler is not running or the "screenshots"
|
||||
* feature is not enabled.
|
||||
* Screenshots are scaled down to fit within a fixed size, and read back to
|
||||
* main memory using async readback. Scaling is done in multiple scale-by-0.5x
|
||||
* steps using DownscaleTarget::CopyFrom, and readback is done using
|
||||
* AsyncReadbackBuffers.
|
||||
*/
|
||||
class ScreenshotGrabber final {
|
||||
public:
|
||||
ScreenshotGrabber();
|
||||
~ScreenshotGrabber();
|
||||
|
||||
// Scale the contents of aWindow's current render target into an
|
||||
// appropriately sized DownscaleTarget and read its contents into an
|
||||
// AsyncReadbackBuffer. The AsyncReadbackBuffer is not mapped into main
|
||||
// memory until the second call to MaybeProcessQueue() after this call to
|
||||
// MaybeGrabScreenshot().
|
||||
void MaybeGrabScreenshot(profiler_screenshots::Window& aWindow);
|
||||
|
||||
// Map the contents of any outstanding AsyncReadbackBuffers from previous
|
||||
// composites into main memory and submit each screenshot to the profiler.
|
||||
void MaybeProcessQueue();
|
||||
|
||||
// Insert a special profiler marker for a composite that didn't do any actual
|
||||
// compositing, so that the profiler knows why no screenshot was taken for
|
||||
// this frame.
|
||||
void NotifyEmptyFrame();
|
||||
|
||||
// Destroy all Window-related resources that this class is holding on to.
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
// non-null while ProfilerScreenshots::IsEnabled() returns true
|
||||
UniquePtr<profiler_screenshots::ScreenshotGrabberImpl> mImpl;
|
||||
};
|
||||
|
||||
// Interface definitions.
|
||||
|
||||
namespace profiler_screenshots {
|
||||
|
||||
class Window {
|
||||
public:
|
||||
virtual already_AddRefed<RenderSource> GetWindowContents() = 0;
|
||||
virtual already_AddRefed<DownscaleTarget> CreateDownscaleTarget(
|
||||
const gfx::IntSize& aSize) = 0;
|
||||
virtual already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer(
|
||||
const gfx::IntSize& aSize) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Window() {}
|
||||
};
|
||||
|
||||
class RenderSource {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RenderSource)
|
||||
|
||||
const auto& Size() const { return mSize; }
|
||||
|
||||
protected:
|
||||
explicit RenderSource(const gfx::IntSize& aSize) : mSize(aSize) {}
|
||||
virtual ~RenderSource() {}
|
||||
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
class DownscaleTarget {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DownscaleTarget)
|
||||
|
||||
virtual already_AddRefed<RenderSource> AsRenderSource() = 0;
|
||||
|
||||
const auto& Size() const { return mSize; }
|
||||
virtual bool DownscaleFrom(RenderSource* aSource,
|
||||
const gfx::IntRect& aSourceRect,
|
||||
const gfx::IntRect& aDestRect) = 0;
|
||||
|
||||
protected:
|
||||
explicit DownscaleTarget(const gfx::IntSize& aSize) : mSize(aSize) {}
|
||||
virtual ~DownscaleTarget() {}
|
||||
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
class AsyncReadbackBuffer {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(
|
||||
mozilla::layers::profiler_screenshots::AsyncReadbackBuffer)
|
||||
|
||||
const auto& Size() const { return mSize; }
|
||||
virtual void CopyFrom(RenderSource* aSource) = 0;
|
||||
virtual bool MapAndCopyInto(gfx::DataSourceSurface* aSurface,
|
||||
const gfx::IntSize& aReadSize) = 0;
|
||||
|
||||
protected:
|
||||
explicit AsyncReadbackBuffer(const gfx::IntSize& aSize) : mSize(aSize) {}
|
||||
virtual ~AsyncReadbackBuffer() {}
|
||||
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
} // namespace profiler_screenshots
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layers_ScreenshotGrabber_h
|
@ -1,60 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_layers_CompositorScreenshotGrabber_h
|
||||
#define mozilla_layers_CompositorScreenshotGrabber_h
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Compositor;
|
||||
class CompositorScreenshotGrabberImpl;
|
||||
|
||||
/**
|
||||
* Used by LayerManagerComposite to grab snapshots from the compositor and
|
||||
* submit them to the Gecko profiler.
|
||||
* Doesn't do any work if the profiler is not running or the "screenshots"
|
||||
* feature is not enabled.
|
||||
* Screenshots are scaled down to fit within a fixed size, and read back to
|
||||
* main memory using async readback. Scaling is done in multiple scale-by-0.5x
|
||||
* steps using CompositingRenderTargets and Compositor::BlitFromRenderTarget,
|
||||
* and readback is done using AsyncReadbackBuffers.
|
||||
*/
|
||||
class CompositorScreenshotGrabber final {
|
||||
public:
|
||||
CompositorScreenshotGrabber();
|
||||
~CompositorScreenshotGrabber();
|
||||
|
||||
// Scale the contents of aCompositor's current render target into an
|
||||
// approapriately sized CompositingRenderTarget and read its contents into an
|
||||
// AsyncReadbackBuffer. The AsyncReadbackBuffer is not mapped into main
|
||||
// memory until the second call to MaybeProcessQueue() after this call to
|
||||
// MaybeGrabScreenshot().
|
||||
void MaybeGrabScreenshot(Compositor* aCompositor);
|
||||
|
||||
// Map the contents of any outstanding AsyncReadbackBuffers from previous
|
||||
// composites into main memory and submit each screenshot to the profiler.
|
||||
void MaybeProcessQueue();
|
||||
|
||||
// Insert a special profiler marker for a composite that didn't do any actual
|
||||
// compositing, so that the profiler knows why no screenshot was taken for
|
||||
// this frame.
|
||||
void NotifyEmptyFrame();
|
||||
|
||||
// Destroy all Compositor-related resources that this class is holding on to.
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
// non-null while ProfilerScreenshots::IsEnabled() returns true
|
||||
UniquePtr<CompositorScreenshotGrabberImpl> mImpl;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layers_CompositorScreenshotGrabber_h
|
@ -89,6 +89,21 @@ class ImageLayer;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
class WindowLMC : public profiler_screenshots::Window {
|
||||
public:
|
||||
explicit WindowLMC(Compositor* aCompositor) : mCompositor(aCompositor) {}
|
||||
|
||||
already_AddRefed<profiler_screenshots::RenderSource> GetWindowContents()
|
||||
override;
|
||||
already_AddRefed<profiler_screenshots::DownscaleTarget> CreateDownscaleTarget(
|
||||
const IntSize& aSize) override;
|
||||
already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
|
||||
CreateAsyncReadbackBuffer(const IntSize& aSize) override;
|
||||
|
||||
protected:
|
||||
Compositor* mCompositor;
|
||||
};
|
||||
|
||||
static LayerComposite* ToLayerComposite(Layer* aLayer) {
|
||||
return static_cast<LayerComposite*>(aLayer->ImplData());
|
||||
}
|
||||
@ -939,6 +954,7 @@ LayerManagerComposite::PushGroupForLayerEffects() {
|
||||
mCompositor->SetRenderTarget(mTwoPassTmpTarget);
|
||||
return previousTarget;
|
||||
}
|
||||
|
||||
void LayerManagerComposite::PopGroupForLayerEffects(
|
||||
RefPtr<CompositingRenderTarget> aPreviousTarget, IntRect aClipRect,
|
||||
bool aGrayscaleEffect, bool aInvertEffect, float aContrastEffect) {
|
||||
@ -1233,7 +1249,8 @@ bool LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion,
|
||||
|
||||
RootLayer()->Cleanup();
|
||||
|
||||
mProfilerScreenshotGrabber.MaybeGrabScreenshot(mCompositor);
|
||||
WindowLMC window(mCompositor);
|
||||
mProfilerScreenshotGrabber.MaybeGrabScreenshot(window);
|
||||
|
||||
if (mCompositionRecorder) {
|
||||
bool hasContentPaint = std::any_of(
|
||||
@ -1663,5 +1680,106 @@ void LayerManagerComposite::PlatformSyncBeforeReplyUpdate() {}
|
||||
|
||||
#endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
|
||||
|
||||
class RenderSourceLMC : public profiler_screenshots::RenderSource {
|
||||
public:
|
||||
explicit RenderSourceLMC(CompositingRenderTarget* aRT)
|
||||
: RenderSource(aRT->GetSize()), mRT(aRT) {}
|
||||
|
||||
const auto& RenderTarget() { return mRT; }
|
||||
|
||||
protected:
|
||||
virtual ~RenderSourceLMC() {}
|
||||
|
||||
RefPtr<CompositingRenderTarget> mRT;
|
||||
};
|
||||
|
||||
class DownscaleTargetLMC : public profiler_screenshots::DownscaleTarget {
|
||||
public:
|
||||
explicit DownscaleTargetLMC(CompositingRenderTarget* aRT, Compositor* aCompositor)
|
||||
: profiler_screenshots::DownscaleTarget(aRT->GetSize()),
|
||||
mRenderSource(new RenderSourceLMC(aRT)),
|
||||
mCompositor(aCompositor) {}
|
||||
|
||||
already_AddRefed<profiler_screenshots::RenderSource> AsRenderSource()
|
||||
override {
|
||||
return do_AddRef(mRenderSource);
|
||||
}
|
||||
|
||||
bool DownscaleFrom(profiler_screenshots::RenderSource* aSource,
|
||||
const IntRect& aSourceRect,
|
||||
const IntRect& aDestRect) override {
|
||||
MOZ_RELEASE_ASSERT(aSourceRect.TopLeft() == IntPoint());
|
||||
MOZ_RELEASE_ASSERT(aDestRect.TopLeft() == IntPoint());
|
||||
RefPtr<CompositingRenderTarget> previousTarget =
|
||||
mCompositor->GetCurrentRenderTarget();
|
||||
|
||||
mCompositor->SetRenderTarget(mRenderSource->RenderTarget());
|
||||
bool result = mCompositor->BlitRenderTarget(
|
||||
static_cast<RenderSourceLMC*>(aSource)->RenderTarget(),
|
||||
aSourceRect.Size(), aDestRect.Size());
|
||||
|
||||
// Restore the old render target.
|
||||
mCompositor->SetRenderTarget(previousTarget);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~DownscaleTargetLMC() {}
|
||||
|
||||
RefPtr<RenderSourceLMC> mRenderSource;
|
||||
Compositor* mCompositor;
|
||||
};
|
||||
|
||||
class AsyncReadbackBufferLMC
|
||||
: public profiler_screenshots::AsyncReadbackBuffer {
|
||||
public:
|
||||
AsyncReadbackBufferLMC(mozilla::layers::AsyncReadbackBuffer* aARB,
|
||||
Compositor* aCompositor)
|
||||
: profiler_screenshots::AsyncReadbackBuffer(aARB->GetSize()),
|
||||
mARB(aARB),
|
||||
mCompositor(aCompositor) {}
|
||||
void CopyFrom(profiler_screenshots::RenderSource* aSource) override {
|
||||
mCompositor->ReadbackRenderTarget(
|
||||
static_cast<RenderSourceLMC*>(aSource)->RenderTarget(), mARB);
|
||||
}
|
||||
bool MapAndCopyInto(DataSourceSurface* aSurface,
|
||||
const IntSize& aReadSize) override {
|
||||
return mARB->MapAndCopyInto(aSurface, aReadSize);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~AsyncReadbackBufferLMC() {}
|
||||
|
||||
RefPtr<mozilla::layers::AsyncReadbackBuffer> mARB;
|
||||
Compositor* mCompositor;
|
||||
};
|
||||
|
||||
already_AddRefed<profiler_screenshots::RenderSource>
|
||||
WindowLMC::GetWindowContents() {
|
||||
RefPtr<CompositingRenderTarget> rt = mCompositor->GetWindowRenderTarget();
|
||||
if (!rt) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeAndAddRef<RenderSourceLMC>(rt);
|
||||
}
|
||||
|
||||
already_AddRefed<profiler_screenshots::DownscaleTarget>
|
||||
WindowLMC::CreateDownscaleTarget(const IntSize& aSize) {
|
||||
RefPtr<CompositingRenderTarget> rt =
|
||||
mCompositor->CreateRenderTarget(IntRect({}, aSize), INIT_MODE_NONE);
|
||||
return MakeAndAddRef<DownscaleTargetLMC>(rt, mCompositor);
|
||||
}
|
||||
|
||||
already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
|
||||
WindowLMC::CreateAsyncReadbackBuffer(const IntSize& aSize) {
|
||||
RefPtr<AsyncReadbackBuffer> carb =
|
||||
mCompositor->CreateAsyncReadbackBuffer(aSize);
|
||||
if (!carb) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeAndAddRef<AsyncReadbackBufferLMC>(carb, mCompositor);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "nscore.h" // for nsAString, etc
|
||||
#include "LayerTreeInvalidation.h"
|
||||
#include "mozilla/layers/CompositorScreenshotGrabber.h"
|
||||
#include "mozilla/layers/ScreenshotGrabber.h"
|
||||
|
||||
class gfxContext;
|
||||
|
||||
@ -491,7 +491,7 @@ class LayerManagerComposite final : public HostLayerManager {
|
||||
bool mIsCompositorReady;
|
||||
|
||||
RefPtr<CompositingRenderTarget> mTwoPassTmpTarget;
|
||||
CompositorScreenshotGrabber mProfilerScreenshotGrabber;
|
||||
ScreenshotGrabber mProfilerScreenshotGrabber;
|
||||
RefPtr<TextRenderer> mTextRenderer;
|
||||
RefPtr<NativeLayerRoot> mNativeLayerRoot;
|
||||
RefPtr<SurfacePoolHandle> mSurfacePoolHandle;
|
||||
|
@ -150,7 +150,6 @@ EXPORTS.mozilla.layers += [
|
||||
'composite/AsyncCompositionManager.h',
|
||||
'composite/CanvasLayerComposite.h',
|
||||
'composite/ColorLayerComposite.h',
|
||||
'composite/CompositorScreenshotGrabber.h',
|
||||
'composite/ContainerLayerComposite.h',
|
||||
'composite/ContentHost.h',
|
||||
'composite/Diagnostics.h',
|
||||
@ -246,6 +245,7 @@ EXPORTS.mozilla.layers += [
|
||||
'RepaintRequest.h',
|
||||
'RotatedBuffer.h',
|
||||
'SampleTime.h',
|
||||
'ScreenshotGrabber.h',
|
||||
'ScrollableLayerGuid.h',
|
||||
'ShareableCanvasRenderer.h',
|
||||
'SourceSurfaceSharedData.h',
|
||||
@ -429,7 +429,6 @@ UNIFIED_SOURCES += [
|
||||
'composite/CanvasLayerComposite.cpp',
|
||||
'composite/ColorLayerComposite.cpp',
|
||||
'composite/CompositableHost.cpp',
|
||||
'composite/CompositorScreenshotGrabber.cpp',
|
||||
'composite/ContainerLayerComposite.cpp',
|
||||
'composite/ContentHost.cpp',
|
||||
'composite/Diagnostics.cpp',
|
||||
@ -525,6 +524,7 @@ UNIFIED_SOURCES += [
|
||||
'RenderTrace.cpp',
|
||||
'RotatedBuffer.cpp',
|
||||
'SampleTime.cpp',
|
||||
'ScreenshotGrabber.cpp',
|
||||
'ShareableCanvasRenderer.cpp',
|
||||
'SourceSurfaceSharedData.cpp',
|
||||
'SourceSurfaceVolatileData.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user