Have processGlyphRun take a glyphRunList, and rename function

Rename processGlyphRun to categorizeGlyphRunList. Change processing
a single glyph run to processing the entire list. By taking
an SkGlyphRunList the code will have access to the buffers it needs
for processing when I move the buffers to the builder.

Clean up - remove some unneeded includes.

Change-Id: I2ce66292b7e63b9cbc63610ba9653b255417d7c1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/538037
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2022-05-06 10:34:58 -04:00 committed by SkCQ
parent 5d553ed398
commit 9f44b7fa84
6 changed files with 161 additions and 196 deletions

View File

@ -2151,13 +2151,9 @@ generated_cc_atom(
"//include/core:SkColorSpace_hdr",
"//include/core:SkMaskFilter_hdr",
"//include/core:SkPathEffect_hdr",
"//include/gpu:GrRecordingContext_hdr",
"//include/private:SkTDArray_hdr",
"//src/gpu/ganesh:GrCaps_hdr",
"//src/gpu/ganesh:GrColorInfo_hdr",
"//src/gpu/ganesh:GrDirectContextPriv_hdr",
"//src/gpu/ganesh:GrRecordingContextPriv_hdr",
"//src/gpu/ganesh:SkGr_hdr",
"//src/gpu/ganesh/text:GrSDFTControl_hdr",
"//src/gpu/ganesh/text:GrTextBlobRedrawCoordinator_hdr",
"//src/gpu/ganesh/v1:SurfaceDrawContext_v1_hdr",

View File

@ -825,16 +825,8 @@ protected:
SkMatrix drawMatrix = this->localToDevice();
drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
const uint64_t uniqueID = glyphRunList.uniqueID();
for (auto& glyphRun : glyphRunList) {
fPainter.processGlyphRun(nullptr,
glyphRun,
drawMatrix,
drawingPaint,
control,
"Cache Diff",
uniqueID);
}
fPainter.categorizeGlyphRunList(
nullptr, glyphRunList, drawMatrix, drawingPaint, control, "Cache Diff");
}
sk_sp<GrSlug> convertGlyphRunListToSlug(const SkGlyphRunList& glyphRunList,
@ -856,14 +848,8 @@ protected:
// Use the lightweight strike cache provided by SkRemoteGlyphCache through fPainter to do
// the analysis.
for (auto& glyphRun : glyphRunList) {
fPainter.processGlyphRun(nullptr,
glyphRun,
positionMatrix,
drawingPaint,
control,
"Convert Slug Analysis");
}
fPainter.categorizeGlyphRunList(
nullptr, glyphRunList, positionMatrix, drawingPaint, control, "Convert Slug Analysis");
// Use the glyph strike cache to get actual glyph information.
return skgpu::v1::MakeSlug(this->localToDevice(),

View File

@ -8,12 +8,8 @@
#include "src/core/SkGlyphRunPainter.h"
#if SK_SUPPORT_GPU
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrColorInfo.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/text/GrSDFTControl.h"
#include "src/gpu/ganesh/text/GrTextBlobRedrawCoordinator.h"
#include "src/gpu/ganesh/v1/SurfaceDrawContext_v1.h"
@ -276,13 +272,13 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
// extra_cflags = ["-D", "SK_TRACE_GLYPH_RUN_PROCESS"]
#if SK_SUPPORT_GPU
void SkGlyphRunListPainter::processGlyphRun(SkGlyphRunPainterInterface* process,
const SkGlyphRun& glyphRun,
const SkMatrix& positionMatrix,
const SkPaint& runPaint,
const GrSDFTControl& control,
const char* tag,
uint64_t uniqueID) {
void SkGlyphRunListPainter::categorizeGlyphRunList(SkGlyphRunPainterInterface* process,
const SkGlyphRunList& glyphRunList,
const SkMatrix& positionMatrix,
const SkPaint& runPaint,
const GrSDFTControl& control,
const char* tag) {
[[maybe_unused]] const uint64_t uniqueID = glyphRunList.uniqueID();
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
SkString msg;
msg.appendf("\nStart glyph run processing");
@ -297,23 +293,93 @@ void SkGlyphRunListPainter::processGlyphRun(SkGlyphRunPainterInterface* process,
positionMatrix[0], positionMatrix[1], positionMatrix[2],
positionMatrix[3], positionMatrix[4], positionMatrix[5]);
#endif
ScopedBuffers _ = this->ensureBuffers(glyphRun);
fRejected.setSource(glyphRun.source());
const SkFont& runFont = glyphRun.font();
// Only consider using direct or SDFT drawing if not drawing hairlines and not perspective.
if ((runPaint.getStyle() != SkPaint::kStroke_Style || runPaint.getStrokeWidth() != 0)
&& !positionMatrix.hasPerspective()) {
SkScalar approximateDeviceTextSize =
SkFontPriv::ApproximateTransformedTextSize(runFont, positionMatrix);
for (auto& glyphRun : glyphRunList) {
ScopedBuffers _ = this->ensureBuffers(glyphRun);
fRejected.setSource(glyphRun.source());
const SkFont& runFont = glyphRun.font();
if (control.isSDFT(approximateDeviceTextSize, runPaint)) {
// Process SDFT - This should be the .009% case.
const auto& [strikeSpec, strikeToSourceScale, matrixRange] =
SkStrikeSpec::MakeSDFT(runFont, runPaint, fDeviceProps, positionMatrix, control);
// Only consider using direct or SDFT drawing if not drawing hairlines and not perspective.
if ((runPaint.getStyle() != SkPaint::kStroke_Style || runPaint.getStrokeWidth() != 0)
&& !positionMatrix.hasPerspective()) {
SkScalar approximateDeviceTextSize =
SkFontPriv::ApproximateTransformedTextSize(runFont, positionMatrix);
if (control.isSDFT(approximateDeviceTextSize, runPaint)) {
// Process SDFT - This should be the .009% case.
const auto& [strikeSpec, strikeToSourceScale, matrixRange] =
SkStrikeSpec::MakeSDFT(
runFont, runPaint, fDeviceProps, positionMatrix, control);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" SDFT case:\n%s", strikeSpec.dump().c_str());
#endif
if (!SkScalarNearlyZero(strikeToSourceScale)) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startSource(fRejected.source());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForSDFTDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
if (process && !fAccepted.empty()) {
// processSourceSDFT must be called even if there are no glyphs to make sure
// runs are set correctly.
process->processSourceSDFT(fAccepted.accepted(),
strike->getUnderlyingStrike(),
strikeToSourceScale,
runFont,
matrixRange);
}
}
}
if (!fRejected.source().empty()) {
// Process masks including ARGB - this should be the 99.99% case.
// This will handle medium size emoji that are sharing the run with SDFT drawn text.
// If things are too big they will be passed along to the drawing of last resort
// below.
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
runFont, runPaint, fDeviceProps, fScalerContextFlags, positionMatrix);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" Mask case:\n%s", strikeSpec.dump().c_str());
#endif
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startDevicePositioning(
fRejected.source(), positionMatrix, strike->roundingSpec());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForMaskDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
if (process && !fAccepted.empty()) {
// processDeviceMasks must be called even if there are no glyphs to make sure
// runs are set correctly.
process->processDeviceMasks(
fAccepted.accepted(), strike->getUnderlyingStrike());
}
}
}
// Glyphs are generated in different scales relative to the source space. Masks are drawn
// in device space, and SDFT and Paths are draw in a fixed constant space. The
// maxDimensionInSourceSpace is used to calculate the factor from strike space to source
// space.
SkScalar maxDimensionInSourceSpace = 0.0;
if (!fRejected.source().empty()) {
// Drawable case - handle big things with that have a drawable.
auto [strikeSpec, strikeToSourceScale] =
SkStrikeSpec::MakePath(runFont, runPaint, fDeviceProps, fScalerContextFlags);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" SDFT case:\n%s", strikeSpec.dump().c_str());
msg.appendf(" Drawable case:\n%s", strikeSpec.dump().c_str());
#endif
if (!SkScalarNearlyZero(strikeToSourceScale)) {
@ -323,142 +389,78 @@ void SkGlyphRunListPainter::processGlyphRun(SkGlyphRunPainterInterface* process,
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForSDFTDrawing(&fAccepted, &fRejected);
strike->prepareForDrawableDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
auto [minHint, maxHint] = fRejected.maxDimensionHint();
maxDimensionInSourceSpace = SkScalarCeilToScalar(maxHint * strikeToSourceScale);
if (process && !fAccepted.empty()) {
// processSourceSDFT must be called even if there are no glyphs to make sure
// processSourceDrawables must be called even if there are no glyphs to make
// sure runs are set correctly.
process->processSourceDrawables(fAccepted.accepted(),
runFont,
strikeSpec.descriptor(),
strikeToSourceScale);
}
}
}
if (!fRejected.source().empty()) {
// Path case - handle big things without color and that have a path.
auto [strikeSpec, strikeToSourceScale] =
SkStrikeSpec::MakePath(runFont, runPaint, fDeviceProps, fScalerContextFlags);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" Path case:\n%s", strikeSpec.dump().c_str());
#endif
if (!SkScalarNearlyZero(strikeToSourceScale)) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startSource(fRejected.source());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForPathDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
auto [minHint, maxHint] = fRejected.maxDimensionHint();
maxDimensionInSourceSpace = SkScalarCeilToScalar(maxHint * strikeToSourceScale);
if (process && !fAccepted.empty()) {
// processSourcePaths must be called even if there are no glyphs to make sure
// runs are set correctly.
process->processSourceSDFT(fAccepted.accepted(),
strike->getUnderlyingStrike(),
strikeToSourceScale,
runFont,
matrixRange);
process->processSourcePaths(fAccepted.accepted(),
runFont,
strikeSpec.descriptor(),
strikeToSourceScale);
}
}
}
if (!fRejected.source().empty()) {
// Process masks including ARGB - this should be the 99.99% case.
// This will handle medium size emoji that are sharing the run with SDFT drawn text.
// If things are too big they will be passed along to the drawing of last resort below.
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
runFont, runPaint, fDeviceProps, fScalerContextFlags, positionMatrix);
if (!fRejected.source().empty() && maxDimensionInSourceSpace != 0) {
// Draw of last resort. Scale the bitmap to the screen.
auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeSourceFallback(
runFont, runPaint, fDeviceProps,
fScalerContextFlags, maxDimensionInSourceSpace);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" Mask case:\n%s", strikeSpec.dump().c_str());
msg.appendf("Transformed case:\n%s", strikeSpec.dump().c_str());
#endif
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
if (!SkScalarNearlyZero(strikeToSourceScale)) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startDevicePositioning(
fRejected.source(), positionMatrix, strike->roundingSpec());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForMaskDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
fAccepted.startSource(fRejected.source());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf("glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForMaskDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
SkASSERT(fRejected.source().empty());
if (process && !fAccepted.empty()) {
// processDeviceMasks must be called even if there are no glyphs to make sure runs
// are set correctly.
process->processDeviceMasks(fAccepted.accepted(), strike->getUnderlyingStrike());
}
}
}
// Glyphs are generated in different scales relative to the source space. Masks are drawn
// in device space, and SDFT and Paths are draw in a fixed constant space. The
// maxDimensionInSourceSpace is used to calculate the factor from strike space to source
// space.
SkScalar maxDimensionInSourceSpace = 0.0;
if (!fRejected.source().empty()) {
// Drawable case - handle big things with that have a drawable.
auto [strikeSpec, strikeToSourceScale] =
SkStrikeSpec::MakePath(runFont, runPaint, fDeviceProps, fScalerContextFlags);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" Drawable case:\n%s", strikeSpec.dump().c_str());
#endif
if (!SkScalarNearlyZero(strikeToSourceScale)) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startSource(fRejected.source());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForDrawableDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
auto [minHint, maxHint] = fRejected.maxDimensionHint();
maxDimensionInSourceSpace = SkScalarCeilToScalar(maxHint * strikeToSourceScale);
if (process && !fAccepted.empty()) {
// processSourceDrawables must be called even if there are no glyphs to make sure
// runs are set correctly.
process->processSourceDrawables(fAccepted.accepted(),
runFont,
strikeSpec.descriptor(),
strikeToSourceScale);
}
}
}
if (!fRejected.source().empty()) {
// Path case - handle big things without color and that have a path.
auto [strikeSpec, strikeToSourceScale] =
SkStrikeSpec::MakePath(runFont, runPaint, fDeviceProps, fScalerContextFlags);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" Path case:\n%s", strikeSpec.dump().c_str());
#endif
if (!SkScalarNearlyZero(strikeToSourceScale)) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startSource(fRejected.source());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf(" glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForPathDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
auto [minHint, maxHint] = fRejected.maxDimensionHint();
maxDimensionInSourceSpace = SkScalarCeilToScalar(maxHint * strikeToSourceScale);
if (process && !fAccepted.empty()) {
// processSourcePaths must be called even if there are no glyphs to make sure
// runs are set correctly.
process->processSourcePaths(fAccepted.accepted(),
runFont,
strikeSpec.descriptor(),
strikeToSourceScale);
}
}
}
if (!fRejected.source().empty() && maxDimensionInSourceSpace != 0) {
// Draw of last resort. Scale the bitmap to the screen.
auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeSourceFallback(
runFont, runPaint, fDeviceProps,
fScalerContextFlags, maxDimensionInSourceSpace);
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf("Transformed case:\n%s", strikeSpec.dump().c_str());
#endif
if (!SkScalarNearlyZero(strikeToSourceScale)) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
fAccepted.startSource(fRejected.source());
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
msg.appendf("glyphs:(x,y):\n %s\n", fAccepted.dumpInput().c_str());
#endif
strike->prepareForMaskDrawing(&fAccepted, &fRejected);
fRejected.flipRejectsToSource();
SkASSERT(fRejected.source().empty());
if (process && !fAccepted.empty()) {
process->processSourceMasks(
if (process && !fAccepted.empty()) {
process->processSourceMasks(
fAccepted.accepted(), strike->getUnderlyingStrike(), strikeToSourceScale);
}
}
}
}

View File

@ -85,13 +85,12 @@ public:
// A nullptr for process means that the calls to the cache will be performed, but none of the
// callbacks will be called.
// N.B. The positionMatrix has already been translated to the glyph run list origin.
void processGlyphRun(SkGlyphRunPainterInterface* process,
const SkGlyphRun& glyphRun,
const SkMatrix& positionMatrix,
const SkPaint& drawPaint,
const GrSDFTControl& control,
const char* tag = nullptr,
uint64_t blobID = SK_InvalidUniqueID);
void categorizeGlyphRunList(SkGlyphRunPainterInterface* process,
const SkGlyphRunList& glyphRunList,
const SkMatrix& positionMatrix,
const SkPaint& drawPaint,
const GrSDFTControl& control,
const char* tag = nullptr);
#endif // SK_SUPPORT_GPU
private:

View File

@ -169,7 +169,6 @@ generated_cc_atom(
"//src/gpu/ganesh:GrBlurUtils_hdr",
"//src/gpu/ganesh:GrClip_hdr",
"//src/gpu/ganesh:GrMeshDrawTarget_hdr",
"//src/gpu/ganesh:GrRecordingContextPriv_hdr",
"//src/gpu/ganesh:GrStyle_hdr",
"//src/gpu/ganesh:SkGr_hdr",
"//src/gpu/ganesh/effects:GrDistanceFieldGeoProc_hdr",

View File

@ -22,7 +22,6 @@
#include "src/core/SkStrikeSpec.h"
#include "src/gpu/ganesh/GrClip.h"
#include "src/gpu/ganesh/GrMeshDrawTarget.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrStyle.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/effects/GrDistanceFieldGeoProc.h"
@ -2188,16 +2187,8 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
sk_sp<GrTextBlob> blob = sk_sp<GrTextBlob>(initializer.initialize(
std::move(alloc), totalMemoryAllocated, positionMatrix, initialLuminance));
const uint64_t uniqueID = glyphRunList.uniqueID();
for (auto& glyphRun : glyphRunList) {
painter->processGlyphRun(blob.get(),
glyphRun,
positionMatrix,
paint,
control,
"GrTextBlob",
uniqueID);
}
painter->categorizeGlyphRunList(
blob.get(), glyphRunList, positionMatrix, paint, control, "GrTextBlob");
return blob;
}
@ -2516,16 +2507,8 @@ sk_sp<Slug> Slug::Make(const SkMatrixProvider& viewMatrix,
std::move(alloc), glyphRunList.sourceBounds(), initialPaint, positionMatrix,
glyphRunList.origin()));
const uint64_t uniqueID = glyphRunList.uniqueID();
for (auto& glyphRun : glyphRunList) {
painter->processGlyphRun(slug.get(),
glyphRun,
positionMatrix,
drawingPaint,
control,
"Make Slug",
uniqueID);
}
painter->categorizeGlyphRunList(
slug.get(), glyphRunList, positionMatrix, drawingPaint, control, "Make Slug");
// There is nothing to draw here. This is particularly a problem with RSX form blobs where a
// single space becomes a run with no glyphs.