1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "include/core/SkFont.h" 9 #include "include/core/SkTypeface.h" 10 #include "src/core/SkScalerCache.h" 11 #include "src/core/SkStrikeSpec.h" 12 #include "src/core/SkTaskGroup.h" 13 #include "tests/Test.h" 14 #include "tools/ToolUtils.h" 15 16 #include <atomic> 17 18 class Barrier { 19 public: Barrier(int threadCount)20 Barrier(int threadCount) : fThreadCount(threadCount) { } waitForAll()21 void waitForAll() { 22 fThreadCount -= 1; 23 while (fThreadCount > 0) { } 24 } 25 26 private: 27 std::atomic<int> fThreadCount; 28 }; 29 DEF_TEST(SkScalerCacheMultiThread,Reporter)30 DEF_TEST(SkScalerCacheMultiThread, Reporter) { 31 sk_sp<SkTypeface> typeface = 32 ToolUtils::create_portable_typeface("serif", SkFontStyle::Italic()); 33 static constexpr int kThreadCount = 4; 34 35 Barrier barrier{kThreadCount}; 36 37 SkFont font; 38 font.setEdging(SkFont::Edging::kAntiAlias); 39 font.setSubpixel(true); 40 font.setTypeface(typeface); 41 42 SkGlyphID glyphs['z']; 43 SkPoint pos['z']; 44 for (int c = ' '; c < 'z'; c++) { 45 glyphs[c] = font.unicharToGlyph(c); 46 pos[c] = {30.0f * c + 30, 30.0f}; 47 } 48 constexpr size_t glyphCount = 'z' - ' '; 49 auto data = SkMakeZip(glyphs, pos).subspan(SkTo<int>(' '), glyphCount); 50 51 SkPaint defaultPaint; 52 SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask( 53 font, defaultPaint, SkSurfaceProps(0, kUnknown_SkPixelGeometry), 54 SkScalerContextFlags::kNone, SkMatrix::I()); 55 56 // Make our own executor so the --threads parameter doesn't mess things up. 57 auto executor = SkExecutor::MakeFIFOThreadPool(kThreadCount); 58 for (int tries = 0; tries < 100; tries++) { 59 SkScalerContextEffects effects; 60 std::unique_ptr<SkScalerContext> ctx{ 61 typeface->createScalerContext(effects, &strikeSpec.descriptor())}; 62 SkScalerCache scalerCache{strikeSpec.descriptor(), std::move(ctx)}; 63 64 auto perThread = [&](int threadIndex) { 65 barrier.waitForAll(); 66 67 auto local = data.subspan(threadIndex * 2, data.size() - kThreadCount * 2); 68 for (int i = 0; i < 100; i++) { 69 SkDrawableGlyphBuffer drawable; 70 SkSourceGlyphBuffer rejects; 71 72 drawable.ensureSize(glyphCount); 73 rejects.setSource(local); 74 75 drawable.startDevice(rejects.source(), {0, 0}, SkMatrix::I(), 76 scalerCache.roundingSpec()); 77 scalerCache.prepareForMaskDrawing(&drawable, &rejects); 78 rejects.flipRejectsToSource(); 79 drawable.reset(); 80 } 81 }; 82 83 SkTaskGroup(*executor).batch(kThreadCount, perThread); 84 } 85 } 86