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