use a linked list for GrAtlasTextOp geometries
Instead of using a GrTBlockList<Geometry> to hold the geometries
in the op. Allocate them on the RecordTimeAllocator, and
link them together.
Change-Id: I32af5724e7abeca1ddb6d38b26afbff7919cbc76
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341725
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 3f217e7..c3a89d0 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -37,7 +37,7 @@
bool needsTransform,
int glyphCount,
SkRect deviceRect,
- const Geometry& geo,
+ Geometry* geo,
GrPaint&& paint)
: INHERITED{ClassID()}
, fProcessors(std::move(paint))
@@ -46,9 +46,10 @@
, fMaskType(static_cast<uint32_t>(maskType))
, fUsesLocalCoords(false)
, fNeedsGlyphTransform(needsTransform)
- , fHasPerspective(needsTransform && geo.fDrawMatrix.hasPerspective())
- , fUseGammaCorrectDistanceTable(false) {
- fGeometries.push_back(geo);
+ , fHasPerspective(needsTransform && geo->fDrawMatrix.hasPerspective())
+ , fUseGammaCorrectDistanceTable(false)
+ , fHead{geo}
+ , fTail{&fHead->fNext} {
// We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
// we treat this as a set of non-AA rects rendered with a texture.
this->setBounds(deviceRect, HasAABloat::kNo, IsHairline::kNo);
@@ -61,7 +62,7 @@
SkColor luminanceColor,
bool useGammaCorrectDistanceTable,
uint32_t DFGPFlags,
- const Geometry& geo,
+ Geometry* geo,
GrPaint&& paint)
: INHERITED{ClassID()}
, fProcessors(std::move(paint))
@@ -70,15 +71,34 @@
, fMaskType(static_cast<uint32_t>(maskType))
, fUsesLocalCoords(false)
, fNeedsGlyphTransform(needsTransform)
- , fHasPerspective(needsTransform && geo.fDrawMatrix.hasPerspective())
+ , fHasPerspective(needsTransform && geo->fDrawMatrix.hasPerspective())
, fUseGammaCorrectDistanceTable(useGammaCorrectDistanceTable)
- , fLuminanceColor(luminanceColor) {
- fGeometries.push_back(geo);
+ , fLuminanceColor(luminanceColor)
+ , fHead{geo}
+ , fTail{&fHead->fNext} {
// We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
// we treat this as a set of non-AA rects rendered with a texture.
this->setBounds(deviceRect, HasAABloat::kNo, IsHairline::kNo);
}
+auto GrAtlasTextOp::Geometry::Make(GrRecordingContext* rc,
+ const GrAtlasSubRun& subRun,
+ const SkMatrix& drawMatrix,
+ SkPoint drawOrigin,
+ SkIRect clipRect,
+ GrTextBlob* blob,
+ const SkPMColor4f& color) -> Geometry* {
+ auto arena = rc->priv().recordTimeAllocator();
+ return arena->make<Geometry>(subRun,
+ drawMatrix,
+ drawOrigin,
+ SkIRect::MakeEmpty(),
+ SkRef(blob),
+ color);
+}
+
+
+
void GrAtlasTextOp::Geometry::fillVertexData(void *dst, int offset, int count) const {
SkMatrix positionMatrix = fDrawMatrix;
positionMatrix.preTranslate(fDrawOrigin.x(), fDrawOrigin.y());
@@ -94,12 +114,12 @@
SkString GrAtlasTextOp::onDumpInfo() const {
SkString str;
int i = 0;
- for (const auto& g : fGeometries.items()) {
+ for(Geometry* geom = fHead; geom != nullptr; geom = geom->fNext) {
str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f\n",
i++,
- g.fColor.toBytes_RGBA(),
- g.fDrawOrigin.x(),
- g.fDrawOrigin.y());
+ geom->fColor.toBytes_RGBA(),
+ geom->fDrawOrigin.x(),
+ geom->fDrawOrigin.y());
}
str += fProcessors.dumpProcessors();
@@ -121,7 +141,7 @@
} else {
// finalize() is called before any merging is done, so at this point there's at most one
// Geometry with a color. Later, for non-bitmap ops, we may have mixed colors.
- color.setToConstant(fGeometries.front().fColor);
+ color.setToConstant(fHead->fColor);
}
switch (this->maskType()) {
@@ -142,7 +162,7 @@
auto analysis = fProcessors.finalize(
color, coverage, clip, &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps,
- clampType, &fGeometries.front().fColor);
+ clampType, &fHead->fColor);
// TODO(michaelludwig): Once processor analysis can be done external to op creation/finalization
// the atlas op metadata can be fully const. This is okay for now since finalize() happens
// before the op is merged, so during combineIfPossible, metadata is effectively const.
@@ -158,7 +178,7 @@
// the matrix is identity. When the shaders require local coords, combineIfPossible requires all
// all geometries to have same draw matrix.
SkMatrix localMatrix = SkMatrix::I();
- if (fUsesLocalCoords && !fGeometries.front().fDrawMatrix.invert(&localMatrix)) {
+ if (fUsesLocalCoords && !fHead->fDrawMatrix.invert(&localMatrix)) {
return;
}
@@ -200,7 +220,7 @@
// Bitmap text uses a single color, combineIfPossible ensures all geometries have the same
// color, so we can use the first's without worry.
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
- target->allocator(), *target->caps().shaderCaps(), fGeometries.front().fColor,
+ target->allocator(), *target->caps().shaderCaps(), fHead->fColor,
false, views, numActiveViews, filter, maskFormat, localMatrix, fHasPerspective);
}
@@ -236,9 +256,9 @@
resetVertexBuffer();
- for (const Geometry& geo : fGeometries.items()) {
- const GrAtlasSubRun& subRun = geo.fSubRun;
- SkASSERT((int) subRun.vertexStride(geo.fDrawMatrix) == vertexStride);
+ for (const Geometry* geo = fHead; geo != nullptr; geo = geo->fNext) {
+ const GrAtlasSubRun& subRun = geo->fSubRun;
+ SkASSERT((int) subRun.vertexStride(geo->fDrawMatrix) == vertexStride);
const int subRunEnd = subRun.glyphCount();
for (int subRunCursor = 0; subRunCursor < subRunEnd;) {
@@ -251,7 +271,7 @@
return;
}
- geo.fillVertexData(vertices + quadCursor * quadSize, subRunCursor, glyphsRegenerated);
+ geo->fillVertexData(vertices + quadCursor * quadSize, subRunCursor, glyphsRegenerated);
subRunCursor += glyphsRegenerated;
quadCursor += glyphsRegenerated;
@@ -363,8 +383,8 @@
if (fUsesLocalCoords) {
// If the fragment processors use local coordinates, the GPs compute them using the inverse
// of the view matrix stored in a uniform, so all geometries must have the same matrix.
- const SkMatrix& thisFirstMatrix = fGeometries.front().fDrawMatrix;
- const SkMatrix& thatFirstMatrix = that->fGeometries.front().fDrawMatrix;
+ const SkMatrix& thisFirstMatrix = fHead->fDrawMatrix;
+ const SkMatrix& thatFirstMatrix = that->fHead->fDrawMatrix;
if (!SkMatrixPriv::CheapEqual(thisFirstMatrix, thatFirstMatrix)) {
return CombineResult::kCannotCombine;
}
@@ -377,7 +397,7 @@
}
} else {
if (this->maskType() == MaskType::kColorBitmap &&
- fGeometries.front().fColor != that->fGeometries.front().fColor) {
+ fHead->fColor != that->fHead->fColor) {
// This ensures all merged bitmap color text ops have a constant color
return CombineResult::kCannotCombine;
}
@@ -386,7 +406,8 @@
fNumGlyphs += that->fNumGlyphs;
// After concat, that's geometry list is emptied so it will not unref the blobs when destructed
- fGeometries.concat(std::move(that->fGeometries));
+ this->addGeometry(that->fHead);
+ that->fHead = nullptr;
return CombineResult::kMerged;
}