Reland "use a linked list for GrAtlasTextOp geometries"
This is a reland of 82a8130654bc6354cdaee9ce05e5d6118e1c5e33
Original change's description:
> 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>
Change-Id: I526d8b0b06fca13046c065cbc06f0c0e1103ce11
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371996
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..c228a16 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,
+ clipRect,
+ 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;
}
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 29c5a54..7c3e191 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -20,8 +20,8 @@
DEFINE_OP_CLASS_ID
~GrAtlasTextOp() override {
- for (const auto& g : fGeometries.items()) {
- g.fBlob->unref();
+ for (const Geometry* g = fHead; g != nullptr; g = g->fNext) {
+ g->fBlob->unref();
}
}
@@ -41,11 +41,21 @@
, fClipRect{clipRect}
, fBlob{blob}
, fColor{color} {}
+
+ static Geometry* Make(GrRecordingContext* rc,
+ const GrAtlasSubRun& subRun,
+ const SkMatrix& drawMatrix,
+ SkPoint drawOrigin,
+ SkIRect clipRect,
+ GrTextBlob* blob,
+ const SkPMColor4f& color);
void fillVertexData(void* dst, int offset, int count) const;
const GrAtlasSubRun& fSubRun;
const SkMatrix fDrawMatrix;
const SkPoint fDrawOrigin;
+ // fClipRect is only used in the DirectMaskSubRun case to do geometric clipping.
+ // TransformedMaskSubRun, and SDFTSubRun don't use this field, and expect an empty rect.
const SkIRect fClipRect;
GrTextBlob* const fBlob; // mutable to make unref call in Op dtor.
@@ -53,6 +63,7 @@
// a constant color that we then evaluate on the CPU.
// TODO: This can be made const once processor analysis is separated from op creation.
SkPMColor4f fColor;
+ Geometry* fNext{nullptr};
};
const char* name() const override { return "AtlasTextOp"; }
@@ -104,7 +115,7 @@
bool needsTransform,
int glyphCount,
SkRect deviceRect,
- const Geometry& geo,
+ Geometry* geo,
GrPaint&& paint);
GrAtlasTextOp(MaskType maskType,
@@ -114,7 +125,7 @@
SkColor luminanceColor,
bool useGammaCorrectDistanceTable,
uint32_t DFGPFlags,
- const Geometry& geo,
+ Geometry* geo,
GrPaint&& paint);
GrProgramInfo* programInfo() override {
@@ -122,6 +133,14 @@
return nullptr;
}
+ void addGeometry(Geometry* geometry) {
+ *fTail = geometry;
+ // The geometry may have many entries. Find the end.
+ do {
+ fTail = &(*fTail)->fNext;
+ } while (*fTail != nullptr);
+ }
+
void onCreateProgramInfo(const GrCaps*,
SkArenaAlloc*,
const GrSurfaceProxyView& writeView,
@@ -193,14 +212,6 @@
const GrSurfaceProxyView* views,
unsigned int numActiveViews) const;
- // The minimum number of Geometry we will try to allocate as ops are merged together.
- // The atlas text op holds one Geometry inline. When combined with the linear growth policy,
- // the total number of geometries follows 6, 18, 36, 60, 90 (the deltas are 6*n).
- static constexpr auto kMinGeometryAllocated = 6;
-
- GrTBlockList<Geometry> fGeometries{kMinGeometryAllocated,
- GrBlockAllocator::GrowthPolicy::kLinear};
-
GrProcessorSet fProcessors;
int fNumGlyphs; // Sum of glyphs in each geometry's subrun
@@ -218,6 +229,9 @@
// for single-channel distance fields.
const SkColor fLuminanceColor{0};
+ Geometry* fHead{nullptr};
+ Geometry** fTail{&fHead};
+
using INHERITED = GrMeshDrawOp;
};
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 1451c56..ead306f 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -686,16 +686,17 @@
const SkPaint& drawPaint = glyphRunList.paint();
const SkPMColor4f drawingColor =
calculate_colors(rtc, drawPaint, viewMatrix, fMaskFormat, &grPaint);
- GrAtlasTextOp::Geometry geometry = {
+
+ GrRecordingContext* const context = rtc->recordingContext();
+ GrAtlasTextOp::Geometry* geometry = GrAtlasTextOp::Geometry::Make(
+ context,
*this,
drawMatrix,
drawOrigin,
clipRect,
- SkRef(fBlob),
- drawingColor
- };
+ fBlob,
+ drawingColor);
- GrRecordingContext* const context = rtc->recordingContext();
GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(context,
op_mask_type(fMaskFormat),
false,
@@ -974,18 +975,16 @@
GrPaint grPaint;
SkPMColor4f drawingColor = calculate_colors(rtc, drawPaint, viewMatrix, fMaskFormat, &grPaint);
- // We can clip geometrically using clipRect and ignore clip if we're not using SDFs or
- // transformed glyphs, and we have an axis-aligned rectangular non-AA clip.
- GrAtlasTextOp::Geometry geometry = {
+ GrRecordingContext* const context = rtc->recordingContext();
+ GrAtlasTextOp::Geometry* geometry = GrAtlasTextOp::Geometry::Make(
+ context,
*this,
drawMatrix,
drawOrigin,
SkIRect::MakeEmpty(),
- SkRef(fBlob),
- drawingColor
- };
+ fBlob,
+ drawingColor);
- GrRecordingContext* context = rtc->recordingContext();
GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(
context,
op_mask_type(fMaskFormat),
@@ -1247,16 +1246,16 @@
DFGPFlags |= MT::kLCDBGRDistanceField == maskType ? kBGR_DistanceFieldEffectFlag : 0;
}
- GrAtlasTextOp::Geometry geometry = {
+ GrRecordingContext* const context = rtc->recordingContext();
+ GrAtlasTextOp::Geometry* geometry = GrAtlasTextOp::Geometry::Make(
+ context,
*this,
drawMatrix,
drawOrigin,
SkIRect::MakeEmpty(),
- SkRef(fBlob),
- drawingColor
- };
+ fBlob,
+ drawingColor);
- GrRecordingContext* context = rtc->recordingContext();
GrOp::Owner op = GrOp::Make<GrAtlasTextOp>(
context,
maskType,