1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 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/SkBitmap.h" 9cb93a386Sopenharmony_ci#include "include/core/SkGraphics.h" 10cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 11cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h" 12cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 13cb93a386Sopenharmony_ci#include "include/private/SkMutex.h" 14cb93a386Sopenharmony_ci#include "src/core/SkDraw.h" 15cb93a386Sopenharmony_ci#include "src/core/SkRemoteGlyphCache.h" 16cb93a386Sopenharmony_ci#include "src/core/SkScalerCache.h" 17cb93a386Sopenharmony_ci#include "src/core/SkStrikeCache.h" 18cb93a386Sopenharmony_ci#include "src/core/SkStrikeSpec.h" 19cb93a386Sopenharmony_ci#include "src/core/SkSurfacePriv.h" 20cb93a386Sopenharmony_ci#include "src/core/SkTypeface_remote.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 22cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 23cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 24cb93a386Sopenharmony_ci#include "src/gpu/text/GrSDFTControl.h" 25cb93a386Sopenharmony_ci#include "tests/Test.h" 26cb93a386Sopenharmony_ci#include "tools/Resources.h" 27cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 28cb93a386Sopenharmony_ci#include "tools/fonts/TestEmptyTypeface.h" 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ciclass DiscardableManager : public SkStrikeServer::DiscardableHandleManager, 31cb93a386Sopenharmony_ci public SkStrikeClient::DiscardableHandleManager { 32cb93a386Sopenharmony_cipublic: 33cb93a386Sopenharmony_ci DiscardableManager() { sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount)); } 34cb93a386Sopenharmony_ci ~DiscardableManager() override = default; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci // Server implementation. 37cb93a386Sopenharmony_ci SkDiscardableHandleId createHandle() override { 38cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci // Handles starts as locked. 41cb93a386Sopenharmony_ci fLockedHandles.add(++fNextHandleId); 42cb93a386Sopenharmony_ci return fNextHandleId; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci bool lockHandle(SkDiscardableHandleId id) override { 45cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci if (id <= fLastDeletedHandleId) return false; 48cb93a386Sopenharmony_ci fLockedHandles.add(id); 49cb93a386Sopenharmony_ci return true; 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci // Client implementation. 53cb93a386Sopenharmony_ci bool deleteHandle(SkDiscardableHandleId id) override { 54cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci return id <= fLastDeletedHandleId; 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci void notifyCacheMiss(SkStrikeClient::CacheMissType type, int fontSize) override { 60cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci fCacheMissCount[type]++; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci bool isHandleDeleted(SkDiscardableHandleId id) override { 65cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci return id <= fLastDeletedHandleId; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci void unlockAll() { 71cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci fLockedHandles.reset(); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci void unlockAndDeleteAll() { 76cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci fLockedHandles.reset(); 79cb93a386Sopenharmony_ci fLastDeletedHandleId = fNextHandleId; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci const SkTHashSet<SkDiscardableHandleId>& lockedHandles() const { 82cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci return fLockedHandles; 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci SkDiscardableHandleId handleCount() { 87cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci return fNextHandleId; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci int cacheMissCount(uint32_t type) { 92cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci return fCacheMissCount[type]; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci bool hasCacheMiss() const { 97cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) { 100cb93a386Sopenharmony_ci if (fCacheMissCount[i] > 0) { return true; } 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci return false; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci void resetCacheMissCounts() { 105cb93a386Sopenharmony_ci SkAutoMutexExclusive l(fMutex); 106cb93a386Sopenharmony_ci sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount)); 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ciprivate: 110cb93a386Sopenharmony_ci // The tests below run in parallel on multiple threads and use the same 111cb93a386Sopenharmony_ci // process global SkStrikeCache. So the implementation needs to be 112cb93a386Sopenharmony_ci // thread-safe. 113cb93a386Sopenharmony_ci mutable SkMutex fMutex; 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci SkDiscardableHandleId fNextHandleId = 0u; 116cb93a386Sopenharmony_ci SkDiscardableHandleId fLastDeletedHandleId = 0u; 117cb93a386Sopenharmony_ci SkTHashSet<SkDiscardableHandleId> fLockedHandles; 118cb93a386Sopenharmony_ci int fCacheMissCount[SkStrikeClient::CacheMissType::kLast + 1u]; 119cb93a386Sopenharmony_ci}; 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_cisk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) { 122cb93a386Sopenharmony_ci SkFont font; 123cb93a386Sopenharmony_ci font.setTypeface(tf); 124cb93a386Sopenharmony_ci font.setHinting(SkFontHinting::kNormal); 125cb93a386Sopenharmony_ci font.setSize(1u); 126cb93a386Sopenharmony_ci font.setEdging(SkFont::Edging::kAntiAlias); 127cb93a386Sopenharmony_ci font.setSubpixel(true); 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci SkTextBlobBuilder builder; 130cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeWH(10, 10); 131cb93a386Sopenharmony_ci const auto& runBuffer = builder.allocRunPosH(font, glyphCount, 0, &bounds); 132cb93a386Sopenharmony_ci SkASSERT(runBuffer.utf8text == nullptr); 133cb93a386Sopenharmony_ci SkASSERT(runBuffer.clusters == nullptr); 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci for (int i = 0; i < glyphCount; i++) { 136cb93a386Sopenharmony_ci runBuffer.glyphs[i] = static_cast<SkGlyphID>(i); 137cb93a386Sopenharmony_ci runBuffer.pos[i] = SkIntToScalar(i); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci return builder.make(); 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cistatic void compare_blobs(const SkBitmap& expected, const SkBitmap& actual, 143cb93a386Sopenharmony_ci skiatest::Reporter* reporter, int tolerance = 0) { 144cb93a386Sopenharmony_ci SkASSERT(expected.width() == actual.width()); 145cb93a386Sopenharmony_ci SkASSERT(expected.height() == actual.height()); 146cb93a386Sopenharmony_ci for (int i = 0; i < expected.width(); ++i) { 147cb93a386Sopenharmony_ci for (int j = 0; j < expected.height(); ++j) { 148cb93a386Sopenharmony_ci SkColor expectedColor = expected.getColor(i, j); 149cb93a386Sopenharmony_ci SkColor actualColor = actual.getColor(i, j); 150cb93a386Sopenharmony_ci if (0 == tolerance) { 151cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedColor == actualColor); 152cb93a386Sopenharmony_ci } else { 153cb93a386Sopenharmony_ci for (int k = 0; k < 4; ++k) { 154cb93a386Sopenharmony_ci int expectedChannel = (expectedColor >> (k*8)) & 0xff; 155cb93a386Sopenharmony_ci int actualChannel = (actualColor >> (k*8)) & 0xff; 156cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, abs(expectedChannel - actualChannel) <= tolerance); 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_cisk_sp<SkSurface> MakeSurface(int width, int height, GrRecordingContext* rContext) { 164cb93a386Sopenharmony_ci const SkImageInfo info = 165cb93a386Sopenharmony_ci SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); 166cb93a386Sopenharmony_ci return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info); 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ciSkSurfaceProps FindSurfaceProps(GrRecordingContext* rContext) { 170cb93a386Sopenharmony_ci auto surface = MakeSurface(1, 1, rContext); 171cb93a386Sopenharmony_ci return surface->props(); 172cb93a386Sopenharmony_ci} 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ciSkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint, 175cb93a386Sopenharmony_ci GrRecordingContext* rContext, const SkMatrix* matrix = nullptr, 176cb93a386Sopenharmony_ci SkScalar x = 0) { 177cb93a386Sopenharmony_ci auto surface = MakeSurface(width, height, rContext); 178cb93a386Sopenharmony_ci if (matrix) surface->getCanvas()->concat(*matrix); 179cb93a386Sopenharmony_ci surface->getCanvas()->drawTextBlob(blob.get(), x, height/2, paint); 180cb93a386Sopenharmony_ci SkBitmap bitmap; 181cb93a386Sopenharmony_ci bitmap.allocN32Pixels(width, height); 182cb93a386Sopenharmony_ci surface->readPixels(bitmap, 0, 0); 183cb93a386Sopenharmony_ci return bitmap; 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_TypefaceSerialization, reporter) { 187cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 188cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 189cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci auto server_tf = SkTypeface::MakeDefault(); 192cb93a386Sopenharmony_ci auto tf_data = server.serializeTypeface(server_tf.get()); 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci auto client_tf = client.deserializeTypeface(tf_data->data(), tf_data->size()); 195cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, client_tf); 196cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, static_cast<SkTypefaceProxy*>(client_tf.get())->remoteTypefaceID() == 197cb93a386Sopenharmony_ci server_tf->uniqueID()); 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 200cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, reporter, ctxInfo) { 204cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 205cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 206cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 207cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 208cb93a386Sopenharmony_ci const SkPaint paint; 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci // Server. 211cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 212cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci int glyphCount = 10; 215cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 216cb93a386Sopenharmony_ci auto props = FindSurfaceProps(dContext); 217cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 218cb93a386Sopenharmony_ci 10, 10, props, nullptr, dContext->supportsDistanceFieldText()); 219cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 222cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci // Client. 225cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 226cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 227cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 228cb93a386Sopenharmony_ci auto clientBlob = buildTextBlob(clientTf, glyphCount); 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, dContext); 231cb93a386Sopenharmony_ci SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, dContext); 232cb93a386Sopenharmony_ci compare_blobs(expected, actual, reporter); 233cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 236cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 237cb93a386Sopenharmony_ci} 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_ReleaseTypeFace, reporter, ctxInfo) { 240cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 241cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 242cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_ci // Server. 245cb93a386Sopenharmony_ci auto serverTf = TestEmptyTypeface::Make(); 246cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 247cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, serverTf->unique()); 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_ci { 250cb93a386Sopenharmony_ci const SkPaint paint; 251cb93a386Sopenharmony_ci int glyphCount = 10; 252cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 253cb93a386Sopenharmony_ci const SkSurfaceProps props; 254cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 255cb93a386Sopenharmony_ci 10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText()); 256cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 257cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !serverTf->unique()); 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 260cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, serverTf->unique()); 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 265cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 266cb93a386Sopenharmony_ci} 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL 269cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) { 270cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 271cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 272cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 275cb93a386Sopenharmony_ci server.serializeTypeface(serverTf.get()); 276cb93a386Sopenharmony_ci int glyphCount = 10; 277cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 278cb93a386Sopenharmony_ci 279cb93a386Sopenharmony_ci const SkSurfaceProps props; 280cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = 281cb93a386Sopenharmony_ci server.makeAnalysisCanvas(10, 10, props, nullptr, true); 282cb93a386Sopenharmony_ci SkPaint paint; 283cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 284cb93a386Sopenharmony_ci 285cb93a386Sopenharmony_ci // The strike from the blob should be locked after it has been drawn on the canvas. 286cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); 287cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u); 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci // Write the strike data and unlock everything. Re-analyzing the blob should lock the handle 290cb93a386Sopenharmony_ci // again. 291cb93a386Sopenharmony_ci std::vector<uint8_t> fontData; 292cb93a386Sopenharmony_ci server.writeStrikeData(&fontData); 293cb93a386Sopenharmony_ci discardableManager->unlockAll(); 294cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 0u); 295cb93a386Sopenharmony_ci 296cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 297cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); 298cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u); 299cb93a386Sopenharmony_ci 300cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 301cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 302cb93a386Sopenharmony_ci} 303cb93a386Sopenharmony_ci#endif 304cb93a386Sopenharmony_ci 305cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL 306cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) { 307cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 308cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 309cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 310cb93a386Sopenharmony_ci 311cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 312cb93a386Sopenharmony_ci server.serializeTypeface(serverTf.get()); 313cb93a386Sopenharmony_ci int glyphCount = 10; 314cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ci const SkSurfaceProps props; 317cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = 318cb93a386Sopenharmony_ci server.makeAnalysisCanvas(10, 10, props, nullptr, true); 319cb93a386Sopenharmony_ci SkPaint paint; 320cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 321cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci // Write the strike data and delete all the handles. Re-analyzing the blob should create new 324cb93a386Sopenharmony_ci // handles. 325cb93a386Sopenharmony_ci std::vector<uint8_t> fontData; 326cb93a386Sopenharmony_ci server.writeStrikeData(&fontData); 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ci // Another analysis pass, to ensure that deleting handles after a complete cache hit still 329cb93a386Sopenharmony_ci // works. This is a regression test for crbug.com/999682. 330cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 331cb93a386Sopenharmony_ci server.writeStrikeData(&fontData); 332cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 335cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 336cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->handleCount() == 2u); 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 339cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 340cb93a386Sopenharmony_ci} 341cb93a386Sopenharmony_ci#endif 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL 344cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) { 345cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 346cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 347cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ci // Server. 350cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 351cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 352cb93a386Sopenharmony_ci 353cb93a386Sopenharmony_ci int glyphCount = 10; 354cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci const SkSurfaceProps props; 357cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = 358cb93a386Sopenharmony_ci server.makeAnalysisCanvas(10, 10, props, nullptr, true); 359cb93a386Sopenharmony_ci SkPaint paint; 360cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 363cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 364cb93a386Sopenharmony_ci 365cb93a386Sopenharmony_ci // Client. 366cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 367cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 368cb93a386Sopenharmony_ci auto* clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()).get(); 369cb93a386Sopenharmony_ci 370cb93a386Sopenharmony_ci // The cache remains alive until it is pinned in the discardable manager. 371cb93a386Sopenharmony_ci SkGraphics::PurgeFontCache(); 372cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !clientTf->unique()); 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_ci // Once the strike is unpinned and purged, SkStrikeClient should be the only owner of the 375cb93a386Sopenharmony_ci // clientTf. 376cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 377cb93a386Sopenharmony_ci SkGraphics::PurgeFontCache(); 378cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, clientTf->unique()); 379cb93a386Sopenharmony_ci 380cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 381cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 382cb93a386Sopenharmony_ci} 383cb93a386Sopenharmony_ci#endif 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL 386cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) { 387cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 388cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 389cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_ci // Server. 392cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 393cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci int glyphCount = 10; 396cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 397cb93a386Sopenharmony_ci 398cb93a386Sopenharmony_ci const SkSurfaceProps props; 399cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = 400cb93a386Sopenharmony_ci server.makeAnalysisCanvas(10, 10, props, nullptr, true); 401cb93a386Sopenharmony_ci SkPaint paint; 402cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 405cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_ci // Client. 408cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 409cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 412cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 413cb93a386Sopenharmony_ci} 414cb93a386Sopenharmony_ci#endif 415cb93a386Sopenharmony_ci 416cb93a386Sopenharmony_ciDEF_TEST(SkRemoteGlyphCache_PurgesServerEntries, reporter) { 417cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 418cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 419cb93a386Sopenharmony_ci server.setMaxEntriesInDescriptorMapForTesting(1u); 420cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci { 423cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 424cb93a386Sopenharmony_ci int glyphCount = 10; 425cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 426cb93a386Sopenharmony_ci 427cb93a386Sopenharmony_ci const SkSurfaceProps props; 428cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = 429cb93a386Sopenharmony_ci server.makeAnalysisCanvas(10, 10, props, nullptr, true); 430cb93a386Sopenharmony_ci SkPaint paint; 431cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 0u); 432cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 433cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u); 434cb93a386Sopenharmony_ci } 435cb93a386Sopenharmony_ci 436cb93a386Sopenharmony_ci // Serialize to release the lock from the strike server and delete all current 437cb93a386Sopenharmony_ci // handles. 438cb93a386Sopenharmony_ci std::vector<uint8_t> fontData; 439cb93a386Sopenharmony_ci server.writeStrikeData(&fontData); 440cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_ci // Use a different typeface. Creating a new strike should evict the previous 443cb93a386Sopenharmony_ci // one. 444cb93a386Sopenharmony_ci { 445cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("Georgia", SkFontStyle()); 446cb93a386Sopenharmony_ci int glyphCount = 10; 447cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_ci const SkSurfaceProps props; 450cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = 451cb93a386Sopenharmony_ci server.makeAnalysisCanvas(10, 10, props, nullptr, true); 452cb93a386Sopenharmony_ci SkPaint paint; 453cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u); 454cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 455cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u); 456cb93a386Sopenharmony_ci } 457cb93a386Sopenharmony_ci 458cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 459cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 460cb93a386Sopenharmony_ci} 461cb93a386Sopenharmony_ci 462cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter, ctxInfo) { 463cb93a386Sopenharmony_ci auto direct = ctxInfo.directContext(); 464cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 465cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 466cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 467cb93a386Sopenharmony_ci SkPaint paint; 468cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 469cb93a386Sopenharmony_ci paint.setStrokeWidth(0); 470cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 471cb93a386Sopenharmony_ci SkStrikeSpec::ShouldDrawAsPath(paint, SkFont(), SkMatrix::I())); 472cb93a386Sopenharmony_ci 473cb93a386Sopenharmony_ci // Server. 474cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 475cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ci int glyphCount = 10; 478cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 479cb93a386Sopenharmony_ci auto props = FindSurfaceProps(direct); 480cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 481cb93a386Sopenharmony_ci 10, 10, props, nullptr, direct->supportsDistanceFieldText()); 482cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 483cb93a386Sopenharmony_ci 484cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 485cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 486cb93a386Sopenharmony_ci 487cb93a386Sopenharmony_ci // Client. 488cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 489cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 490cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 491cb93a386Sopenharmony_ci auto clientBlob = buildTextBlob(clientTf, glyphCount); 492cb93a386Sopenharmony_ci 493cb93a386Sopenharmony_ci SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct); 494cb93a386Sopenharmony_ci SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct); 495cb93a386Sopenharmony_ci compare_blobs(expected, actual, reporter, 1); 496cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 497cb93a386Sopenharmony_ci 498cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 499cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 500cb93a386Sopenharmony_ci} 501cb93a386Sopenharmony_ci 502cb93a386Sopenharmony_cisk_sp<SkTextBlob> make_blob_causing_fallback( 503cb93a386Sopenharmony_ci sk_sp<SkTypeface> targetTf, const SkTypeface* glyphTf, skiatest::Reporter* reporter) { 504cb93a386Sopenharmony_ci SkFont font; 505cb93a386Sopenharmony_ci font.setSubpixel(true); 506cb93a386Sopenharmony_ci font.setSize(96); 507cb93a386Sopenharmony_ci font.setHinting(SkFontHinting::kNormal); 508cb93a386Sopenharmony_ci font.setTypeface(targetTf); 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 511cb93a386Sopenharmony_ci !SkStrikeSpec::ShouldDrawAsPath(SkPaint(), font, SkMatrix::I())); 512cb93a386Sopenharmony_ci 513cb93a386Sopenharmony_ci char s[] = "Skia"; 514cb93a386Sopenharmony_ci int runSize = strlen(s); 515cb93a386Sopenharmony_ci 516cb93a386Sopenharmony_ci SkTextBlobBuilder builder; 517cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeIWH(100, 100); 518cb93a386Sopenharmony_ci const auto& runBuffer = builder.allocRunPosH(font, runSize, 10, &bounds); 519cb93a386Sopenharmony_ci SkASSERT(runBuffer.utf8text == nullptr); 520cb93a386Sopenharmony_ci SkASSERT(runBuffer.clusters == nullptr); 521cb93a386Sopenharmony_ci 522cb93a386Sopenharmony_ci SkFont(sk_ref_sp(glyphTf)).textToGlyphs(s, strlen(s), SkTextEncoding::kUTF8, 523cb93a386Sopenharmony_ci runBuffer.glyphs, runSize); 524cb93a386Sopenharmony_ci 525cb93a386Sopenharmony_ci SkRect glyphBounds; 526cb93a386Sopenharmony_ci font.getWidths(runBuffer.glyphs, 1, nullptr, &glyphBounds); 527cb93a386Sopenharmony_ci 528cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, glyphBounds.width() > SkStrikeCommon::kSkSideTooBigForAtlas); 529cb93a386Sopenharmony_ci 530cb93a386Sopenharmony_ci for (int i = 0; i < runSize; i++) { 531cb93a386Sopenharmony_ci runBuffer.pos[i] = i * 10; 532cb93a386Sopenharmony_ci } 533cb93a386Sopenharmony_ci 534cb93a386Sopenharmony_ci return builder.make(); 535cb93a386Sopenharmony_ci} 536cb93a386Sopenharmony_ci 537cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsMaskWithPathFallback, 538cb93a386Sopenharmony_ci reporter, ctxInfo) { 539cb93a386Sopenharmony_ci auto direct = ctxInfo.directContext(); 540cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 541cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 542cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 543cb93a386Sopenharmony_ci 544cb93a386Sopenharmony_ci SkPaint paint; 545cb93a386Sopenharmony_ci 546cb93a386Sopenharmony_ci auto serverTf = MakeResourceAsTypeface("fonts/HangingS.ttf"); 547cb93a386Sopenharmony_ci // TODO: when the cq bots can handle this font remove the check. 548cb93a386Sopenharmony_ci if (serverTf == nullptr) { 549cb93a386Sopenharmony_ci return; 550cb93a386Sopenharmony_ci } 551cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci auto serverBlob = make_blob_causing_fallback(serverTf, serverTf.get(), reporter); 554cb93a386Sopenharmony_ci 555cb93a386Sopenharmony_ci auto props = FindSurfaceProps(direct); 556cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 557cb93a386Sopenharmony_ci 10, 10, props, nullptr, direct->supportsDistanceFieldText()); 558cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 559cb93a386Sopenharmony_ci 560cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 561cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 562cb93a386Sopenharmony_ci 563cb93a386Sopenharmony_ci // Client. 564cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 565cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 566cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 567cb93a386Sopenharmony_ci 568cb93a386Sopenharmony_ci auto clientBlob = make_blob_causing_fallback(clientTf, serverTf.get(), reporter); 569cb93a386Sopenharmony_ci 570cb93a386Sopenharmony_ci SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct); 571cb93a386Sopenharmony_ci SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct); 572cb93a386Sopenharmony_ci compare_blobs(expected, actual, reporter); 573cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 574cb93a386Sopenharmony_ci 575cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 576cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 577cb93a386Sopenharmony_ci} 578cb93a386Sopenharmony_ci 579cb93a386Sopenharmony_ci#if 0 580cb93a386Sopenharmony_ci// TODO: turn this one when I figure out how to deal with the pixel variance from linear 581cb93a386Sopenharmony_ci// interpolation from GPU to GPU. 582cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsSDFTWithAllARGBFallback, 583cb93a386Sopenharmony_ci reporter, ctxInfo) { 584cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 585cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 586cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 587cb93a386Sopenharmony_ci 588cb93a386Sopenharmony_ci SkPaint paint; 589cb93a386Sopenharmony_ci 590cb93a386Sopenharmony_ci auto serverTf = ToolUtils::planet_typeface(); 591cb93a386Sopenharmony_ci // TODO: when the cq bots can handle this font remove the check. 592cb93a386Sopenharmony_ci if (serverTf == nullptr) { 593cb93a386Sopenharmony_ci return; 594cb93a386Sopenharmony_ci } 595cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 596cb93a386Sopenharmony_ci 597cb93a386Sopenharmony_ci auto makeBlob = [&reporter](sk_sp<SkTypeface> typeface) { 598cb93a386Sopenharmony_ci SkFont font; 599cb93a386Sopenharmony_ci font.setSubpixel(true); 600cb93a386Sopenharmony_ci font.setSize(96); 601cb93a386Sopenharmony_ci font.setHinting(SkFontHinting::kNormal); 602cb93a386Sopenharmony_ci font.setTypeface(typeface); 603cb93a386Sopenharmony_ci 604cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkDraw::ShouldDrawTextAsPaths(font, SkPaint(), SkMatrix::I())); 605cb93a386Sopenharmony_ci 606cb93a386Sopenharmony_ci // Mercury to Uranus. 607cb93a386Sopenharmony_ci SkGlyphID glyphs[] = {1, 2, 3, 4, 5, 6, 7, 8}; 608cb93a386Sopenharmony_ci 609cb93a386Sopenharmony_ci SkTextBlobBuilder builder; 610cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeIWH(100, 100); 611cb93a386Sopenharmony_ci const auto& runBuffer = builder.allocRunPosH(font, SK_ARRAY_COUNT(glyphs), 100, &bounds); 612cb93a386Sopenharmony_ci SkASSERT(runBuffer.utf8text == nullptr); 613cb93a386Sopenharmony_ci SkASSERT(runBuffer.clusters == nullptr); 614cb93a386Sopenharmony_ci 615cb93a386Sopenharmony_ci std::copy(std::begin(glyphs), std::end(glyphs), runBuffer.glyphs); 616cb93a386Sopenharmony_ci 617cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(glyphs); i++) { 618cb93a386Sopenharmony_ci runBuffer.pos[i] = i * 100; 619cb93a386Sopenharmony_ci } 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_ci return builder.make(); 622cb93a386Sopenharmony_ci }; 623cb93a386Sopenharmony_ci 624cb93a386Sopenharmony_ci auto serverBlob = makeBlob(serverTf); 625cb93a386Sopenharmony_ci 626cb93a386Sopenharmony_ci auto props = FindSurfaceProps(ctxInfo.grContext()); 627cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 628cb93a386Sopenharmony_ci 10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText()); 629cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 400, paint); 630cb93a386Sopenharmony_ci 631cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 632cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 633cb93a386Sopenharmony_ci 634cb93a386Sopenharmony_ci // Client. 635cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 636cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 637cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_ci auto clientBlob = makeBlob(clientTf); 640cb93a386Sopenharmony_ci 641cb93a386Sopenharmony_ci SkBitmap expected = RasterBlob(serverBlob, 800, 800, paint, ctxInfo.grContext()); 642cb93a386Sopenharmony_ci SkBitmap actual = RasterBlob(clientBlob, 800, 800, paint, ctxInfo.grContext()); 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_ci // Pixel variance can be high because of the atlas placement, and large scaling in the linear 645cb93a386Sopenharmony_ci // interpolation. 646cb93a386Sopenharmony_ci compare_blobs(expected, actual, reporter, 36); 647cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 650cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 651cb93a386Sopenharmony_ci} 652cb93a386Sopenharmony_ci#endif 653cb93a386Sopenharmony_ci 654cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY, reporter, ctxInfo) { 655cb93a386Sopenharmony_ci auto direct = ctxInfo.directContext(); 656cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 657cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 658cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 659cb93a386Sopenharmony_ci SkPaint paint; 660cb93a386Sopenharmony_ci paint.setAntiAlias(true); 661cb93a386Sopenharmony_ci 662cb93a386Sopenharmony_ci // Server. 663cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 664cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 665cb93a386Sopenharmony_ci 666cb93a386Sopenharmony_ci int glyphCount = 10; 667cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 668cb93a386Sopenharmony_ci auto props = FindSurfaceProps(direct); 669cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 670cb93a386Sopenharmony_ci 10, 10, props, nullptr, direct->supportsDistanceFieldText()); 671cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0.5, 0, paint); 672cb93a386Sopenharmony_ci 673cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 674cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 675cb93a386Sopenharmony_ci 676cb93a386Sopenharmony_ci // Client. 677cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 678cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 679cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 680cb93a386Sopenharmony_ci auto clientBlob = buildTextBlob(clientTf, glyphCount); 681cb93a386Sopenharmony_ci 682cb93a386Sopenharmony_ci SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, nullptr, 0.5); 683cb93a386Sopenharmony_ci SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, nullptr, 0.5); 684cb93a386Sopenharmony_ci compare_blobs(expected, actual, reporter); 685cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 688cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 689cb93a386Sopenharmony_ci} 690cb93a386Sopenharmony_ci 691cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, ctxInfo) { 692cb93a386Sopenharmony_ci auto direct = ctxInfo.directContext(); 693cb93a386Sopenharmony_ci if (!direct->priv().caps()->shaderCaps()->supportsDistanceFieldText()) { 694cb93a386Sopenharmony_ci return; 695cb93a386Sopenharmony_ci } 696cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 697cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 698cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 699cb93a386Sopenharmony_ci SkPaint paint; 700cb93a386Sopenharmony_ci SkFont font; 701cb93a386Sopenharmony_ci 702cb93a386Sopenharmony_ci // A scale transform forces fallback to dft. 703cb93a386Sopenharmony_ci SkMatrix matrix = SkMatrix::Scale(16, 16); 704cb93a386Sopenharmony_ci GrSDFTControl control = direct->priv().asRecordingContext()->priv().getSDFTControl(true); 705cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, control.drawingType(font, paint, matrix) == GrSDFTControl::kSDFT); 706cb93a386Sopenharmony_ci 707cb93a386Sopenharmony_ci // Server. 708cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 709cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 710cb93a386Sopenharmony_ci 711cb93a386Sopenharmony_ci int glyphCount = 10; 712cb93a386Sopenharmony_ci auto serverBlob = buildTextBlob(serverTf, glyphCount); 713cb93a386Sopenharmony_ci const SkSurfaceProps props; 714cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 715cb93a386Sopenharmony_ci 10, 10, props, nullptr, direct->supportsDistanceFieldText()); 716cb93a386Sopenharmony_ci cache_diff_canvas->concat(matrix); 717cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint); 718cb93a386Sopenharmony_ci 719cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 720cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 721cb93a386Sopenharmony_ci 722cb93a386Sopenharmony_ci // Client. 723cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 724cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 725cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); 726cb93a386Sopenharmony_ci auto clientBlob = buildTextBlob(clientTf, glyphCount); 727cb93a386Sopenharmony_ci 728cb93a386Sopenharmony_ci SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, &matrix); 729cb93a386Sopenharmony_ci SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, &matrix); 730cb93a386Sopenharmony_ci compare_blobs(expected, actual, reporter); 731cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 732cb93a386Sopenharmony_ci 733cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 734cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 735cb93a386Sopenharmony_ci} 736cb93a386Sopenharmony_ci 737cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_CacheMissReporting, reporter, ctxInfo) { 738cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 739cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 740cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 741cb93a386Sopenharmony_ci 742cb93a386Sopenharmony_ci auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); 743cb93a386Sopenharmony_ci auto tfData = server.serializeTypeface(serverTf.get()); 744cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(tfData->data(), tfData->size()); 745cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, clientTf); 746cb93a386Sopenharmony_ci int glyphCount = 10; 747cb93a386Sopenharmony_ci auto clientBlob = buildTextBlob(clientTf, glyphCount); 748cb93a386Sopenharmony_ci 749cb93a386Sopenharmony_ci // Raster the client-side blob without the glyph data, we should get cache miss notifications. 750cb93a386Sopenharmony_ci SkPaint paint; 751cb93a386Sopenharmony_ci SkMatrix matrix = SkMatrix::I(); 752cb93a386Sopenharmony_ci RasterBlob(clientBlob, 10, 10, paint, ctxInfo.directContext(), &matrix); 753cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 754cb93a386Sopenharmony_ci discardableManager->cacheMissCount(SkStrikeClient::kFontMetrics) == 1); 755cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 756cb93a386Sopenharmony_ci discardableManager->cacheMissCount(SkStrikeClient::kGlyphMetrics) == 10); 757cb93a386Sopenharmony_ci 758cb93a386Sopenharmony_ci // There shouldn't be any image or path requests, since we mark the glyph as empty on a cache 759cb93a386Sopenharmony_ci // miss. 760cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphImage) == 0); 761cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphPath) == 0); 762cb93a386Sopenharmony_ci 763cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 764cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 765cb93a386Sopenharmony_ci} 766cb93a386Sopenharmony_ci 767cb93a386Sopenharmony_cisk_sp<SkTextBlob> MakeEmojiBlob(sk_sp<SkTypeface> serverTf, SkScalar textSize, 768cb93a386Sopenharmony_ci sk_sp<SkTypeface> clientTf = nullptr) { 769cb93a386Sopenharmony_ci SkFont font; 770cb93a386Sopenharmony_ci font.setTypeface(serverTf); 771cb93a386Sopenharmony_ci font.setSize(textSize); 772cb93a386Sopenharmony_ci 773cb93a386Sopenharmony_ci const char* text = ToolUtils::emoji_sample_text(); 774cb93a386Sopenharmony_ci SkFont serverFont = font; 775cb93a386Sopenharmony_ci auto blob = SkTextBlob::MakeFromText(text, strlen(text), font); 776cb93a386Sopenharmony_ci if (clientTf == nullptr) return blob; 777cb93a386Sopenharmony_ci 778cb93a386Sopenharmony_ci SkSerialProcs s_procs; 779cb93a386Sopenharmony_ci s_procs.fTypefaceProc = [](SkTypeface*, void* ctx) -> sk_sp<SkData> { 780cb93a386Sopenharmony_ci return SkData::MakeUninitialized(1u); 781cb93a386Sopenharmony_ci }; 782cb93a386Sopenharmony_ci auto serialized = blob->serialize(s_procs); 783cb93a386Sopenharmony_ci 784cb93a386Sopenharmony_ci SkDeserialProcs d_procs; 785cb93a386Sopenharmony_ci d_procs.fTypefaceCtx = &clientTf; 786cb93a386Sopenharmony_ci d_procs.fTypefaceProc = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> { 787cb93a386Sopenharmony_ci return *(static_cast<sk_sp<SkTypeface>*>(ctx)); 788cb93a386Sopenharmony_ci }; 789cb93a386Sopenharmony_ci return SkTextBlob::Deserialize(serialized->data(), serialized->size(), d_procs); 790cb93a386Sopenharmony_ci} 791cb93a386Sopenharmony_ci 792cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithNoPaths, reporter, ctxInfo) { 793cb93a386Sopenharmony_ci auto direct = ctxInfo.directContext(); 794cb93a386Sopenharmony_ci sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); 795cb93a386Sopenharmony_ci SkStrikeServer server(discardableManager.get()); 796cb93a386Sopenharmony_ci SkStrikeClient client(discardableManager, false); 797cb93a386Sopenharmony_ci 798cb93a386Sopenharmony_ci auto serverTf = ToolUtils::emoji_typeface(); 799cb93a386Sopenharmony_ci auto serverTfData = server.serializeTypeface(serverTf.get()); 800cb93a386Sopenharmony_ci auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); 801cb93a386Sopenharmony_ci 802cb93a386Sopenharmony_ci auto props = FindSurfaceProps(direct); 803cb93a386Sopenharmony_ci std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas( 804cb93a386Sopenharmony_ci 500, 500, props, nullptr, direct->supportsDistanceFieldText()); 805cb93a386Sopenharmony_ci for (SkScalar textSize : { 70, 180, 270, 340}) { 806cb93a386Sopenharmony_ci auto serverBlob = MakeEmojiBlob(serverTf, textSize); 807cb93a386Sopenharmony_ci 808cb93a386Sopenharmony_ci SkPaint paint; 809cb93a386Sopenharmony_ci cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint); 810cb93a386Sopenharmony_ci 811cb93a386Sopenharmony_ci std::vector<uint8_t> serverStrikeData; 812cb93a386Sopenharmony_ci server.writeStrikeData(&serverStrikeData); 813cb93a386Sopenharmony_ci if (!serverStrikeData.empty()) { 814cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 815cb93a386Sopenharmony_ci client.readStrikeData(serverStrikeData.data(), 816cb93a386Sopenharmony_ci serverStrikeData.size())); 817cb93a386Sopenharmony_ci } 818cb93a386Sopenharmony_ci auto clientBlob = MakeEmojiBlob(serverTf, textSize, clientTf); 819cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, clientBlob); 820cb93a386Sopenharmony_ci 821cb93a386Sopenharmony_ci RasterBlob(clientBlob, 500, 500, paint, direct); 822cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss()); 823cb93a386Sopenharmony_ci discardableManager->resetCacheMissCounts(); 824cb93a386Sopenharmony_ci } 825cb93a386Sopenharmony_ci 826cb93a386Sopenharmony_ci // Must unlock everything on termination, otherwise valgrind complains about memory leaks. 827cb93a386Sopenharmony_ci discardableManager->unlockAndDeleteAll(); 828cb93a386Sopenharmony_ci} 829