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 : f646862dcef7a480b21dfb7ddb1fa165338ba506
extra : source : b865a866fe5a3257615cb54b7e5e790cc9331988
This commit is contained in:
Ryan Hunt 2018-07-26 16:33:07 -05:00
Родитель 2dd7814423
Коммит 16e8c5d426
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);
@ -158,6 +159,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.
@ -166,6 +173,11 @@ private:
if (T::AffectsSnapshot) {
MarkChanged();
}
if (mFlushBytes &&
mCommands.BufferWillAlloc<T>() &&
mCommands.BufferCapacity() > mFlushBytes) {
FlushCommandBuffer();
}
return mCommands.Append<T>();
}
template<typename T>
@ -173,6 +185,11 @@ private:
if (T::AffectsSnapshot) {
MarkChanged();
}
if (mFlushBytes &&
mCommands.BufferWillAlloc<T>() &&
mCommands.BufferCapacity() > mFlushBytes) {
FlushCommandBuffer();
}
return mCommands.ReuseOrAppend<T>();
}
@ -194,6 +211,7 @@ private:
std::vector<PushedLayer> mPushedLayers;
CaptureCommandList mCommands;
size_t mFlushBytes;
};
} // namespace gfx

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

@ -452,6 +452,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);