Make the GrSmallPathAtlasMgr a flush-time object
This will allow the small path renderer to be used w/ DDLs.
This is broken out of the omnibus CL:
https://skia-review.googlesource.com/c/skia/+/307776 (Split the small path renderer into record-time and flush-time pieces)
Bug: 1108408
Change-Id: I64cc6ff677d0aead7cf2f097c0e7fbb15b49d49d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309304
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/GrDirectContext.h b/include/gpu/GrDirectContext.h
index 5347878..5d84fcc 100644
--- a/include/gpu/GrDirectContext.h
+++ b/include/gpu/GrDirectContext.h
@@ -88,7 +88,7 @@
private:
std::unique_ptr<GrAtlasManager> fAtlasManager;
- // The small path renderer atlas will be stored here
+ std::unique_ptr<GrSmallPathAtlasMgr> fSmallPathAtlasMgr;
typedef GrContext INHERITED;
};
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index 4ae1831..6f04a5f 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -59,16 +59,25 @@
void GrDirectContext::abandonContext() {
INHERITED::abandonContext();
+ if (fSmallPathAtlasMgr) {
+ fSmallPathAtlasMgr->reset();
+ }
fAtlasManager->freeAll();
}
void GrDirectContext::releaseResourcesAndAbandonContext() {
INHERITED::releaseResourcesAndAbandonContext();
+ if (fSmallPathAtlasMgr) {
+ fSmallPathAtlasMgr->reset();
+ }
fAtlasManager->freeAll();
}
void GrDirectContext::freeGpuResources() {
this->flushAndSubmit();
+ if (fSmallPathAtlasMgr) {
+ fSmallPathAtlasMgr->reset();
+ }
fAtlasManager->freeAll();
INHERITED::freeGpuResources();
@@ -115,8 +124,17 @@
}
GrSmallPathAtlasMgr* GrDirectContext::onGetSmallPathAtlasMgr() {
- // The small path renderer atlas will be created here
- return nullptr;
+ if (!fSmallPathAtlasMgr) {
+ fSmallPathAtlasMgr = std::make_unique<GrSmallPathAtlasMgr>();
+
+ this->priv().addOnFlushCallbackObject(fSmallPathAtlasMgr.get());
+ }
+
+ if (!fSmallPathAtlasMgr->initAtlas(this->proxyProvider(), this->caps())) {
+ return nullptr;
+ }
+
+ return fSmallPathAtlasMgr.get();
}
#ifdef SK_GL
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index 337f7cd..ed7d532 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -59,9 +59,7 @@
fChain.push_back(sk_make_sp<GrAALinearizingConvexPathRenderer>());
}
if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) {
- auto spr = sk_make_sp<GrSmallPathRenderer>();
- spr->addToOnFlushCallbacks(context);
- fChain.push_back(std::move(spr));
+ fChain.push_back(sk_make_sp<GrSmallPathRenderer>());
}
if (options.fGpuPathRenderers & GpuPathRenderers::kStencilAndCover) {
auto direct = context->asDirectContext();
diff --git a/src/gpu/ops/GrSmallPathAtlasMgr.cpp b/src/gpu/ops/GrSmallPathAtlasMgr.cpp
index 7fbb232..ca9b5bf 100644
--- a/src/gpu/ops/GrSmallPathAtlasMgr.cpp
+++ b/src/gpu/ops/GrSmallPathAtlasMgr.cpp
@@ -30,6 +30,7 @@
delete shapeData;
}
+ fShapeList.reset();
fShapeCache.reset();
#ifdef DF_PATH_TRACKING
diff --git a/src/gpu/ops/GrSmallPathAtlasMgr.h b/src/gpu/ops/GrSmallPathAtlasMgr.h
index 7c5be41..17ab571 100644
--- a/src/gpu/ops/GrSmallPathAtlasMgr.h
+++ b/src/gpu/ops/GrSmallPathAtlasMgr.h
@@ -18,7 +18,12 @@
class GrStyledShape;
/**
- * This class manages the small path renderer's atlas.
+ * This class manages the small path renderer's atlas. It solely operates at flush time. Thus
+ * the small path renderer will generate ops at record time but the location of the ops' source
+ * data and even the number of proxies to be used will not be determined until the recorded
+ * DAGs/DDLs are (re)played.
+ *
+ * TODO: investigate fusing this class and the GrAtlasManager.
*/
class GrSmallPathAtlasMgr : public GrOnFlushCallbackObject,
public GrDrawOpAtlas::EvictionCallback,
@@ -55,6 +60,10 @@
}
}
+ // This object has the same lifetime as the GrContext so we want it to survive freeGpuResources
+ // calls
+ bool retainOnFreeGpuResources() override { return true; }
+
const GrSurfaceProxyView* getViews(int* numActiveProxies) {
*numActiveProxies = fAtlas->numActivePages();
return fAtlas->getViews();
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 8410a25..95b40c6 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -40,14 +40,10 @@
static constexpr SkScalar kMinSize = SK_ScalarHalf;
static constexpr SkScalar kMaxSize = 2*kMaxMIP;
-GrSmallPathRenderer::GrSmallPathRenderer() : fAtlasMgr(new GrSmallPathAtlasMgr) {}
+GrSmallPathRenderer::GrSmallPathRenderer() {}
GrSmallPathRenderer::~GrSmallPathRenderer() {}
-void GrSmallPathRenderer::addToOnFlushCallbacks(GrRecordingContext* rContext) {
- rContext->priv().addOnFlushCallbackObject(fAtlasMgr.get());
-}
-
GrPathRenderer::CanDrawPath GrSmallPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
if (!args.fCaps->shaderCaps()->shaderDerivativeSupport()) {
return CanDrawPath::kNo;
@@ -105,15 +101,14 @@
GrPaint&& paint,
const GrStyledShape& shape,
const SkMatrix& viewMatrix,
- GrSmallPathAtlasMgr* atlasMgr,
bool gammaCorrect,
const GrUserStencilSettings* stencilSettings) {
return Helper::FactoryHelper<SmallPathOp>(context, std::move(paint), shape, viewMatrix,
- atlasMgr, gammaCorrect, stencilSettings);
+ gammaCorrect, stencilSettings);
}
SmallPathOp(Helper::MakeArgs helperArgs, const SkPMColor4f& color, const GrStyledShape& shape,
- const SkMatrix& viewMatrix, GrSmallPathAtlasMgr* atlasMgr, bool gammaCorrect,
+ const SkMatrix& viewMatrix, bool gammaCorrect,
const GrUserStencilSettings* stencilSettings)
: INHERITED(ClassID())
, fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) {
@@ -132,7 +127,6 @@
fShapes.emplace_back(Entry{color, shape, viewMatrix});
- fAtlasMgr = atlasMgr;
fGammaCorrect = gammaCorrect;
}
@@ -197,6 +191,11 @@
void onPrepareDraws(Target* target) override {
int instanceCount = fShapes.count();
+ GrSmallPathAtlasMgr* atlasMgr = target->smallPathAtlasManager();
+ if (!atlasMgr) {
+ return;
+ }
+
static constexpr int kMaxTextures = GrDistanceFieldPathGeoProc::kMaxTextures;
static_assert(GrBitmapTextGeoProc::kMaxTextures == kMaxTextures);
@@ -204,7 +203,7 @@
flushInfo.fPrimProcProxies = target->allocPrimProcProxyPtrs(kMaxTextures);
int numActiveProxies;
- const GrSurfaceProxyView* views = fAtlasMgr->getViews(&numActiveProxies);
+ const GrSurfaceProxyView* views = atlasMgr->getViews(&numActiveProxies);
for (int i = 0; i < numActiveProxies; ++i) {
// This op does not know its atlas proxies when it is added to a GrOpsTasks, so the
// proxies don't get added during the visitProxies call. Thus we add them here.
@@ -322,39 +321,39 @@
int ceilDesiredDimension = SkScalarCeilToInt(desiredDimension);
// check to see if df path is cached
- shapeData = fAtlasMgr->findOrCreate(args.fShape, ceilDesiredDimension);
+ shapeData = atlasMgr->findOrCreate(args.fShape, ceilDesiredDimension);
if (!shapeData->fAtlasLocator.plotLocator().isValid()) {
SkScalar scale = desiredDimension / maxDim;
if (!this->addDFPathToAtlas(target,
&flushInfo,
- fAtlasMgr->atlas(),
+ atlasMgr->atlas(),
shapeData,
args.fShape,
ceilDesiredDimension,
scale)) {
- fAtlasMgr->deleteCacheEntry(shapeData);
+ atlasMgr->deleteCacheEntry(shapeData);
continue;
}
}
} else {
// check to see if bitmap path is cached
- shapeData = fAtlasMgr->findOrCreate(args.fShape, args.fViewMatrix);
+ shapeData = atlasMgr->findOrCreate(args.fShape, args.fViewMatrix);
if (!shapeData->fAtlasLocator.plotLocator().isValid()) {
if (!this->addBMPathToAtlas(target,
&flushInfo,
- fAtlasMgr->atlas(),
+ atlasMgr->atlas(),
shapeData,
args.fShape,
args.fViewMatrix)) {
- fAtlasMgr->deleteCacheEntry(shapeData);
+ atlasMgr->deleteCacheEntry(shapeData);
continue;
}
}
}
auto uploadTarget = target->deferredUploadTarget();
- fAtlasMgr->setUseToken(shapeData, uploadTarget->tokenTracker()->nextDrawToken());
+ atlasMgr->setUseToken(shapeData, uploadTarget->tokenTracker()->nextDrawToken());
this->writePathVertices(vertices, GrVertexColor(args.fColor, fWideColor),
args.fViewMatrix, shapeData);
@@ -367,6 +366,8 @@
bool addToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, GrDrawOpAtlas* atlas,
int width, int height, const void* image,
GrDrawOpAtlas::AtlasLocator* atlasLocator) const {
+ SkASSERT(atlas);
+
auto resourceProvider = target->resourceProvider();
auto uploadTarget = target->deferredUploadTarget();
@@ -389,6 +390,7 @@
bool addDFPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
GrDrawOpAtlas* atlas, GrSmallPathShapeData* shapeData,
const GrStyledShape& shape, uint32_t dimension, SkScalar scale) const {
+ SkASSERT(atlas);
const SkRect& bounds = shape.bounds();
@@ -487,6 +489,8 @@
bool addBMPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
GrDrawOpAtlas* atlas, GrSmallPathShapeData* shapeData,
const GrStyledShape& shape, const SkMatrix& ctm) const {
+ SkASSERT(atlas);
+
const SkRect& bounds = shape.bounds();
if (bounds.isEmpty()) {
return false;
@@ -580,12 +584,15 @@
}
void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
+ GrSmallPathAtlasMgr* atlasMgr = target->smallPathAtlasManager();
+ if (!atlasMgr) {
+ return;
+ }
int numActiveProxies;
- const GrSurfaceProxyView* views = fAtlasMgr->getViews(&numActiveProxies);
+ const GrSurfaceProxyView* views = atlasMgr->getViews(&numActiveProxies);
GrGeometryProcessor* gp = flushInfo->fGeometryProcessor;
-
if (gp->numTextureSamplers() != numActiveProxies) {
for (int i = gp->numTextureSamplers(); i < numActiveProxies; ++i) {
flushInfo->fPrimProcProxies[i] = views[i].proxy();
@@ -678,7 +685,6 @@
SkSTArray<1, Entry> fShapes;
Helper fHelper;
- GrSmallPathAtlasMgr* fAtlasMgr;
bool fGammaCorrect;
bool fWideColor;
@@ -689,18 +695,13 @@
GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
"GrSmallPathRenderer::onDrawPath");
- const GrCaps* caps = args.fContext->priv().caps();
-
// we've already bailed on inverse filled paths, so this is safe
SkASSERT(!args.fShape->isEmpty());
SkASSERT(args.fShape->hasUnstyledKey());
- if (!fAtlasMgr->initAtlas(args.fContext->priv().proxyProvider(), caps)) {
- return false;
- }
std::unique_ptr<GrDrawOp> op = SmallPathOp::Make(
args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
- fAtlasMgr.get(), args.fGammaCorrect, args.fUserStencilSettings);
+ args.fGammaCorrect, args.fUserStencilSettings);
args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
@@ -709,38 +710,19 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
#if GR_TEST_UTILS
-
-struct GrSmallPathRenderer::PathTestStruct {
- PathTestStruct() : fContextID(SK_InvalidGenID) {}
- ~PathTestStruct() { }
-
- uint32_t fContextID;
- std::unique_ptr<GrSmallPathAtlasMgr> fAtlasMgr;
-};
-
std::unique_ptr<GrDrawOp> GrSmallPathRenderer::createOp_TestingOnly(
GrRecordingContext* context,
GrPaint&& paint,
const GrStyledShape& shape,
const SkMatrix& viewMatrix,
- GrSmallPathAtlasMgr* atlasMgr,
bool gammaCorrect,
const GrUserStencilSettings* stencil) {
return GrSmallPathRenderer::SmallPathOp::Make(context, std::move(paint), shape, viewMatrix,
- atlasMgr, gammaCorrect, stencil);
+ gammaCorrect, stencil);
}
GR_DRAW_OP_TEST_DEFINE(SmallPathOp) {
- static GrSmallPathRenderer::PathTestStruct gTestStruct;
-
- if (context->priv().contextID() != gTestStruct.fContextID) {
- gTestStruct.fContextID = context->priv().contextID();
- gTestStruct.fAtlasMgr = std::make_unique<GrSmallPathAtlasMgr>();
- gTestStruct.fAtlasMgr->initAtlas(context->priv().proxyProvider(),
- context->priv().caps());
- }
-
SkMatrix viewMatrix = GrTest::TestMatrix(random);
bool gammaCorrect = random->nextBool();
@@ -749,7 +731,6 @@
return GrSmallPathRenderer::createOp_TestingOnly(
context,
std::move(paint), shape, viewMatrix,
- gTestStruct.fAtlasMgr.get(),
gammaCorrect,
GrGetRandomStencil(random, context));
}
diff --git a/src/gpu/ops/GrSmallPathRenderer.h b/src/gpu/ops/GrSmallPathRenderer.h
index e0a45a7..3fdba12 100644
--- a/src/gpu/ops/GrSmallPathRenderer.h
+++ b/src/gpu/ops/GrSmallPathRenderer.h
@@ -12,7 +12,6 @@
class GrDrawOp;
class GrRecordingContext;
-class GrSmallPathAtlasMgr;
class GrStyledShape;
class GrSmallPathRenderer : public GrPathRenderer {
@@ -22,16 +21,12 @@
const char* name() const final { return "Small"; }
- void addToOnFlushCallbacks(GrRecordingContext*);
-
static std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrRecordingContext*,
GrPaint&&,
const GrStyledShape&,
const SkMatrix& viewMatrix,
- GrSmallPathAtlasMgr*,
bool gammaCorrect,
const GrUserStencilSettings*);
- struct PathTestStruct;
private:
class SmallPathOp;
@@ -44,8 +39,6 @@
bool onDrawPath(const DrawPathArgs&) override;
- std::unique_ptr<GrSmallPathAtlasMgr> fAtlasMgr;
-
typedef GrPathRenderer INHERITED;
};