diff options
author | Khushal <khushalsagar@chromium.org> | 2018-05-02 10:29:37 -0700 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-02 18:39:31 +0000 |
commit | 38a08436886e82de4eb9ebdbcb2bbd5ea7b05c6d (patch) | |
tree | 3477528878c8d4b0a053fbc807efd02e60fcde14 /tests/SkRemoteGlyphCacheTest.cpp | |
parent | 81afc04b5368fc4a7cb6ae4b4d7069e67a3a51f8 (diff) |
fonts: Reland push font remoting.
This relands the following changes:
1) https://skia-review.googlesource.com/c/skia/+/120283
2) https://skia-review.googlesource.com/c/skia/+/125029
3) https://skia-review.googlesource.com/c/skia/+/125140
The original changes had to be reverted due to a memory leak in
SkBaseDevice from SkTextBlobCacheDiffCanvas. This has been addressed by
https://skia-review.googlesource.com/c/skia/+/125160
TBR=herb@google.com
Bug: skia:7515, 831354
Change-Id: I73f4fcb1c397f31bf01553ff48c71ed2d6dd0770
Reviewed-on: https://skia-review.googlesource.com/125326
Commit-Queue: Khusal Sagar <khushalsagar@chromium.org>
Reviewed-by: Khusal Sagar <khushalsagar@chromium.org>
Diffstat (limited to 'tests/SkRemoteGlyphCacheTest.cpp')
-rw-r--r-- | tests/SkRemoteGlyphCacheTest.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp new file mode 100644 index 0000000000..64739de8d3 --- /dev/null +++ b/tests/SkRemoteGlyphCacheTest.cpp @@ -0,0 +1,223 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkGraphics.h" +#include "SkMutex.h" +#include "SkRemoteGlyphCache.h" +#include "SkStrikeCache.h" +#include "SkSurface.h" +#include "SkTextBlob.h" +#include "SkTypeface_remote.h" +#include "Test.h" + +class DiscardableManager : public SkStrikeServer::DiscardableHandleManager, + public SkStrikeClient::DiscardableHandleManager { +public: + DiscardableManager() = default; + ~DiscardableManager() override = default; + + // Server implementation. + SkDiscardableHandleId createHandle() override { + // Handles starts as locked. + fLockedHandles.add(++fNextHandleId); + return fNextHandleId; + } + bool lockHandle(SkDiscardableHandleId id) override { + if (id <= fLastDeletedHandleId) return false; + fLockedHandles.add(id); + return true; + } + + // Client implementation. + bool deleteHandle(SkDiscardableHandleId id) override { return id <= fLastDeletedHandleId; } + + void unlockAll() { fLockedHandles.reset(); } + void unlockAndDeleteAll() { + unlockAll(); + fLastDeletedHandleId = fNextHandleId; + } + const SkTHashSet<SkDiscardableHandleId>& lockedHandles() const { return fLockedHandles; } + SkDiscardableHandleId handleCount() { return fNextHandleId; } + +private: + SkDiscardableHandleId fNextHandleId = 0u; + SkDiscardableHandleId fLastDeletedHandleId = 0u; + SkTHashSet<SkDiscardableHandleId> fLockedHandles; +}; + +sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) { + SkPaint font; + font.setTypeface(tf); + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + font.setTextAlign(SkPaint::kLeft_Align); + font.setStyle(SkPaint::kFill_Style); + font.setHinting(SkPaint::kNormal_Hinting); + font.setTextSize(1u); + + SkTextBlobBuilder builder; + SkRect bounds = SkRect::MakeWH(10, 10); + const auto& runBuffer = builder.allocRunPosH(font, glyphCount, 0, &bounds); + SkASSERT(runBuffer.utf8text == nullptr); + SkASSERT(runBuffer.clusters == nullptr); + + for (int i = 0; i < glyphCount; i++) { + runBuffer.glyphs[i] = static_cast<SkGlyphID>(i); + runBuffer.pos[i] = SkIntToScalar(i); + } + return builder.make(); +} + +SkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height) { + auto surface = SkSurface::MakeRasterN32Premul(width, height); + SkPaint paint; + surface->getCanvas()->drawTextBlob(blob.get(), 0u, 0u, paint); + SkBitmap bitmap; + bitmap.allocN32Pixels(width, height); + surface->readPixels(bitmap, 0, 0); + return bitmap; +} + +DEF_TEST(SkRemoteGlyphCache_TypefaceSerialization, reporter) { + sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); + SkStrikeServer server(discardableManager.get()); + SkStrikeClient client(discardableManager); + + auto server_tf = SkTypeface::MakeDefault(); + auto tf_data = server.serializeTypeface(server_tf.get()); + + auto client_tf = client.deserializeTypeface(tf_data->data(), tf_data->size()); + REPORTER_ASSERT(reporter, client_tf); + REPORTER_ASSERT(reporter, SkTypefaceProxy::DownCast(client_tf.get())->remoteTypefaceID() == + server_tf->uniqueID()); +} + +DEF_TEST(SkRemoteGlyphCache_StrikeSerialization, reporter) { + sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); + SkStrikeServer server(discardableManager.get()); + SkStrikeClient client(discardableManager); + + // Server. + auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); + auto serverTfData = server.serializeTypeface(serverTf.get()); + + int glyphCount = 10; + auto serverBlob = buildTextBlob(serverTf, glyphCount); + const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server); + SkPaint paint; + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + + std::vector<uint8_t> serverStrikeData; + server.writeStrikeData(&serverStrikeData); + + // Client. + auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); + REPORTER_ASSERT(reporter, + client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); + auto clientBlob = buildTextBlob(clientTf, glyphCount); + + SkBitmap expected = RasterBlob(serverBlob, 10, 10); + SkBitmap actual = RasterBlob(clientBlob, 10, 10); + for (int i = 0; i < expected.width(); ++i) { + for (int j = 0; j < expected.height(); ++j) { + REPORTER_ASSERT(reporter, expected.getColor(i, j) == actual.getColor(i, j)); + } + } +} + +DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) { + sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); + SkStrikeServer server(discardableManager.get()); + SkStrikeClient client(discardableManager); + + auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); + server.serializeTypeface(serverTf.get()); + int glyphCount = 10; + auto serverBlob = buildTextBlob(serverTf, glyphCount); + + const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server); + SkPaint paint; + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + + // The strike from the blob should be locked after it has been drawn on the canvas. + REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); + REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u); + + // Write the strike data and unlock everything. Re-analyzing the blob should lock the handle + // again. + std::vector<uint8_t> fontData; + server.writeStrikeData(&fontData); + discardableManager->unlockAll(); + REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 0u); + + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); + REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u); +} + +DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) { + sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); + SkStrikeServer server(discardableManager.get()); + SkStrikeClient client(discardableManager); + + auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); + server.serializeTypeface(serverTf.get()); + int glyphCount = 10; + auto serverBlob = buildTextBlob(serverTf, glyphCount); + + const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server); + SkPaint paint; + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); + + // Write the strike data and delete all the handles. Re-analyzing the blob should create new + // handles. + std::vector<uint8_t> fontData; + server.writeStrikeData(&fontData); + discardableManager->unlockAndDeleteAll(); + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + printf("HandleCount: %d\n ", discardableManager->handleCount()); + REPORTER_ASSERT(reporter, discardableManager->handleCount() == 2u); +} + +DEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) { + sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); + SkStrikeServer server(discardableManager.get()); + SkStrikeClient client(discardableManager); + + // Server. + auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); + auto serverTfData = server.serializeTypeface(serverTf.get()); + + int glyphCount = 10; + auto serverBlob = buildTextBlob(serverTf, glyphCount); + + const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server); + SkPaint paint; + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + + std::vector<uint8_t> serverStrikeData; + server.writeStrikeData(&serverStrikeData); + + // Client. + REPORTER_ASSERT(reporter, + client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); + auto* clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()).get(); + + // The cache remains alive until it is pinned in the discardable manager. + SkGraphics::PurgeFontCache(); + REPORTER_ASSERT(reporter, !clientTf->unique()); + + // Once the strike is unpinned and purged, SkStrikeClient should be the only owner of the + // clientTf. + discardableManager->unlockAndDeleteAll(); + SkGraphics::PurgeFontCache(); + REPORTER_ASSERT(reporter, clientTf->unique()); +} |