aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/remote_demo.cpp
diff options
context:
space:
mode:
authorGravatar Khushal <khushalsagar@chromium.org>2018-05-01 10:49:04 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-01 18:15:15 +0000
commit101d56359a5a5dc3b8a2a4149ac171e25eb0bec0 (patch)
tree926066f75a16d8c56da1ab3c3fe4701ce170ebb2 /tools/remote_demo.cpp
parente618eee83350902a06bba9c5b358b6c4c11e836c (diff)
fonts: Set up remote glyph caching to push fonts.
Currently the SkStrikeClient is designed to pull fonts from the server on demand, and to pre-fetch a batched request by analyzing the ops using a SkTextBlobCacheDiffCanvas. This change modifies the design to support a push based model, where the server pushes fonts required by the client and sets up the requisite SkGlyphCaches on the client prior to rasterizing the ops. This model still relies on the SkTextBlobCacheDiffCanvas for analyzing the glyphs required for rasterizing an op. The glyph caches required for raster are locked and missing glyphs to be sent to the client are tracked by the SkStrikeServer. The embedder can serialize this font data at any point, but must ensure that this data is deserialized by the SkStrikeClient at the remote end, before rasterizing any ops analyzed prior to serialization. Any refs on the caches are released once the font data is serialized by the server. The locking of glyph caches relies on the embedder providing discardable handles. These handles can be created on the server and serialized to be sent to the client, and map to an instance of SkGlyphCache. This allows the server to control the lifetime of the caches on the client. Bug: skia:7515 Change-Id: Id39f346b47b60899778404bbd0429ee811d0e53b Reviewed-on: https://skia-review.googlesource.com/120283 Commit-Queue: Khusal Sagar <khushalsagar@chromium.org> Reviewed-by: Herb Derby <herb@google.com>
Diffstat (limited to 'tools/remote_demo.cpp')
-rw-r--r--tools/remote_demo.cpp130
1 files changed, 89 insertions, 41 deletions
diff --git a/tools/remote_demo.cpp b/tools/remote_demo.cpp
index 8fc96cadb8..105a9b3ea7 100644
--- a/tools/remote_demo.cpp
+++ b/tools/remote_demo.cpp
@@ -16,8 +16,9 @@
#include <thread>
#include <unistd.h>
-#include "SkRemoteGlyphCache.h"
#include "SkGraphics.h"
+#include "SkRemoteGlyphCache.h"
+#include "SkScalerContext.h"
#include "SkSurface.h"
static std::string gSkpName;
@@ -25,6 +26,46 @@ static bool gUseGpu = true;
static bool gPurgeFontCaches = true;
static bool gUseProcess = true;
+class ServerDiscardableManager : public SkStrikeServer::DiscardableHandleManager {
+public:
+ ServerDiscardableManager() = default;
+ ~ServerDiscardableManager() override = default;
+
+ SkDiscardableHandleId createHandle() override { return ++nextHandleId; }
+ bool lockHandle(SkDiscardableHandleId handleId) override {
+ return handleId > lastPurgedHandleId;
+ }
+ void purgeAll() { lastPurgedHandleId = nextHandleId; }
+
+private:
+ SkDiscardableHandleId nextHandleId = 0u;
+ SkDiscardableHandleId lastPurgedHandleId = 0u;
+};
+
+class ClientDiscardableManager : public SkStrikeClient::DiscardableHandleManager {
+public:
+ class ScopedPurgeCache {
+ public:
+ ScopedPurgeCache(ClientDiscardableManager* manager) : fManager(manager) {
+ if (fManager) fManager->allowPurging = true;
+ }
+ ~ScopedPurgeCache() {
+ if (fManager) fManager->allowPurging = false;
+ }
+
+ private:
+ ClientDiscardableManager* fManager;
+ };
+
+ ClientDiscardableManager() = default;
+ ~ClientDiscardableManager() override = default;
+
+ bool deleteHandle(SkDiscardableHandleId) override { return allowPurging; }
+
+private:
+ bool allowPurging = false;
+};
+
static bool write_SkData(int fd, const SkData& data) {
size_t size = data.size();
ssize_t bytesWritten = ::write(fd, &size, sizeof(size));
@@ -43,7 +84,6 @@ static bool write_SkData(int fd, const SkData& data) {
}
static sk_sp<SkData> read_SkData(int fd) {
-
size_t size;
ssize_t readSize = ::read(fd, &size, sizeof(size));
if (readSize <= 0) {
@@ -92,44 +132,56 @@ private:
std::chrono::duration<double> fElapsedSeconds{0.0};
};
-static void build_prime_cache_spec(const SkIRect &bounds,
- const SkSurfaceProps &props,
- const SkPicture &pic,
- SkStrikeCacheDifferenceSpec *strikeDifference) {
+static bool push_font_data(const SkPicture& pic, SkStrikeServer* strikeServer, int writeFd) {
SkMatrix deviceMatrix = SkMatrix::I();
-
- SkTextBlobCacheDiffCanvas filter(
- bounds.width(), bounds.height(), deviceMatrix, props,
- SkScalerContextFlags::kFakeGammaAndBoostContrast,
- strikeDifference);
-
+ const SkIRect bounds = pic.cullRect().round();
+ const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
+ SkTextBlobCacheDiffCanvas filter(bounds.width(), bounds.height(), deviceMatrix, props,
+ strikeServer);
pic.playback(&filter);
+
+ std::vector<uint8_t> fontData;
+ strikeServer->writeStrikeData(&fontData);
+ auto data = SkData::MakeWithoutCopy(fontData.data(), fontData.size());
+ return write_SkData(writeFd, *data);
}
-static void final_draw(std::string outFilename,
- SkDeserialProcs* procs,
- SkData* picData,
- SkStrikeClient* client) {
+static void final_draw(std::string outFilename, SkData* picData, SkStrikeClient* client,
+ ClientDiscardableManager* discardableManager, int readFd, int writeFd) {
+ SkDeserialProcs procs;
+ auto decode = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
+ return reinterpret_cast<SkStrikeClient*>(ctx)->deserializeTypeface(data, length);
+ };
+ procs.fTypefaceProc = decode;
+ procs.fTypefaceCtx = client;
- auto pic = SkPicture::MakeFromData(picData, procs);
+ auto pic = SkPicture::MakeFromData(picData, &procs);
auto cullRect = pic->cullRect();
auto r = cullRect.round();
auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
auto c = s->getCanvas();
- auto picUnderTest = SkPicture::MakeFromData(picData, procs);
+ auto picUnderTest = SkPicture::MakeFromData(picData, &procs);
Timer drawTime;
+ auto randomData = SkData::MakeUninitialized(1u);
for (int i = 0; i < 100; i++) {
if (gPurgeFontCaches) {
+ ClientDiscardableManager::ScopedPurgeCache purge(discardableManager);
SkGraphics::PurgeFontCache();
+ SkASSERT(SkGraphics::GetFontCacheUsed() == 0u);
}
+
drawTime.start();
if (client != nullptr) {
- SkStrikeCacheDifferenceSpec strikeDifference;
- build_prime_cache_spec(r, s->props(), *picUnderTest, &strikeDifference);
- client->primeStrikeCache(strikeDifference);
+ // Kick the renderer to send us the fonts.
+ write_SkData(writeFd, *randomData);
+ auto fontData = read_SkData(readFd);
+ if (fontData && !fontData->isEmpty()) {
+ if (!client->readStrikeData(fontData->data(), fontData->size()))
+ SK_ABORT("Bad serialization");
+ }
}
c->drawPicture(picUnderTest);
drawTime.stop();
@@ -150,22 +202,16 @@ static void final_draw(std::string outFilename,
static void gpu(int readFd, int writeFd) {
if (gUseGpu) {
- auto clientRPC = [readFd, writeFd](const SkData& inBuffer) {
- write_SkData(writeFd, inBuffer);
- return read_SkData(readFd);
- };
-
auto picData = read_SkData(readFd);
if (picData == nullptr) {
return;
}
- SkStrikeClient client{clientRPC};
+ sk_sp<ClientDiscardableManager> discardableManager = sk_make_sp<ClientDiscardableManager>();
+ SkStrikeClient strikeClient(discardableManager);
- SkDeserialProcs procs;
- client.prepareDeserializeProcs(&procs);
-
- final_draw("test.png", &procs, picData.get(), &client);
+ final_draw("test.png", picData.get(), &strikeClient, discardableManager.get(), readFd,
+ writeFd);
}
::close(writeFd);
@@ -177,7 +223,8 @@ static void gpu(int readFd, int writeFd) {
static int renderer(
const std::string& skpName, int readFd, int writeFd)
{
- SkStrikeServer server{};
+ ServerDiscardableManager discardableManager;
+ SkStrikeServer server(&discardableManager);
auto closeAll = [readFd, writeFd]() {
::close(writeFd);
::close(readFd);
@@ -186,11 +233,16 @@ static int renderer(
auto skpData = SkData::MakeFromFileName(skpName.c_str());
std::cout << "skp stream is " << skpData->size() << " bytes long " << std::endl;
- SkSerialProcs procs;
sk_sp<SkData> stream;
if (gUseGpu) {
auto pic = SkPicture::MakeFromData(skpData.get());
- server.prepareSerializeProcs(&procs);
+ SkSerialProcs procs;
+ auto encode = [](SkTypeface* tf, void* ctx) -> sk_sp<SkData> {
+ return reinterpret_cast<SkStrikeServer*>(ctx)->serializeTypeface(tf);
+ };
+ procs.fTypefaceProc = encode;
+ procs.fTypefaceCtx = &server;
+
stream = pic->serialize(&procs);
if (!write_SkData(writeFd, *stream)) {
@@ -198,22 +250,18 @@ static int renderer(
return 1;
}
- std::vector<uint8_t> tmpBuffer;
while (true) {
auto inBuffer = read_SkData(readFd);
if (inBuffer == nullptr) {
closeAll();
return 0;
}
-
- tmpBuffer.clear();
- server.serve(*inBuffer, &tmpBuffer);
- auto outBuffer = SkData::MakeWithoutCopy(tmpBuffer.data(), tmpBuffer.size());
- write_SkData(writeFd, *outBuffer);
+ if (gPurgeFontCaches) discardableManager.purgeAll();
+ push_font_data(*pic.get(), &server, writeFd);
}
} else {
stream = skpData;
- final_draw("test-correct.png", nullptr, stream.get(), nullptr);
+ final_draw("test-correct.png", stream.get(), nullptr, nullptr, -1, -1);
closeAll();
return 0;
}