[graphite] Move DrawAtlasMgr to PathAtlas.
This will allow ComputePathAtlas to share it.
Bug: b/305696981
Change-Id: I11f059604fe11594b908e3fe92cf0b93d48d77af
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/839338
Reviewed-by: Arman Uguray <armansito@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/graphite/PathAtlas.cpp b/src/gpu/graphite/PathAtlas.cpp
index 211ed5d..750c132 100644
--- a/src/gpu/graphite/PathAtlas.cpp
+++ b/src/gpu/graphite/PathAtlas.cpp
@@ -9,8 +9,10 @@
#include "include/gpu/graphite/Recorder.h"
#include "src/gpu/graphite/Caps.h"
+#include "src/gpu/graphite/RasterPathUtils.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/RendererProvider.h"
+#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/geom/Transform_graphite.h"
namespace skgpu::graphite {
@@ -69,4 +71,134 @@
return std::make_pair(fRecorder->priv().rendererProvider()->coverageMask(), atlasMask);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+PathAtlas::DrawAtlasMgr::DrawAtlasMgr(size_t width, size_t height,
+ size_t plotWidth, size_t plotHeight,
+ std::string_view label,
+ const Caps* caps) {
+ static constexpr SkColorType colorType = kAlpha_8_SkColorType;
+
+ fDrawAtlas = DrawAtlas::Make(colorType,
+ SkColorTypeBytesPerPixel(colorType),
+ width, height,
+ plotWidth, plotHeight,
+ this,
+ caps->allowMultipleAtlasTextures() ?
+ DrawAtlas::AllowMultitexturing::kYes :
+ DrawAtlas::AllowMultitexturing::kNo,
+ this,
+ label);
+ SkASSERT(fDrawAtlas);
+ fKeyLists.resize(fDrawAtlas->numPlots() * fDrawAtlas->maxPages());
+ for (int i = 0; i < fKeyLists.size(); ++i) {
+ fKeyLists[i].reset();
+ }
+}
+
+namespace {
+uint32_t shape_key_list_index(const PlotLocator& locator, const DrawAtlas* drawAtlas) {
+ return locator.pageIndex() * drawAtlas->numPlots() + locator.plotIndex();
+}
+} // namespace
+
+const TextureProxy* PathAtlas::DrawAtlasMgr::findOrCreateEntry(Recorder* recorder,
+ const Shape& shape,
+ const Transform& transform,
+ const SkStrokeRec& strokeRec,
+ skvx::half2 maskSize,
+ skvx::half2* outPos) {
+ // Shapes must have a key to use this method
+ skgpu::UniqueKey maskKey = GeneratePathMaskKey(shape, transform, strokeRec, maskSize);
+ AtlasLocator* cachedLocator = fShapeCache.find(maskKey);
+ if (cachedLocator) {
+ SkIPoint topLeft = cachedLocator->topLeft();
+ *outPos = skvx::half2(topLeft.x() + kEntryPadding, topLeft.y() + kEntryPadding);
+ fDrawAtlas->setLastUseToken(*cachedLocator,
+ recorder->priv().tokenTracker()->nextFlushToken());
+ return fDrawAtlas->getProxies()[cachedLocator->pageIndex()].get();
+ }
+
+ AtlasLocator locator;
+ const TextureProxy* proxy = this->addToAtlas(recorder, shape, transform, strokeRec,
+ maskSize, outPos, &locator);
+ if (!proxy) {
+ return nullptr;
+ }
+
+ // Add locator to ShapeCache.
+ fShapeCache.set(maskKey, locator);
+ // Add key to Plot's ShapeKeyList.
+ uint32_t index = shape_key_list_index(locator.plotLocator(), fDrawAtlas.get());
+ ShapeKeyEntry* keyEntry = new ShapeKeyEntry();
+ keyEntry->fKey = maskKey;
+ fKeyLists[index].addToTail(keyEntry);
+
+ return proxy;
+}
+
+const TextureProxy* PathAtlas::DrawAtlasMgr::addToAtlas(Recorder* recorder,
+ const Shape& shape,
+ const Transform& transform,
+ const SkStrokeRec& strokeRec,
+ skvx::half2 maskSize,
+ skvx::half2* outPos,
+ AtlasLocator* locator) {
+ // Render mask.
+ SkIRect iShapeBounds = SkIRect::MakeXYWH(0, 0, maskSize.x(), maskSize.y());
+ // Outset to take padding into account
+ SkIRect iAtlasBounds = iShapeBounds.makeOutset(kEntryPadding, kEntryPadding);
+
+ // Request space in DrawAtlas.
+ DrawAtlas::ErrorCode errorCode = fDrawAtlas->addRect(recorder,
+ iAtlasBounds.width(),
+ iAtlasBounds.height(),
+ locator);
+ if (errorCode != DrawAtlas::ErrorCode::kSucceeded) {
+ return nullptr;
+ }
+ SkIPoint topLeft = locator->topLeft();
+ *outPos = skvx::half2(topLeft.x()+kEntryPadding, topLeft.y()+kEntryPadding);
+
+ // If the mask is empty, just return.
+ // TODO: this may not be needed if we can handle clipped out bounds with inverse fills
+ // another way. See PathAtlas::addShape().
+ if (!all(maskSize)) {
+ fDrawAtlas->setLastUseToken(*locator,
+ recorder->priv().tokenTracker()->nextFlushToken());
+ return fDrawAtlas->getProxies()[locator->pageIndex()].get();
+ }
+
+ if (!this->onAddToAtlas(shape, transform, strokeRec, iShapeBounds, *locator)) {
+ return nullptr;
+ }
+
+ fDrawAtlas->setLastUseToken(*locator,
+ recorder->priv().tokenTracker()->nextFlushToken());
+
+ return fDrawAtlas->getProxies()[locator->pageIndex()].get();
+}
+
+bool PathAtlas::DrawAtlasMgr::recordUploads(DrawContext* dc, Recorder* recorder) {
+ return fDrawAtlas->recordUploads(dc, recorder);
+}
+
+void PathAtlas::DrawAtlasMgr::evict(PlotLocator plotLocator) {
+ // Remove all entries for this Plot from the ShapeCache
+ uint32_t index = shape_key_list_index(plotLocator, fDrawAtlas.get());
+ ShapeKeyList::Iter iter;
+ iter.init(fKeyLists[index], ShapeKeyList::Iter::kHead_IterStart);
+ ShapeKeyEntry* currEntry;
+ while ((currEntry = iter.get())) {
+ iter.next();
+ fShapeCache.remove(currEntry->fKey);
+ fKeyLists[index].remove(currEntry);
+ delete currEntry;
+ }
+}
+
+void PathAtlas::DrawAtlasMgr::postFlush(Recorder* recorder) {
+ fDrawAtlas->compact(recorder->priv().tokenTracker()->nextFlushToken());
+}
+
} // namespace skgpu::graphite
diff --git a/src/gpu/graphite/PathAtlas.h b/src/gpu/graphite/PathAtlas.h
index b2f0043..ca32d33 100644
--- a/src/gpu/graphite/PathAtlas.h
+++ b/src/gpu/graphite/PathAtlas.h
@@ -9,6 +9,11 @@
#define skgpu_graphite_PathAtlas_DEFINED
#include "include/core/SkStrokeRec.h"
+#include "src/base/SkTInternalLList.h"
+#include "src/core/SkTHash.h"
+#include "src/gpu/AtlasTypes.h"
+#include "src/gpu/ResourceKey.h"
+#include "src/gpu/graphite/DrawAtlas.h"
#include "src/gpu/graphite/geom/CoverageMaskShape.h"
namespace skgpu::graphite {
@@ -104,6 +109,60 @@
skvx::half2 maskSize,
skvx::half2* outPos) = 0;
+ // Wrapper class to manage DrawAtlas and associated caching operations
+ class DrawAtlasMgr : public AtlasGenerationCounter, public PlotEvictionCallback {
+ public:
+ const TextureProxy* findOrCreateEntry(Recorder* recorder,
+ const Shape& shape,
+ const Transform& transform,
+ const SkStrokeRec& strokeRec,
+ skvx::half2 maskSize,
+ skvx::half2* outPos);
+ // Adds to DrawAtlas but not the cache
+ const TextureProxy* addToAtlas(Recorder* recorder,
+ const Shape& shape,
+ const Transform& transform,
+ const SkStrokeRec& strokeRec,
+ skvx::half2 maskSize,
+ skvx::half2* outPos,
+ AtlasLocator* locator);
+ bool recordUploads(DrawContext*, Recorder*);
+ void evict(PlotLocator) override;
+ void postFlush(Recorder*);
+
+ protected:
+ DrawAtlasMgr(size_t width, size_t height,
+ size_t plotWidth, size_t plotHeight,
+ std::string_view label, const Caps*);
+
+ bool virtual onAddToAtlas(const Shape&,
+ const Transform& transform,
+ const SkStrokeRec&,
+ SkIRect shapeBounds,
+ const AtlasLocator&) = 0;
+
+ std::unique_ptr<DrawAtlas> fDrawAtlas;
+
+ private:
+ // Tracks whether a shape is already in the DrawAtlas, and its location in the atlas
+ struct UniqueKeyHash {
+ uint32_t operator()(const skgpu::UniqueKey& key) const { return key.hash(); }
+ };
+ using ShapeCache = skia_private::THashMap<skgpu::UniqueKey, AtlasLocator, UniqueKeyHash>;
+ ShapeCache fShapeCache;
+
+ // List of stored keys per Plot, used to invalidate cache entries.
+ // When a Plot is invalidated via evict(), we'll get its index and Page index from the
+ // PlotLocator, index into the fKeyLists array to get the ShapeKeyList for that Plot,
+ // then iterate through the list and remove entries matching those keys from the ShapeCache.
+ struct ShapeKeyEntry {
+ skgpu::UniqueKey fKey;
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeKeyEntry);
+ };
+ using ShapeKeyList = SkTInternalLList<ShapeKeyEntry>;
+ SkTDArray<ShapeKeyList> fKeyLists;
+ };
+
// The Recorder that created and owns this Atlas.
Recorder* fRecorder;
diff --git a/src/gpu/graphite/RasterPathAtlas.cpp b/src/gpu/graphite/RasterPathAtlas.cpp
index f58c018..1dd9de3 100644
--- a/src/gpu/graphite/RasterPathAtlas.cpp
+++ b/src/gpu/graphite/RasterPathAtlas.cpp
@@ -15,7 +15,6 @@
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/RasterPathUtils.h"
#include "src/gpu/graphite/RecorderPriv.h"
-#include "src/gpu/graphite/TextureProxy.h"
namespace skgpu::graphite {
@@ -86,143 +85,27 @@
/////////////////////////////////////////////////////////////////////////////////////////
-RasterPathAtlas::DrawAtlasMgr::DrawAtlasMgr(size_t width, size_t height,
- size_t plotWidth, size_t plotHeight,
- const Caps* caps) {
- static constexpr SkColorType colorType = kAlpha_8_SkColorType;
-
-
- fDrawAtlas = DrawAtlas::Make(colorType,
- SkColorTypeBytesPerPixel(colorType),
- width, height,
- plotWidth, plotHeight,
- this,
- caps->allowMultipleAtlasTextures() ?
- DrawAtlas::AllowMultitexturing::kYes :
- DrawAtlas::AllowMultitexturing::kNo,
- this,
- /*label=*/"RasterPathAtlas");
- SkASSERT(fDrawAtlas);
- fKeyLists.resize(fDrawAtlas->numPlots() * fDrawAtlas->maxPages());
- for (int i = 0; i < fKeyLists.size(); ++i) {
- fKeyLists[i].reset();
- }
-}
-
-namespace {
-uint32_t shape_key_list_index(const PlotLocator& locator, const DrawAtlas* drawAtlas) {
- return locator.pageIndex() * drawAtlas->numPlots() + locator.plotIndex();
-}
-} // namespace
-
-const TextureProxy* RasterPathAtlas::DrawAtlasMgr::findOrCreateEntry(Recorder* recorder,
- const Shape& shape,
- const Transform& transform,
- const SkStrokeRec& strokeRec,
- skvx::half2 maskSize,
- skvx::half2* outPos) {
- // Shapes must have a key to use this method
- skgpu::UniqueKey maskKey = GeneratePathMaskKey(shape, transform, strokeRec, maskSize);
- AtlasLocator* cachedLocator = fShapeCache.find(maskKey);
- if (cachedLocator) {
- SkIPoint topLeft = cachedLocator->topLeft();
- *outPos = skvx::half2(topLeft.x() + kEntryPadding, topLeft.y() + kEntryPadding);
- fDrawAtlas->setLastUseToken(*cachedLocator,
- recorder->priv().tokenTracker()->nextFlushToken());
- return fDrawAtlas->getProxies()[cachedLocator->pageIndex()].get();
- }
-
- AtlasLocator locator;
- const TextureProxy* proxy = this->addToAtlas(recorder, shape, transform, strokeRec,
- maskSize, outPos, &locator);
- if (!proxy) {
- return nullptr;
- }
-
- // Add locator to ShapeCache.
- fShapeCache.set(maskKey, locator);
- // Add key to Plot's ShapeKeyList.
- uint32_t index = shape_key_list_index(locator.plotLocator(), fDrawAtlas.get());
- ShapeKeyEntry* keyEntry = new ShapeKeyEntry();
- keyEntry->fKey = maskKey;
- fKeyLists[index].addToTail(keyEntry);
-
- return proxy;
-}
-
-const TextureProxy* RasterPathAtlas::DrawAtlasMgr::addToAtlas(Recorder* recorder,
- const Shape& shape,
- const Transform& transform,
- const SkStrokeRec& strokeRec,
- skvx::half2 maskSize,
- skvx::half2* outPos,
- AtlasLocator* locator) {
- // Render mask.
- SkIRect iShapeBounds = SkIRect::MakeXYWH(0, 0, maskSize.x(), maskSize.y());
- // Outset to take padding into account
- SkIRect iAtlasBounds = iShapeBounds.makeOutset(kEntryPadding, kEntryPadding);
-
- // Request space in DrawAtlas.
- DrawAtlas::ErrorCode errorCode = fDrawAtlas->addRect(recorder,
- iAtlasBounds.width(),
- iAtlasBounds.height(),
- locator);
- if (errorCode != DrawAtlas::ErrorCode::kSucceeded) {
- return nullptr;
- }
- SkIPoint topLeft = locator->topLeft();
- *outPos = skvx::half2(topLeft.x()+kEntryPadding, topLeft.y()+kEntryPadding);
-
- // If the mask is empty, just return.
- // TODO: this may not be needed if we can handle clipped out bounds with inverse fills
- // another way. See PathAtlas::addShape().
- if (!all(maskSize)) {
- fDrawAtlas->setLastUseToken(*locator,
- recorder->priv().tokenTracker()->nextFlushToken());
- return fDrawAtlas->getProxies()[locator->pageIndex()].get();
- }
-
+bool RasterPathAtlas::RasterAtlasMgr::onAddToAtlas(const Shape& shape,
+ const Transform& transform,
+ const SkStrokeRec& strokeRec,
+ SkIRect shapeBounds,
+ const AtlasLocator& locator) {
// Rasterize path to backing pixmap.
// This pixmap will be the size of the Plot that contains the given rect, not the entire atlas,
// and hence the position we render at will be relative to that Plot.
// The value of outPos is relative to the entire texture, to be used for texture coords.
SkAutoPixmapStorage dst;
- SkIPoint renderPos = fDrawAtlas->prepForRender(*locator, &dst);
+ SkIPoint renderPos = fDrawAtlas->prepForRender(locator, &dst);
RasterMaskHelper helper(&dst);
if (!helper.init(fDrawAtlas->plotSize())) {
- return nullptr;
+ return false;
}
// Offset to plot location and draw
- iShapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
- helper.drawShape(shape, transform, strokeRec, iShapeBounds);
+ shapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
+ helper.drawShape(shape, transform, strokeRec, shapeBounds);
- fDrawAtlas->setLastUseToken(*locator,
- recorder->priv().tokenTracker()->nextFlushToken());
-
- return fDrawAtlas->getProxies()[locator->pageIndex()].get();
-}
-
-bool RasterPathAtlas::DrawAtlasMgr::recordUploads(DrawContext* dc, Recorder* recorder) {
- return fDrawAtlas->recordUploads(dc, recorder);
-}
-
-void RasterPathAtlas::DrawAtlasMgr::evict(PlotLocator plotLocator) {
- // Remove all entries for this Plot from the ShapeCache
- uint32_t index = shape_key_list_index(plotLocator, fDrawAtlas.get());
- ShapeKeyList::Iter iter;
- iter.init(fKeyLists[index], ShapeKeyList::Iter::kHead_IterStart);
- ShapeKeyEntry* currEntry;
- while ((currEntry = iter.get())) {
- iter.next();
- fShapeCache.remove(currEntry->fKey);
- fKeyLists[index].remove(currEntry);
- delete currEntry;
- }
-}
-
-void RasterPathAtlas::DrawAtlasMgr::postFlush(Recorder* recorder) {
- fDrawAtlas->compact(recorder->priv().tokenTracker()->nextFlushToken());
+ return true;
}
} // namespace skgpu::graphite
diff --git a/src/gpu/graphite/RasterPathAtlas.h b/src/gpu/graphite/RasterPathAtlas.h
index f6f4404..a26833d 100644
--- a/src/gpu/graphite/RasterPathAtlas.h
+++ b/src/gpu/graphite/RasterPathAtlas.h
@@ -8,11 +8,6 @@
#ifndef skgpu_graphite_RasterPathAtlas_DEFINED
#define skgpu_graphite_RasterPathAtlas_DEFINED
-#include "src/base/SkTInternalLList.h"
-#include "src/core/SkTHash.h"
-#include "src/gpu/AtlasTypes.h"
-#include "src/gpu/ResourceKey.h"
-#include "src/gpu/graphite/DrawAtlas.h"
#include "src/gpu/graphite/PathAtlas.h"
namespace skgpu::graphite {
@@ -46,57 +41,25 @@
skvx::half2 maskSize,
skvx::half2* outPos) override;
private:
- // Wrapper class to manage DrawAtlas and associated caching operations
- class DrawAtlasMgr : public AtlasGenerationCounter, public PlotEvictionCallback {
+ class RasterAtlasMgr : public PathAtlas::DrawAtlasMgr {
public:
- DrawAtlasMgr(size_t width, size_t height,
- size_t plotWidth, size_t plotHeight,
- const Caps*);
+ RasterAtlasMgr(size_t width, size_t height,
+ size_t plotWidth, size_t plotHeight,
+ const Caps* caps)
+ : PathAtlas::DrawAtlasMgr(width, height, plotWidth, plotHeight,
+ /*label=*/"RasterPathAtlas", caps) {}
- const TextureProxy* findOrCreateEntry(Recorder* recorder,
- const Shape& shape,
- const Transform& transform,
- const SkStrokeRec& strokeRec,
- skvx::half2 maskSize,
- skvx::half2* outPos);
- // Adds to DrawAtlas but not the cache
- const TextureProxy* addToAtlas(Recorder* recorder,
- const Shape& shape,
- const Transform& transform,
- const SkStrokeRec& strokeRec,
- skvx::half2 maskSize,
- skvx::half2* outPos,
- AtlasLocator* locator);
- bool recordUploads(DrawContext*, Recorder*);
- void evict(PlotLocator) override;
- void postFlush(Recorder*);
-
- private:
-
- std::unique_ptr<DrawAtlas> fDrawAtlas;
-
- // Tracks whether a shape is already in the DrawAtlas, and its location in the atlas
- struct UniqueKeyHash {
- uint32_t operator()(const skgpu::UniqueKey& key) const { return key.hash(); }
- };
- using ShapeCache = skia_private::THashMap<skgpu::UniqueKey, AtlasLocator, UniqueKeyHash>;
- ShapeCache fShapeCache;
-
- // List of stored keys per Plot, used to invalidate cache entries.
- // When a Plot is invalidated via evict(), we'll get its index and Page index from the
- // PlotLocator, index into the fKeyLists array to get the ShapeKeyList for that Plot,
- // then iterate through the list and remove entries matching those keys from the ShapeCache.
- struct ShapeKeyEntry {
- skgpu::UniqueKey fKey;
- SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeKeyEntry);
- };
- using ShapeKeyList = SkTInternalLList<ShapeKeyEntry>;
- SkTDArray<ShapeKeyList> fKeyLists;
+ protected:
+ bool onAddToAtlas(const Shape&,
+ const Transform& transform,
+ const SkStrokeRec&,
+ SkIRect shapeBounds,
+ const AtlasLocator&) override;
};
- DrawAtlasMgr fCachedAtlasMgr;
- DrawAtlasMgr fSmallPathAtlasMgr;
- DrawAtlasMgr fUncachedAtlasMgr;
+ RasterAtlasMgr fCachedAtlasMgr;
+ RasterAtlasMgr fSmallPathAtlasMgr;
+ RasterAtlasMgr fUncachedAtlasMgr;
};
} // namespace skgpu::graphite