aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/SkRemoteGlyphCacheTest.cpp
diff options
context:
space:
mode:
authorGravatar Khushal <khushalsagar@chromium.org>2018-05-02 10:29:37 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-02 18:39:31 +0000
commit38a08436886e82de4eb9ebdbcb2bbd5ea7b05c6d (patch)
tree3477528878c8d4b0a053fbc807efd02e60fcde14 /tests/SkRemoteGlyphCacheTest.cpp
parent81afc04b5368fc4a7cb6ae4b4d7069e67a3a51f8 (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.cpp223
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());
+}