| /* | |
| * Copyright 2020 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "bench/Benchmark.h" | |
| #include "include/core/SkCanvas.h" | |
| #include "include/core/SkColorSpace.h" | |
| #include "include/core/SkFont.h" | |
| #include "include/core/SkTypeface.h" | |
| #include "include/gpu/ganesh/GrDirectContext.h" | |
| #include "include/gpu/ganesh/GrRecordingContext.h" | |
| #include "src/core/SkStrikeCache.h" | |
| #include "src/core/SkUTF.h" | |
| #include "src/core/SkUtils.h" | |
| #include "src/gpu/ganesh/GrDirectContextPriv.h" | |
| #include "src/gpu/ganesh/SkGr.h" | |
| #include "src/gpu/ganesh/text/GlyphData.h" | |
| #include "src/text/GlyphRun.h" | |
| #include "src/text/gpu/StrikeCache.h" | |
| #include "src/text/gpu/TextBlob.h" | |
| #include "tools/fonts/FontToolUtils.h" | |
| #include "tools/ganesh/TestCanvas.h" | |
| #include "tools/text/gpu/TextBlobTools.h" | |
| // From Project Guttenberg. This is UTF-8 text. | |
| static const char* gText = | |
| "Call me Ishmael. Some years ago--never mind how long precisely"; | |
| class FillBench {}; | |
| template <> class skiatest::TestCanvas<FillBench> { | |
| public: | |
| static SkDevice* GetDevice(SkCanvas* canvas) { | |
| return canvas->topDevice(); | |
| } | |
| }; | |
| class DirectMaskGlyphVertexFillBenchmark : public Benchmark { | |
| using Glyph = skgpu::ganesh::Glyph; | |
| using GlyphData = skgpu::ganesh::GlyphData; | |
| bool isSuitableFor(Backend backend) override { | |
| return backend == Backend::kGanesh; | |
| } | |
| const char* onGetName() override { | |
| return "DirectMaskGlyphVertexFillBenchmark"; | |
| } | |
| void onPerCanvasPreDraw(SkCanvas* canvas) override { | |
| auto typeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle()); | |
| SkFont font(typeface); | |
| SkMatrix view = SkMatrix::I(); | |
| size_t len = strlen(gText); | |
| sktext::GlyphRunBuilder builder; | |
| SkPaint paint; | |
| auto glyphRunList = builder.textToGlyphRunList(font, paint, gText, len, {100, 100}); | |
| SkASSERT_RELEASE(!glyphRunList.empty()); | |
| auto device = skiatest::TestCanvas<FillBench>::GetDevice(canvas); | |
| SkMatrix drawMatrix = view; | |
| const SkPoint drawOrigin = glyphRunList.origin(); | |
| drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y()); | |
| fBlob = sktext::gpu::TextBlob::Make(glyphRunList, | |
| paint, | |
| drawMatrix, | |
| device->strikeDeviceInfo(), | |
| SkStrikeCache::GlobalStrikeCache()); | |
| const sktext::gpu::AtlasSubRun* subRun = | |
| sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get()); | |
| SkASSERT_RELEASE(subRun); | |
| if (!subRun->glyphVector().hasBackendData()) { | |
| // Since isSuitableFor() requires Ganesh and this is nanobench, we know the canvas | |
| // will be backed by a direct context. | |
| GrDirectContext* ctx = canvas->recordingContext()->asDirectContext(); | |
| GrAtlasManager* atlasMgr = ctx->priv().getAtlasManager(); | |
| subRun->glyphVector().initBackendData<GlyphData>(&fCache, | |
| atlasMgr, | |
| subRun->maskFormat(), | |
| subRun->glyphSrcPadding(), | |
| /*isSDF=*/false); | |
| } | |
| const auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>(); | |
| fVertices.reset(new char[glyphData.vertexStride(subRun->maskFormat(), drawMatrix) * | |
| subRun->glyphCount() * 4]); | |
| } | |
| void onDraw(int loops, SkCanvas* canvas) override { | |
| const sktext::gpu::AtlasSubRun* subRun = | |
| sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get()); | |
| SkASSERT_RELEASE(subRun); | |
| SkIRect clip = SkIRect::MakeEmpty(); | |
| SkPaint paint; | |
| SkPMColor4f pmColor = SkColorToPMColor4f(paint.getColor(), /*colorInfo=*/{}); | |
| SkMatrix positionMatrix = SkMatrix::Translate(100, 100); | |
| auto& glyphData = subRun->glyphVector().accessBackendData<GlyphData>(); | |
| SkSpan<const Glyph> glyphs = subRun->glyphVector().accessBackendGlyphs<Glyph>(); | |
| for (int loop = 0; loop < loops; loop++) { | |
| glyphData.fillVertexData(subRun->vertexFiller(), | |
| glyphs, | |
| 0, | |
| subRun->glyphCount(), | |
| pmColor, | |
| positionMatrix, | |
| clip, | |
| fVertices.get()); | |
| } | |
| } | |
| private: | |
| sk_sp<sktext::gpu::TextBlob> fBlob; | |
| sktext::gpu::StrikeCache fCache; | |
| std::unique_ptr<char[]> fVertices; | |
| }; | |
| DEF_BENCH(return new DirectMaskGlyphVertexFillBenchmark{}) |