put an arena on GrSurfaceDrawContext

This is part one of two CLs. In this CL, I put a
sk_sp<GrArenas> on GrSurfaceFillContext where GrArenas wraps
a SkArenaAlloc to add ref counting. Creating
a GrOpsTask shares the GrArenas with the ops task. New plumbing
was added to GR_DRAW_OP_TEST_DEFINE to allow a proper
GrSurfaceDrawContext to be passed to GrAtlasTextOp's
GR_DRAW_OP_TEST_DEFINE so the arena will have a proper lifetime.

The second CL will work on replacing GrOpsTask's fAllocators
system with the shared arena.

Change-Id: Ife3be0ab265441cbffab360f2808f5eed86db8b3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/392936
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2021-04-05 18:38:35 -04:00 committed by Skia Commit-Bot
parent 9267183cf4
commit 5a2de5e72f
13 changed files with 68 additions and 37 deletions

View File

@ -27,10 +27,11 @@ void GrDrawRandomOp(SkRandom*, GrSurfaceDrawContext*, GrPaint&&);
/** GrDrawOp subclasses should define test factory functions using this macro. */ /** GrDrawOp subclasses should define test factory functions using this macro. */
#define GR_DRAW_OP_TEST_DEFINE(Op) \ #define GR_DRAW_OP_TEST_DEFINE(Op) \
GrOp::Owner Op##__Test(GrPaint&& paint, SkRandom* random, \ GrOp::Owner Op##__Test(GrPaint&& paint, SkRandom* random, \
GrRecordingContext* context, int numSamples) GrRecordingContext* context, \
GrSurfaceDrawContext* sdc, int numSamples)
#define GR_DRAW_OP_TEST_FRIEND(Op) \ #define GR_DRAW_OP_TEST_FRIEND(Op) \
friend GrOp::OpOwner Op##__Test(GrPaint&& paint, SkRandom* random, \ friend GrOp::OpOwner Op##__Test(GrPaint&&, SkRandom*, \
GrRecordingContext* context, int numSamples) GrRecordingContext*, GrSurfaceDrawContext*, int)
/** Helper for op test factories to pick a random stencil state. */ /** Helper for op test factories to pick a random stencil state. */
const GrUserStencilSettings* GrGetRandomStencil(SkRandom* random, GrContext_Base*); const GrUserStencilSettings* GrGetRandomStencil(SkRandom* random, GrContext_Base*);

View File

@ -659,14 +659,17 @@ void GrDrawingManager::closeActiveOpsTask() {
} }
sk_sp<GrOpsTask> GrDrawingManager::newOpsTask(GrSurfaceProxyView surfaceView, sk_sp<GrOpsTask> GrDrawingManager::newOpsTask(GrSurfaceProxyView surfaceView,
sk_sp<GrArenas> arenas,
bool flushTimeOpsTask) { bool flushTimeOpsTask) {
SkDEBUGCODE(this->validate()); SkDEBUGCODE(this->validate());
SkASSERT(fContext); SkASSERT(fContext);
this->closeActiveOpsTask(); this->closeActiveOpsTask();
sk_sp<GrOpsTask> opsTask(new GrOpsTask(this, std::move(surfaceView), sk_sp<GrOpsTask> opsTask(new GrOpsTask(this,
fContext->priv().auditTrail())); std::move(surfaceView),
fContext->priv().auditTrail(),
std::move(arenas)));
SkASSERT(this->getLastRenderTask(opsTask->target(0)) == opsTask.get()); SkASSERT(this->getLastRenderTask(opsTask->target(0)) == opsTask.get());
if (flushTimeOpsTask) { if (flushTimeOpsTask) {

View File

@ -23,6 +23,7 @@
// Enabling this will print out which path renderers are being chosen // Enabling this will print out which path renderers are being chosen
#define GR_PATH_RENDERER_SPEW 0 #define GR_PATH_RENDERER_SPEW 0
class GrArenas;
class GrCoverageCountingPathRenderer; class GrCoverageCountingPathRenderer;
class GrGpuBuffer; class GrGpuBuffer;
class GrOnFlushCallbackObject; class GrOnFlushCallbackObject;
@ -46,7 +47,9 @@ public:
void freeGpuResources(); void freeGpuResources();
// OpsTasks created at flush time are stored and handled different from the others. // OpsTasks created at flush time are stored and handled different from the others.
sk_sp<GrOpsTask> newOpsTask(GrSurfaceProxyView, bool flushTimeOpsTask); sk_sp<GrOpsTask> newOpsTask(GrSurfaceProxyView,
sk_sp<GrArenas> arenas,
bool flushTimeOpsTask);
// Create a render task that can resolve MSAA and/or regenerate mipmap levels on proxies. This // Create a render task that can resolve MSAA and/or regenerate mipmap levels on proxies. This
// method will only add the new render task to the list. It is up to the caller to call // method will only add the new render task to the list. It is up to the caller to call

View File

@ -355,11 +355,13 @@ inline void GrOpsTask::OpChain::validate() const {
GrOpsTask::GrOpsTask(GrDrawingManager* drawingMgr, GrOpsTask::GrOpsTask(GrDrawingManager* drawingMgr,
GrSurfaceProxyView view, GrSurfaceProxyView view,
GrAuditTrail* auditTrail) GrAuditTrail* auditTrail,
sk_sp<GrArenas> arenas)
: GrRenderTask() : GrRenderTask()
, fAuditTrail(auditTrail) , fAuditTrail(auditTrail)
, fTargetSwizzle(view.swizzle()) , fTargetSwizzle(view.swizzle())
, fTargetOrigin(view.origin()) , fTargetOrigin(view.origin())
, fArenas{std::move(arenas)}
SkDEBUGCODE(, fNumClips(0)) { SkDEBUGCODE(, fNumClips(0)) {
fAllocators.push_back(std::make_unique<SkArenaAlloc>(4096)); fAllocators.push_back(std::make_unique<SkArenaAlloc>(4096));
this->addTarget(drawingMgr, view.detachProxy()); this->addTarget(drawingMgr, view.detachProxy());

View File

@ -32,14 +32,21 @@ class GrClearOp;
class GrGpuBuffer; class GrGpuBuffer;
class GrRenderTargetProxy; class GrRenderTargetProxy;
class GrArenas : public SkNVRefCnt<GrArenas> {
public:
SkArenaAlloc* arenaAlloc() { return &fArenaAlloc; }
private:
SkArenaAlloc fArenaAlloc{1024};
};
class GrOpsTask : public GrRenderTask { class GrOpsTask : public GrRenderTask {
private: private:
using DstProxyView = GrXferProcessor::DstProxyView; using DstProxyView = GrXferProcessor::DstProxyView;
public: public:
// The Arenas must outlive the GrOpsTask, either by preserving the context that owns // Manage the arenas life time by maintaining are reference to it.
// the pool, or by moving the pool to the DDL that takes over the GrOpsTask. GrOpsTask(GrDrawingManager*, GrSurfaceProxyView, GrAuditTrail*, sk_sp<GrArenas>);
GrOpsTask(GrDrawingManager*, GrSurfaceProxyView, GrAuditTrail*);
~GrOpsTask() override; ~GrOpsTask() override;
GrOpsTask* asOpsTask() override { return this; } GrOpsTask* asOpsTask() override { return this; }
@ -268,6 +275,7 @@ private:
// MDB TODO: 4096 for the first allocation may be huge overkill. Gather statistics to determine // MDB TODO: 4096 for the first allocation may be huge overkill. Gather statistics to determine
// the correct size. // the correct size.
SkSTArray<1, std::unique_ptr<SkArenaAlloc>> fAllocators; SkSTArray<1, std::unique_ptr<SkArenaAlloc>> fAllocators;
sk_sp<GrArenas> fArenas;
SkDEBUGCODE(int fNumClips;) SkDEBUGCODE(int fNumClips;)
// TODO: We could look into this being a set if we find we're adding a lot of duplicates that is // TODO: We could look into this being a set if we find we're adding a lot of duplicates that is

View File

@ -17,6 +17,7 @@
#include "src/gpu/GrColorInfo.h" #include "src/gpu/GrColorInfo.h"
#include "src/gpu/GrDataUtils.h" #include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrImageInfo.h" #include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrOpsTask.h"
#include "src/gpu/GrPixmap.h" #include "src/gpu/GrPixmap.h"
#include "src/gpu/GrRenderTask.h" #include "src/gpu/GrRenderTask.h"
#include "src/gpu/GrSurfaceProxy.h" #include "src/gpu/GrSurfaceProxy.h"

View File

@ -342,8 +342,8 @@ GrOpsTask* GrSurfaceFillContext::getOpsTask() {
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
if (!fOpsTask || fOpsTask->isClosed()) { if (!fOpsTask || fOpsTask->isClosed()) {
sk_sp<GrOpsTask> newOpsTask = this->drawingManager()->newOpsTask(this->writeSurfaceView(), sk_sp<GrOpsTask> newOpsTask = this->drawingManager()->newOpsTask(
fFlushTimeOpsTask); this->writeSurfaceView(), fArenas, fFlushTimeOpsTask);
if (fOpsTask) { if (fOpsTask) {
this->willReplaceOpsTask(fOpsTask.get(), newOpsTask.get()); this->willReplaceOpsTask(fOpsTask.get(), newOpsTask.get());
} }

View File

@ -195,6 +195,8 @@ public:
bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); } bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }
GrMipmapped mipmapped() const; GrMipmapped mipmapped() const;
SkArenaAlloc* arenaAlloc() { return fArenas->arenaAlloc(); }
#if GR_TEST_UTILS #if GR_TEST_UTILS
GrOpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); } GrOpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); }
#endif #endif
@ -241,6 +243,9 @@ private:
// reason, the GrOpsTask should only ever be accessed via 'getOpsTask'. // reason, the GrOpsTask should only ever be accessed via 'getOpsTask'.
sk_sp<GrOpsTask> fOpsTask; sk_sp<GrOpsTask> fOpsTask;
// The arenas shared by the OpsTask.
sk_sp<GrArenas> fArenas = sk_make_sp<GrArenas>();
bool fFlushTimeOpsTask; bool fFlushTimeOpsTask;
using INHERITED = GrSurfaceContext; using INHERITED = GrSurfaceContext;

View File

@ -112,8 +112,12 @@ auto GrAtlasTextOp::Geometry::MakeForBlob(const GrAtlasSubRun& subRun,
SkPoint drawOrigin, SkPoint drawOrigin,
SkIRect clipRect, SkIRect clipRect,
sk_sp<GrTextBlob> blob, sk_sp<GrTextBlob> blob,
const SkPMColor4f& color) -> Geometry* { const SkPMColor4f& color,
return new Geometry{subRun, SkArenaAlloc* alloc) -> Geometry* {
// Bypass the automatic dtor behavior in SkArenaAlloc. I'm leaving this up to the Op to run
// all geometry dtors for now.
void* geo = alloc->makeBytesAlignedTo(sizeof(Geometry), alignof(Geometry));
return new(geo) Geometry{subRun,
drawMatrix, drawMatrix,
drawOrigin, drawOrigin,
clipRect, clipRect,
@ -522,10 +526,6 @@ GrOp::Owner GrAtlasTextOp::CreateOpTestingOnly(GrSurfaceDrawContext* rtc,
} }
GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) { GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) {
// Setup dummy SkPaint / GrPaint / GrSurfaceDrawContext
auto rtc = GrSurfaceDrawContext::Make(
context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kApprox, {1024, 1024});
SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrixInvertible(random)); SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrixInvertible(random));
SkPaint skPaint; SkPaint skPaint;
@ -548,8 +548,7 @@ GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) {
int xInt = (random->nextU() % kMaxTrans) * xPos; int xInt = (random->nextU() % kMaxTrans) * xPos;
int yInt = (random->nextU() % kMaxTrans) * yPos; int yInt = (random->nextU() % kMaxTrans) * yPos;
return GrAtlasTextOp::CreateOpTestingOnly( return GrAtlasTextOp::CreateOpTestingOnly(sdc, skPaint, font, matrixProvider, text, xInt, yInt);
rtc.get(), skPaint, font, matrixProvider, text, xInt, yInt);
} }
#endif #endif

View File

@ -27,7 +27,7 @@ public:
~GrAtlasTextOp() override { ~GrAtlasTextOp() override {
for (const Geometry* g = fHead; g != nullptr;) { for (const Geometry* g = fHead; g != nullptr;) {
const Geometry* next = g->fNext; const Geometry* next = g->fNext;
delete g; g->~Geometry();
g = next; g = next;
} }
} }
@ -67,7 +67,8 @@ public:
SkPoint drawOrigin, SkPoint drawOrigin,
SkIRect clipRect, SkIRect clipRect,
sk_sp<GrTextBlob> blob, sk_sp<GrTextBlob> blob,
const SkPMColor4f& color); const SkPMColor4f& color,
SkArenaAlloc* alloc);
void fillVertexData(void* dst, int offset, int count) const; void fillVertexData(void* dst, int offset, int count) const;

View File

@ -677,7 +677,8 @@ DirectMaskSubRun::makeAtlasTextOp(const GrClip* clip, const SkMatrixProvider& vi
drawOrigin, drawOrigin,
clipRect, clipRect,
sk_ref_sp<GrTextBlob>(fBlob), sk_ref_sp<GrTextBlob>(fBlob),
drawingColor); drawingColor,
sdc->arenaAlloc());
GrRecordingContext* const rContext = sdc->recordingContext(); GrRecordingContext* const rContext = sdc->recordingContext();
GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(rContext, GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(rContext,
@ -970,7 +971,8 @@ TransformedMaskSubRun::makeAtlasTextOp(const GrClip* clip,
drawOrigin, drawOrigin,
SkIRect::MakeEmpty(), SkIRect::MakeEmpty(),
sk_ref_sp<GrTextBlob>(fBlob), sk_ref_sp<GrTextBlob>(fBlob),
drawingColor); drawingColor,
sdc->arenaAlloc());
GrRecordingContext* const rContext = sdc->recordingContext(); GrRecordingContext* const rContext = sdc->recordingContext();
GrOp::Owner op = GrOp::Make<GrAtlasTextOp>( GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(
@ -1252,7 +1254,8 @@ SDFTSubRun::makeAtlasTextOp(const GrClip* clip,
drawOrigin, drawOrigin,
SkIRect::MakeEmpty(), SkIRect::MakeEmpty(),
sk_ref_sp<GrTextBlob>(fBlob), sk_ref_sp<GrTextBlob>(fBlob),
drawingColor); drawingColor,
sdc->arenaAlloc());
GrRecordingContext* const rContext = sdc->recordingContext(); GrRecordingContext* const rContext = sdc->recordingContext();
GrOp::Owner op = GrOp::Make<GrAtlasTextOp>( GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(

View File

@ -205,6 +205,7 @@ DEF_GPUTEST(OpChainTest, reporter, /*ctxInfo*/) {
bool repeat = false; bool repeat = false;
Combinable combinable; Combinable combinable;
GrDrawingManager* drawingMgr = dContext->priv().drawingManager(); GrDrawingManager* drawingMgr = dContext->priv().drawingManager();
sk_sp<GrArenas> arenas = sk_make_sp<GrArenas>();
for (int p = 0; p < kNumPermutations; ++p) { for (int p = 0; p < kNumPermutations; ++p) {
for (int i = 0; i < kNumOps - 2 && !repeat; ++i) { for (int i = 0; i < kNumOps - 2 && !repeat; ++i) {
// The current implementation of nextULessThan() is biased. :( // The current implementation of nextULessThan() is biased. :(
@ -221,7 +222,8 @@ DEF_GPUTEST(OpChainTest, reporter, /*ctxInfo*/) {
&tracker); &tracker);
GrOpsTask opsTask(drawingMgr, GrOpsTask opsTask(drawingMgr,
GrSurfaceProxyView(proxy, kOrigin, writeSwizzle), GrSurfaceProxyView(proxy, kOrigin, writeSwizzle),
dContext->priv().auditTrail()); dContext->priv().auditTrail(),
arenas);
// This assumes the particular values of kRanges. // This assumes the particular values of kRanges.
std::fill_n(result, result_width(), -1); std::fill_n(result, result_width(), -1);
std::fill_n(validResult, result_width(), -1); std::fill_n(validResult, result_width(), -1);

View File

@ -53,7 +53,7 @@ int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
#define DRAW_OP_TEST_EXTERN(Op) \ #define DRAW_OP_TEST_EXTERN(Op) \
extern GrOp::Owner Op##__Test(GrPaint&&, SkRandom*, \ extern GrOp::Owner Op##__Test(GrPaint&&, SkRandom*, \
GrRecordingContext*, int numSamples) GrRecordingContext*, GrSurfaceDrawContext*, int)
#define DRAW_OP_TEST_ENTRY(Op) Op##__Test #define DRAW_OP_TEST_ENTRY(Op) Op##__Test
DRAW_OP_TEST_EXTERN(AAConvexPathOp); DRAW_OP_TEST_EXTERN(AAConvexPathOp);
@ -81,7 +81,7 @@ DRAW_OP_TEST_EXTERN(TextureOp);
void GrDrawRandomOp(SkRandom* random, GrSurfaceDrawContext* surfaceDrawContext, GrPaint&& paint) { void GrDrawRandomOp(SkRandom* random, GrSurfaceDrawContext* surfaceDrawContext, GrPaint&& paint) {
auto context = surfaceDrawContext->recordingContext(); auto context = surfaceDrawContext->recordingContext();
using MakeDrawOpFn = GrOp::Owner (GrPaint&&, SkRandom*, using MakeDrawOpFn = GrOp::Owner (GrPaint&&, SkRandom*,
GrRecordingContext*, int numSamples); GrRecordingContext*, GrSurfaceDrawContext*, int numSamples);
static constexpr MakeDrawOpFn* gFactories[] = { static constexpr MakeDrawOpFn* gFactories[] = {
DRAW_OP_TEST_ENTRY(AAConvexPathOp), DRAW_OP_TEST_ENTRY(AAConvexPathOp),
DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp), DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp),
@ -108,8 +108,11 @@ void GrDrawRandomOp(SkRandom* random, GrSurfaceDrawContext* surfaceDrawContext,
static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories); static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories);
uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal)); uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal));
auto op = gFactories[index]( auto op = gFactories[index](std::move(paint),
std::move(paint), random, context, surfaceDrawContext->numSamples()); random,
context,
surfaceDrawContext,
surfaceDrawContext->numSamples());
// Creating a GrAtlasTextOp my not produce an op if for example, it is totally outside the // Creating a GrAtlasTextOp my not produce an op if for example, it is totally outside the
// render target context. // render target context.