Bug 1478815 part 9 - Add ability to create a DrawTargetCapture that can flush to its destination draw target. r=bas

This commit adds the ability to create a different kind of DrawTargetCapture which
has a limit on the size of which its CaptureCommandList can grow before it is
synchronously flushed to its destination DrawTarget.

Special care is taken to not do a sync flush until we would need to resize
the backing store of the CaptureCommandList. This allows us to not waste
memory we've already allocated.

The async painting content clients are updated to use it, and get a default
value from a new preference.

MozReview-Commit-ID: CJL7ffvaRzR

--HG--
extra : rebase_source : 546d9838808320c51d9ceef0ed0ffcbb88a16269
This commit is contained in:
Ryan Hunt 2018-07-26 16:33:07 -05:00
Родитель af49011c30
Коммит 8b6aa26413
9 изменённых файлов: 74 добавлений и 9 удалений

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

@ -1632,6 +1632,18 @@ public:
static already_AddRefed<DrawTarget>
CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
/**
* Create a DrawTarget that captures the drawing commands to eventually be replayed
* onto the DrawTarget provided. An optional byte size can be provided as a limit
* for the CaptureCommandList. When the limit is reached, the CaptureCommandList
* will be replayed to the target and then cleared.
*
* @param aSize Size of the area this DT will capture.
* @param aFlushBytes The byte limit at which to flush the CaptureCommandList
*/
static already_AddRefed<DrawTargetCapture>
CreateCaptureDrawTargetForTarget(gfx::DrawTarget* aTarget, size_t aFlushBytes = 0);
/**
* Create a DrawTarget that captures the drawing commands and can be replayed
* onto a compatible DrawTarget afterwards.

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

@ -11,11 +11,19 @@ namespace mozilla {
namespace gfx {
CaptureCommandList::~CaptureCommandList()
{
Clear();
}
void
CaptureCommandList::Clear()
{
for (iterator iter(*this); !iter.Done(); iter.Next()) {
DrawingCommand* cmd = iter.Get();
cmd->~DrawingCommand();
}
mLastCommand = nullptr;
mStorage.clear();
}
} // namespace gfx

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

@ -64,6 +64,17 @@ public:
return Append<T>();
}
template <typename T>
bool BufferWillAlloc() const {
return mStorage.size() + sizeof(uint32_t) + sizeof(T) > mStorage.capacity();
}
size_t BufferCapacity() const {
return mStorage.capacity();
}
void Clear();
class iterator
{
public:

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

@ -23,13 +23,27 @@ DrawTargetCaptureImpl::~DrawTargetCaptureImpl()
}
}
DrawTargetCaptureImpl::DrawTargetCaptureImpl(gfx::DrawTarget* aTarget, size_t aFlushBytes)
: mSnapshot(nullptr),
mStride(0),
mSurfaceAllocationSize(0),
mFlushBytes(aFlushBytes)
{
mSize = aTarget->GetSize();
mFormat = aTarget->GetFormat();
SetPermitSubpixelAA(aTarget->GetPermitSubpixelAA());
mRefDT = aTarget;
}
DrawTargetCaptureImpl::DrawTargetCaptureImpl(BackendType aBackend,
const IntSize& aSize,
SurfaceFormat aFormat)
: mSize(aSize),
mSnapshot(nullptr),
mStride(0),
mSurfaceAllocationSize(0)
mSurfaceAllocationSize(0),
mFlushBytes(0)
{
RefPtr<DrawTarget> screenRefDT =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
@ -75,6 +89,7 @@ DrawTargetCaptureImpl::Init(const IntSize& aSize, DrawTarget* aRefDT)
void
DrawTargetCaptureImpl::InitForData(int32_t aStride, size_t aSurfaceAllocationSize)
{
MOZ_ASSERT(!mFlushBytes);
mStride = aStride;
mSurfaceAllocationSize = aSurfaceAllocationSize;
}

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

@ -24,6 +24,7 @@ class DrawTargetCaptureImpl : public DrawTargetCapture
friend class SourceSurfaceCapture;
public:
DrawTargetCaptureImpl(gfx::DrawTarget* aTarget, size_t aFlushBytes);
DrawTargetCaptureImpl(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat);
bool Init(const IntSize& aSize, DrawTarget* aRefDT);
@ -156,6 +157,12 @@ protected:
void MarkChanged();
private:
void FlushCommandBuffer()
{
ReplayToDrawTarget(mRefDT, Matrix());
mCommands.Clear();
}
// This storage system was used to minimize the amount of heap allocations
// that are required while recording. It should be noted there's no
// guarantees on the alignments of DrawingCommands allocated in this array.
@ -164,6 +171,11 @@ private:
if (T::AffectsSnapshot) {
MarkChanged();
}
if (mFlushBytes &&
mCommands.BufferWillAlloc<T>() &&
mCommands.BufferCapacity() > mFlushBytes) {
FlushCommandBuffer();
}
return mCommands.Append<T>();
}
template<typename T>
@ -171,6 +183,11 @@ private:
if (T::AffectsSnapshot) {
MarkChanged();
}
if (mFlushBytes &&
mCommands.BufferWillAlloc<T>() &&
mCommands.BufferCapacity() > mFlushBytes) {
FlushCommandBuffer();
}
return mCommands.ReuseOrAppend<T>();
}
@ -192,6 +209,7 @@ private:
std::vector<PushedLayer> mPushedLayers;
CaptureCommandList mCommands;
size_t mFlushBytes;
};
} // namespace gfx

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

@ -451,6 +451,12 @@ Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT
return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT, aSize);
}
already_AddRefed<DrawTargetCapture>
Factory::CreateCaptureDrawTargetForTarget(gfx::DrawTarget* aTarget, size_t aFlushBytes)
{
return MakeAndAddRef<DrawTargetCaptureImpl>(aTarget, aFlushBytes);
}
already_AddRefed<DrawTargetCapture>
Factory::CreateCaptureDrawTarget(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
{

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

@ -83,10 +83,7 @@ RotatedBuffer::BeginCapture()
MOZ_ASSERT(!mCapture);
MOZ_ASSERT(target);
mCapture =
Factory::CreateCaptureDrawTarget(target->GetBackendType(),
target->GetSize(),
target->GetFormat());
mCapture = Factory::CreateCaptureDrawTargetForTarget(target, gfxPrefs::LayersOMTPCaptureLimit());
}
RefPtr<gfx::DrawTargetCapture>

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

@ -711,10 +711,7 @@ TileClient::AcquireBackBuffer(CompositableClient& aCompositable,
// Construct a capture draw target if necessary
RefPtr<DrawTargetCapture> capture;
if (aFlags & TilePaintFlags::Async) {
capture =
Factory::CreateCaptureDrawTarget(target->GetBackendType(),
target->GetSize(),
target->GetFormat());
capture = Factory::CreateCaptureDrawTargetForTarget(target, gfxPrefs::LayersOMTPCaptureLimit());
target = capture;
}

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

@ -634,6 +634,7 @@ private:
DECL_GFX_PREF(Once, "layers.mlgpu.enable-container-resizing", AdvancedLayersEnableContainerResizing, bool, true);
DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false);
DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);
DECL_GFX_PREF(Once, "layers.omtp.capture-limit", LayersOMTPCaptureLimit, uint32_t, 25 * 1024 * 1024);
DECL_GFX_PREF(Live, "layers.omtp.dump-capture", LayersOMTPDumpCapture, bool, false);
DECL_GFX_PREF(Once, "layers.omtp.paint-workers", LayersOMTPPaintWorkers, int32_t, 1);
DECL_GFX_PREF(Live, "layers.omtp.release-capture-on-main-thread", LayersOMTPReleaseCaptureOnMainThread, bool, false);