Some more clipped text optimizations.
* Limit size of text batches to keep inside default vertex buffer size
* Expand geodata allocation by 1.5x rather than 2x
* Don't add text subruns that lie outside the clip rect
Bug: skia:3990
Change-Id: I2b8f8bc5599d14c43e0a98e9633bc51980a7619c
Reviewed-on: https://skia-review.googlesource.com/62861
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 257fb3b..21e7c6f 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -315,18 +315,27 @@
}
}
+ // Keep the batch vertex buffer size below 32K so we don't have to create a special one
+ // We use the largest possible vertex size for this
+ static const int kVertexSize = sizeof(SkPoint) + sizeof(SkColor) + 2 * sizeof(uint16_t);
+ static const int kMaxGlyphs = 32768 / (4 * kVertexSize);
+ if (this->fNumGlyphs + that->fNumGlyphs > kMaxGlyphs) {
+ return false;
+ }
+
fNumGlyphs += that->numGlyphs();
// Reallocate space for geo data if necessary and then import that's geo data.
int newGeoCount = that->fGeoCount + fGeoCount;
- // We assume (and here enforce) that the allocation size is the smallest power of two that
- // is greater than or equal to the number of geometries (and at least
- // kMinGeometryAllocated).
- int newAllocSize = GrNextPow2(newGeoCount);
- int currAllocSize = SkTMax<int>(kMinGeometryAllocated, GrNextPow2(fGeoCount));
- if (newGeoCount > currAllocSize) {
+ // We reallocate at a rate of 1.5x to try to get better total memory usage
+ if (newGeoCount > fGeoDataAllocSize) {
+ int newAllocSize = fGeoDataAllocSize + fGeoDataAllocSize/2;
+ while (newAllocSize < newGeoCount) {
+ newAllocSize += newAllocSize / 2;
+ }
fGeoData.realloc(newAllocSize);
+ fGeoDataAllocSize = newAllocSize;
}
// We steal the ref on the blobs from the other AtlasTextOp and set its count to 0 so that
diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h
index 0762736..622b993 100644
--- a/src/gpu/ops/GrAtlasTextOp.h
+++ b/src/gpu/ops/GrAtlasTextOp.h
@@ -117,8 +117,12 @@
GrPixelConfigIsClamped dstIsClamped) override;
private:
+ // The minimum number of Geometry we will try to allocate.
+ static constexpr auto kMinGeometryAllocated = 4;
+
GrAtlasTextOp(GrPaint&& paint)
: INHERITED(ClassID())
+ , fGeoDataAllocSize(kMinGeometryAllocated)
, fColor(paint.getColor())
, fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
, fProcessors(std::move(paint)) {}
@@ -176,9 +180,6 @@
sk_sp<GrGeometryProcessor> setupDfProcessor() const;
- // The minimum number of Geometry we will try to allocate.
- enum { kMinGeometryAllocated = 4 };
-
enum MaskType {
kGrayscaleCoverageMask_MaskType,
kLCDCoverageMask_MaskType,
@@ -190,6 +191,7 @@
};
SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
+ int fGeoDataAllocSize;
GrColor fColor;
uint32_t fSRGBFlags;
GrProcessorSet fProcessors;
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index be83dc1..a6dbd67 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -306,31 +306,39 @@
continue;
}
+ bool skipClip = false;
+ bool submitOp = true;
+ SkIRect clipRect = SkIRect::MakeEmpty();
SkRect rtBounds = SkRect::MakeWH(rtc->width(), rtc->height());
SkRRect clipRRect;
GrAA aa;
- // we can clip geometrically if we're not using SDFs,
+ // We can clip geometrically if we're not using SDFs,
// and we have an axis-aligned rectangular non-AA clip
- bool skipClip = false;
- SkIRect clipRect = SkIRect::MakeEmpty();
if (!info.drawAsDistanceFields() && clip.isRRect(rtBounds, &clipRRect, &aa) &&
clipRRect.isRect() && GrAA::kNo == aa) {
skipClip = true;
- // we only need to do clipping work if the subrun isn't contained by the clip
+ // We only need to do clipping work if the subrun isn't contained by the clip
SkRect subRunBounds;
this->computeSubRunBounds(&subRunBounds, run, subRun, viewMatrix, x, y);
if (!clipRRect.getBounds().contains(subRunBounds)) {
- clipRRect.getBounds().round(&clipRect);
+ // If the subrun is completely outside, don't add an op for it
+ if (!clipRRect.getBounds().intersects(subRunBounds)) {
+ submitOp = false;
+ } else {
+ clipRRect.getBounds().round(&clipRect);
+ }
}
}
- auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, clipRect,
- std::move(paint), props, distanceAdjustTable, cache, rtc);
- if (op) {
- if (skipClip) {
- rtc->addDrawOp(GrNoClip(), std::move(op));
- } else {
- rtc->addDrawOp(clip, std::move(op));
+ if (submitOp) {
+ auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, clipRect,
+ std::move(paint), props, distanceAdjustTable, cache, rtc);
+ if (op) {
+ if (skipClip) {
+ rtc->addDrawOp(GrNoClip(), std::move(op));
+ } else {
+ rtc->addDrawOp(clip, std::move(op));
+ }
}
}
}