print telemetry for diagnosing text drawing problems in Chrome
Dump information about the Difference, Serialization, Deserialization, and Drawing phases of Renderer/GPU text drawing. Add the following to your args.gn to turn on telemetry. extra_cflags = ["-D", "SK_TRACE_GLYPH_RUN_PROCESS"] Change-Id: If435257574b74910822dbb90cc9dbca311578fe8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/385696 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
4dff68a166
commit
7b39c3d1ae
@ -83,6 +83,18 @@ bool SkDescriptor::operator==(const SkDescriptor& other) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
SkString SkDescriptor::dumpRec() const {
|
||||
const SkScalerContextRec* rec = static_cast<const SkScalerContextRec*>(
|
||||
this->findEntry(kRec_SkDescriptorTag, nullptr));
|
||||
|
||||
SkString result;
|
||||
result.appendf(" Checksum: %x\n", fChecksum);
|
||||
if (rec != nullptr) {
|
||||
result.append(rec->dump());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) {
|
||||
const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
|
||||
size_t len = desc->fLength - sizeof(uint32_t);
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
uint32_t getCount() const { return fCount; }
|
||||
#endif
|
||||
|
||||
SkString dumpRec() const;
|
||||
|
||||
private:
|
||||
SkDescriptor() = default;
|
||||
friend class SkDescriptorTestHelper;
|
||||
|
@ -98,6 +98,16 @@ void SkDrawableGlyphBuffer::startGPUDevice(
|
||||
SkDEBUGCODE(fPhase = kInput);
|
||||
}
|
||||
|
||||
SkString SkDrawableGlyphBuffer::dumpInput() const {
|
||||
SkASSERT(fPhase == kInput);
|
||||
|
||||
SkString msg;
|
||||
for (auto [packedGlyphID, pos]
|
||||
: SkZip<SkGlyphVariant, SkPoint>{fInputSize, fMultiBuffer.get(), fPositions.get()}) {
|
||||
msg.appendf("0x%x:(%a,%a), ", packedGlyphID.packedID().value(), pos.x(), pos.y());
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
void SkDrawableGlyphBuffer::reset() {
|
||||
SkDEBUGCODE(fPhase = kReset);
|
||||
|
@ -172,6 +172,8 @@ public:
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkGlyphPositionRoundingSpec& roundingSpec);
|
||||
|
||||
SkString dumpInput() const;
|
||||
|
||||
// The input of SkPackedGlyphIDs
|
||||
SkZip<SkGlyphVariant, SkPoint> input() {
|
||||
SkASSERT(fPhase == kInput);
|
||||
|
@ -136,12 +136,25 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
|
||||
}
|
||||
}
|
||||
|
||||
// Use the following in your args.gn to dump telemetry for diagnosing chrome Renderer/GPU
|
||||
// differences.
|
||||
// extra_cflags = ["-D", "SK_TRACE_GLYPH_RUN_PROCESS"]
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkPaint& runPaint,
|
||||
const GrSDFTControl& control,
|
||||
SkGlyphRunPainterInterface* process) {
|
||||
SkGlyphRunPainterInterface* process,
|
||||
const char* tag) {
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
SkString msg;
|
||||
msg.appendf("\nStart glyph run processing");
|
||||
if (tag != nullptr) {
|
||||
msg.appendf(" for %s ", tag);
|
||||
}
|
||||
msg.appendf("\n");
|
||||
#endif
|
||||
ScopedBuffers _ = this->ensureBuffers(glyphRun);
|
||||
fRejects.setSource(glyphRun.source());
|
||||
const SkFont& runFont = glyphRun.font();
|
||||
@ -153,10 +166,17 @@ void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
const auto& [strikeSpec, minScale, maxScale] =
|
||||
SkStrikeSpec::MakeSDFT(runFont, runPaint, fDeviceProps, drawMatrix, control);
|
||||
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" SDFT case:\n%s", strikeSpec.dump().c_str());
|
||||
#endif
|
||||
|
||||
if (!strikeSpec.isEmpty()) {
|
||||
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
|
||||
|
||||
fDrawable.startSource(fRejects.source());
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" glyphs:(x,y):\n %s\n", fDrawable.dumpInput().c_str());
|
||||
#endif
|
||||
strike->prepareForSDFTDrawing(&fDrawable, &fRejects);
|
||||
fRejects.flipRejectsToSource();
|
||||
|
||||
@ -175,9 +195,16 @@ void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
|
||||
runFont, runPaint, fDeviceProps, fScalerContextFlags, drawMatrix);
|
||||
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" Mask case:\n%s", strikeSpec.dump().c_str());
|
||||
#endif
|
||||
|
||||
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
|
||||
|
||||
fDrawable.startGPUDevice(fRejects.source(), drawMatrix, strike->roundingSpec());
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" glyphs:(x,y):\n %s\n", fDrawable.dumpInput().c_str());
|
||||
#endif
|
||||
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
|
||||
fRejects.flipRejectsToSource();
|
||||
|
||||
@ -198,10 +225,17 @@ void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
SkStrikeSpec strikeSpec = 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 (!strikeSpec.isEmpty()) {
|
||||
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
|
||||
|
||||
fDrawable.startSource(fRejects.source());
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" glyphs:(x,y):\n %s\n", fDrawable.dumpInput().c_str());
|
||||
#endif
|
||||
strike->prepareForPathDrawing(&fDrawable, &fRejects);
|
||||
fRejects.flipRejectsToSource();
|
||||
maxDimensionInSourceSpace =
|
||||
@ -221,10 +255,17 @@ void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
runFont, runPaint, fDeviceProps,
|
||||
fScalerContextFlags, maxDimensionInSourceSpace);
|
||||
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf("Transformed case:\n%s", strikeSpec.dump().c_str());
|
||||
#endif
|
||||
|
||||
if (!strikeSpec.isEmpty()) {
|
||||
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
|
||||
|
||||
fDrawable.startSource(fRejects.source());
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf("glyphs:(x,y):\n %s\n", fDrawable.dumpInput().c_str());
|
||||
#endif
|
||||
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
|
||||
fRejects.flipRejectsToSource();
|
||||
SkASSERT(fRejects.source().empty());
|
||||
@ -234,6 +275,13 @@ void SkGlyphRunListPainter::processGlyphRun(const SkGlyphRun& glyphRun,
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf("End glyph run processing");
|
||||
if (tag != nullptr) {
|
||||
msg.appendf(" for %s ", tag);
|
||||
}
|
||||
SkDebugf("%s\n", msg.c_str());
|
||||
#endif
|
||||
}
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
|
@ -87,7 +87,8 @@ public:
|
||||
const SkMatrix& drawMatrix,
|
||||
const SkPaint& drawPaint,
|
||||
const GrSDFTControl& control,
|
||||
SkGlyphRunPainterInterface* process);
|
||||
SkGlyphRunPainterInterface* process,
|
||||
const char* tag = nullptr);
|
||||
#endif // SK_SUPPORT_GPU
|
||||
|
||||
private:
|
||||
|
@ -654,6 +654,10 @@ sk_sp<SkData> SkStrikeServerImpl::serializeTypeface(SkTypeface* tf) {
|
||||
}
|
||||
|
||||
void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
SkString msg;
|
||||
msg.appendf("\nBegin send strike differences\n");
|
||||
#endif
|
||||
size_t strikesToSend = 0;
|
||||
fRemoteStrikesToSend.foreach ([&](RemoteStrike* strike) {
|
||||
if (strike->hasPendingGlyphs()) {
|
||||
@ -686,6 +690,9 @@ void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
|
||||
auto it = fDescToRemoteStrike.find(&strike->getDescriptor());
|
||||
SkASSERT(it != fDescToRemoteStrike.end());
|
||||
SkASSERT(it->second.get() == strike);
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.append(strike->getDescriptor().dumpRec());
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
@ -694,10 +701,17 @@ void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
|
||||
strike->writePendingGlyphs(&serializer);
|
||||
strike->resetScalerContext();
|
||||
}
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.append(strike->getDescriptor().dumpRec());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
);
|
||||
fRemoteStrikesToSend.reset();
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf("End send strike differences");
|
||||
SkDebugf("%s\n", msg.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
RemoteStrike* SkStrikeServerImpl::getOrCreateCache(
|
||||
@ -831,7 +845,8 @@ protected:
|
||||
drawMatrix,
|
||||
glyphRunList.paint(),
|
||||
control,
|
||||
nullptr);
|
||||
nullptr,
|
||||
"Cache Diff");
|
||||
}
|
||||
#endif // SK_SUPPORT_GPU
|
||||
}
|
||||
@ -994,6 +1009,11 @@ bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memo
|
||||
addTypeface(wire);
|
||||
}
|
||||
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
SkString msg;
|
||||
msg.appendf("\nBegin receive strike differences\n");
|
||||
#endif
|
||||
|
||||
if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE
|
||||
|
||||
for (size_t i = 0; i < strikeCount; ++i) {
|
||||
@ -1002,6 +1022,9 @@ bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memo
|
||||
|
||||
SkAutoDescriptor sourceAd;
|
||||
if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" Received descriptor:\n%s", sourceAd.getDesc()->dumpRec().c_str());
|
||||
#endif
|
||||
|
||||
bool fontMetricsInitialized;
|
||||
if (!deserializer.read(&fontMetricsInitialized)) READ_FAILURE
|
||||
@ -1023,6 +1046,9 @@ bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memo
|
||||
SkAutoDescriptor ad;
|
||||
auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad);
|
||||
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf(" Mapped descriptor:\n%s", client_desc->dumpRec().c_str());
|
||||
#endif
|
||||
auto strike = fStrikeCache->findStrike(*client_desc);
|
||||
// Metrics are only sent the first time. If the metrics are not initialized, there must
|
||||
// be an existing strike.
|
||||
@ -1077,6 +1103,11 @@ bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memo
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SK_TRACE_GLYPH_RUN_PROCESS)
|
||||
msg.appendf("End receive strike differences");
|
||||
SkDebugf("%s\n", msg.c_str());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -128,13 +128,13 @@ public:
|
||||
|
||||
SkString dump() const {
|
||||
SkString msg;
|
||||
msg.appendf("Rec\n");
|
||||
msg.appendf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
|
||||
msg.appendf(" Rec\n");
|
||||
msg.appendf(" textsize %a prescale %a preskew %a post [%a %a %a %a]\n",
|
||||
fTextSize, fPreScaleX, fPreSkewX, fPost2x2[0][0],
|
||||
fPost2x2[0][1], fPost2x2[1][0], fPost2x2[1][1]);
|
||||
msg.appendf(" frame %g miter %g format %d join %d cap %d flags %#hx\n",
|
||||
msg.appendf(" frame %g miter %g format %d join %d cap %d flags %#hx\n",
|
||||
fFrameWidth, fMiterLimit, fMaskFormat, fStrokeJoin, fStrokeCap, fFlags);
|
||||
msg.appendf(" lum bits %x, device gamma %d, paint gamma %d contrast %d\n", fLumBits,
|
||||
msg.appendf(" lum bits %x, device gamma %d, paint gamma %d contrast %d\n", fLumBits,
|
||||
fDeviceGamma, fPaintGamma, fContrast);
|
||||
return msg;
|
||||
}
|
||||
|
@ -140,6 +140,10 @@ bool SkStrikeSpec::ShouldDrawAsPath(
|
||||
|| distance(SkMatrix::kMSkewX, SkMatrix::kMScaleY) > maxSizeSquared;
|
||||
}
|
||||
|
||||
SkString SkStrikeSpec::dump() const {
|
||||
return fAutoDescriptor.getDesc()->dumpRec();
|
||||
}
|
||||
|
||||
SkStrikeSpec SkStrikeSpec::MakePDFVector(const SkTypeface& typeface, int* size) {
|
||||
SkFont font;
|
||||
font.setHinting(SkFontHinting::kNone);
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
bool isEmpty() const { return SkScalarNearlyZero(fStrikeToSourceRatio); }
|
||||
const SkDescriptor& descriptor() const { return *fAutoDescriptor.getDesc(); }
|
||||
static bool ShouldDrawAsPath(const SkPaint& paint, const SkFont& font, const SkMatrix& matrix);
|
||||
SkString dump() const;
|
||||
|
||||
private:
|
||||
SkStrikeSpec(
|
||||
|
@ -1506,7 +1506,8 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
|
||||
drawMatrix,
|
||||
glyphRunList.paint(),
|
||||
control,
|
||||
blob.get());
|
||||
blob.get(),
|
||||
"GrTextBlob");
|
||||
}
|
||||
|
||||
return blob;
|
||||
|
Loading…
Reference in New Issue
Block a user