From 4473907dee6b34785ac5dafba7561c40977d9786 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Sun, 8 Apr 2018 03:56:42 +0000 Subject: Revert "Remove all notion of transport from the API." This reverts commit 4961a938586e3c46cf80f15ecb70a011324bfe59. Reason for revert: Breaks MSVC Original change's description: > Remove all notion of transport from the API. > > There is only a need to pass buffers in and out of the system. > All transport is external to the system. > > Change-Id: I26dfc8e0b4cce9969395c96d5230078e7dca3f3d > Reviewed-on: https://skia-review.googlesource.com/119062 > Commit-Queue: Herb Derby > Reviewed-by: Khushal Sagar TBR=herb@google.com,reed@google.com,khushalsagar@google.com # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: I62cbac1be4483702ba7464822d93fb9f818f88b7 Reviewed-on: https://skia-review.googlesource.com/119580 Reviewed-by: Herb Derby Commit-Queue: Herb Derby --- src/core/SkRemoteGlyphCache.cpp | 351 ++++++++++++++++++++++++++-------------- src/core/SkRemoteGlyphCache.h | 35 ++-- tools/remote_demo.cpp | 98 ++++------- 3 files changed, 284 insertions(+), 200 deletions(-) diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp index 3d925c49d3..9a7557f5c4 100644 --- a/src/core/SkRemoteGlyphCache.cpp +++ b/src/core/SkRemoteGlyphCache.cpp @@ -43,6 +43,77 @@ private: size_t fSize; }; +// -- SkRemoteStrikeTransport ---------------------------------------------------------------------- + +static SkRemoteStrikeTransport::IOResult write_data( + size_t size, const uint8_t* data, SkRemoteStrikeTransport* t) { + + if (t->write(&size, sizeof(size)) == SkRemoteStrikeTransport::kFail) { + return SkRemoteStrikeTransport::kFail; + } + + if (t->write(data, size) == SkRemoteStrikeTransport::kFail) { + return SkRemoteStrikeTransport::kFail; + } + + return SkRemoteStrikeTransport::kSuccess; +} + +static SkRemoteStrikeTransport::IOResult read_data( + size_t size, uint8_t* data, SkRemoteStrikeTransport* t) { + + size_t totalRead = 0; + while (totalRead < size) { + size_t sizeRead; + SkRemoteStrikeTransport::IOResult result; + std::tie(sizeRead, result) = t->read(&data[totalRead], size - totalRead); + if (result == SkRemoteStrikeTransport::kFail || sizeRead == 0) { + return SkRemoteStrikeTransport::kFail; + } + totalRead += sizeRead; + } + + return SkRemoteStrikeTransport::kSuccess; +} + +SkRemoteStrikeTransport::IOResult SkRemoteStrikeTransport::writeSkData(const SkData& data) { + return write_data(data.size(), (uint8_t*)data.data(), this); +} + +sk_sp SkRemoteStrikeTransport::readSkData() { + size_t size; + if(std::get<1>(this->read(&size, sizeof(size))) == kFail) { + return nullptr; + } + + auto data = std::unique_ptr{new uint8_t[size]}; + if (read_data(size, data.get(), this) == kFail) { + return nullptr; + } + + return SkData::MakeWithCopy(data.get(), size); +} + +SkRemoteStrikeTransport::IOResult SkRemoteStrikeTransport::writeVector( + const std::vector& vector) { + return write_data(vector.size(), vector.data(), this); +} + +SkRemoteStrikeTransport::IOResult SkRemoteStrikeTransport::readVector( + std::vector* vector) { + size_t vectorSize = 0; + size_t readSize = 0; + SkRemoteStrikeTransport::IOResult result; + std::tie(readSize, result) = this->read(&vectorSize, sizeof(vectorSize)); + if(result == kFail || readSize == 0) { + return kFail; + } + + vector->resize(vectorSize); + + return read_data(vectorSize, vector->data(), this); +} + // -- Serializer ---------------------------------------------------------------------------------- static size_t pad(size_t size, size_t alignment) { @@ -91,20 +162,18 @@ private: class Deserializer { public: - Deserializer(const SkData& buffer) : fBuffer{buffer} { } + Deserializer(const std::vector& buffer) : fBuffer{buffer} { } template T* read() { size_t padded = pad(fCursor, alignof(T)); fCursor = padded + sizeof(T); - auto data = (uint8_t*)fBuffer.data(); - return (T*)&data[padded]; + return (T*)&fBuffer[padded]; } SkDescriptor* readDescriptor() { size_t padded = pad(fCursor, alignof(SkDescriptor)); - auto data = (uint8_t*)fBuffer.data(); - SkDescriptor* result = (SkDescriptor*)&data[padded]; + SkDescriptor* result = (SkDescriptor*)&fBuffer[padded]; fCursor = padded + result->getLength(); return result; } @@ -113,8 +182,7 @@ public: ArraySlice readArray(int count) { size_t padded = pad(fCursor, alignof(T)); size_t size = count * sizeof(T); - auto data = (uint8_t*)fBuffer.data(); - const T* base = (const T*)&data[padded]; + const T* base = (const T*)&fBuffer[padded]; ArraySlice result = ArraySlice{base, (uint32_t)count}; fCursor = padded + size; return result; @@ -123,8 +191,8 @@ public: size_t size() {return fCursor;} private: - const SkData& fBuffer; - size_t fCursor{0}; + const std::vector& fBuffer; + size_t fCursor{0}; }; @@ -418,6 +486,14 @@ public: }; }; +class Result { + union { + SkPaint::FontMetrics fontMetrics; + SkGlyph glyph; + StrikeDiffHeader strikeDiffHeader; + }; +}; + size_t SkStrikeCacheDifferenceSpec::sizeBytes() const { size_t sum = sizeof(Op) + sizeof(StrikeDiffHeader); for (auto& pair : fDescriptorToDifferencesMap) { @@ -514,67 +590,85 @@ static void update_caches_from_strikes_data(SkStrikeClient *client, } // -- SkStrikeServer ------------------------------------------------------------------------------- -SkStrikeServer::SkStrikeServer() { } +SkStrikeServer::SkStrikeServer(SkRemoteStrikeTransport* transport) + : fTransport{transport} { } SkStrikeServer::~SkStrikeServer() { printf("Strike server - ops: %d\n", fOpCount); } -void SkStrikeServer::serve(const SkData& inBuffer, std::vector* outBuffer) { +int SkStrikeServer::serve() { - fOpCount += 1; + std::vector inBuffer; + std::vector outBuffer; - Serializer serializer{outBuffer}; - Deserializer deserializer{inBuffer}; - Op* op = deserializer.read(); - - switch (op->opCode) { - case OpCode::kFontMetrics : { - auto scaler = this->generateScalerContext(op->descriptor, op->typefaceId); - SkPaint::FontMetrics metrics; - scaler->getFontMetrics(&metrics); - serializer.push_back(metrics); + while (true) { + inBuffer.clear(); + auto result = fTransport->readVector(&inBuffer); + if (result == SkRemoteStrikeTransport::kFail) { break; } - case OpCode::kGlyphPath : { - auto sc = this->generateScalerContext(op->descriptor, op->typefaceId); - // TODO: check for buffer overflow. - SkPath path; - if (sc->getPath(op->glyphID, &path)) { - size_t pathSize = path.writeToMemory(nullptr); - serializer.push_back(pathSize); - auto pathData = serializer.allocateArray(pathSize); - path.writeToMemory(pathData); - } - break; - } - case OpCode::kGlyphMetricsAndImage : { - auto scaler = this->generateScalerContext(op->descriptor, op->typefaceId); - auto glyph = serializer.emplace_back(); - // TODO: check for buffer overflow. - glyph->initWithGlyphID(op->glyphID); - scaler->getMetrics(glyph); - auto imageSize = glyph->computeImageSize(); - glyph->fPathData = nullptr; - glyph->fImage = nullptr; - if (imageSize > 0) { - // Since the allocateArray can move glyph, make one that stays in one place. - SkGlyph stationaryGlyph = *glyph; - stationaryGlyph.fImage = serializer.allocateArray(imageSize); - scaler->getImage(stationaryGlyph); + Deserializer deserializer{inBuffer}; + Op* op = deserializer.read(); + + fOpCount += 1; + + outBuffer.clear(); + Serializer serializer{&outBuffer}; + + switch (op->opCode) { + case OpCode::kFontMetrics : { + auto sc = this->generateScalerContext(op->descriptor, op->typefaceId); + SkPaint::FontMetrics metrics; + sc->getFontMetrics(&metrics); + serializer.push_back(metrics); + break; } - break; - } - case OpCode::kPrepopulateCache : { - read_strikes_spec_write_strikes_data( - &deserializer, &serializer, this); - break; + case OpCode::kGlyphPath : { + auto sc = this->generateScalerContext(op->descriptor, op->typefaceId); + // TODO: check for buffer overflow. + SkPath path; + if (sc->getPath(op->glyphID, &path)) { + size_t pathSize = path.writeToMemory(nullptr); + serializer.push_back(pathSize); + auto pathData = serializer.allocateArray(pathSize); + path.writeToMemory(pathData); + } + break; + } + case OpCode::kGlyphMetricsAndImage : { + auto scaler = this->generateScalerContext(op->descriptor, op->typefaceId); + + auto glyph = serializer.emplace_back(); + // TODO: check for buffer overflow. + glyph->initWithGlyphID(op->glyphID); + scaler->getMetrics(glyph); + auto imageSize = glyph->computeImageSize(); + glyph->fPathData = nullptr; + glyph->fImage = nullptr; + + if (imageSize > 0) { + // Since the allocateArray can move glyph, make one that stays in one place. + SkGlyph stationaryGlyph = *glyph; + stationaryGlyph.fImage = serializer.allocateArray(imageSize); + scaler->getImage(stationaryGlyph); + } + break; + } + case OpCode::kPrepopulateCache : { + read_strikes_spec_write_strikes_data( + &deserializer, &serializer, this); + break; + } + + default: + SK_ABORT("Bad op"); } - default: - SK_ABORT("Bad op"); + fTransport->writeVector(outBuffer); } + return 0; } void SkStrikeServer::prepareSerializeProcs(SkSerialProcs* procs) { @@ -623,88 +717,105 @@ sk_sp SkStrikeServer::encodeTypeface(SkTypeface* tf) { } // -- SkStrikeClient ------------------------------------------------------------------------------- -SkStrikeClient::SkStrikeClient(SkStrikeCacheClientRPC clientRPC) - : fClientRPC{clientRPC} { } -void SkStrikeClient::generateFontMetrics( - const SkTypefaceProxy& typefaceProxy, - const SkScalerContextRec& rec, - SkPaint::FontMetrics* metrics) -{ - fBuffer.clear(); +SkStrikeClient::SkStrikeClient(SkRemoteStrikeTransport* transport) + : fTransport{transport} { } - Serializer serializer{&fBuffer}; - serializer.emplace_back(OpCode::kFontMetrics, typefaceProxy.remoteTypefaceID(), rec); +void SkStrikeClient::generateFontMetrics( + const SkTypefaceProxy& typefaceProxy, + const SkScalerContextRec& rec, + SkPaint::FontMetrics* metrics) { + // Send generateFontMetrics + { + fBuffer.clear(); + Serializer serializer{&fBuffer}; + serializer.emplace_back(OpCode::kFontMetrics, typefaceProxy.remoteTypefaceID(), rec); + fTransport->writeVector(fBuffer); + } - auto outBuffer = SkData::MakeWithoutCopy(fBuffer.data(), fBuffer.size()); - auto inbuffer = fClientRPC(*outBuffer); - Deserializer deserializer(*inbuffer); - *metrics = *deserializer.read(); + // Receive generateFontMetrics + { + fBuffer.clear(); + fTransport->readVector(&fBuffer); + Deserializer deserializer(fBuffer); + *metrics = *deserializer.read(); + } } void SkStrikeClient::generateMetricsAndImage( - const SkTypefaceProxy& typefaceProxy, - const SkScalerContextRec& rec, - SkArenaAlloc* alloc, - SkGlyph* glyph) -{ + const SkTypefaceProxy& typefaceProxy, + const SkScalerContextRec& rec, + SkArenaAlloc* alloc, + SkGlyph* glyph) { + { fBuffer.clear(); Serializer serializer(&fBuffer); Op *op = serializer.emplace_back( OpCode::kGlyphMetricsAndImage, typefaceProxy.remoteTypefaceID(), rec); - op->glyphID = glyph->getPackedID(); - - auto outBuffer = SkData::MakeWithoutCopy(fBuffer.data(), fBuffer.size()); - auto inbuffer = fClientRPC(*outBuffer); - Deserializer deserializer(*inbuffer); - *glyph = *deserializer.read(); - auto imageSize = glyph->computeImageSize(); - glyph->fPathData = nullptr; - glyph->fImage = nullptr; - if (imageSize > 0) { - auto image = deserializer.readArray(imageSize); - SkASSERT(imageSize == image.size()); - glyph->allocImage(alloc); - memcpy(glyph->fImage, image.data(), imageSize); + op->glyphID = glyph->getPackedID(); + fTransport->writeVector(fBuffer); + } + + // Receive generateMetricsAndImage + { + fBuffer.clear(); + fTransport->readVector(&fBuffer); + Deserializer deserializer(fBuffer); + *glyph = *deserializer.read(); + auto imageSize = glyph->computeImageSize(); + glyph->fPathData = nullptr; + glyph->fImage = nullptr; + if (imageSize > 0) { + auto image = deserializer.readArray(imageSize); + SkASSERT(imageSize == image.size()); + glyph->allocImage(alloc); + memcpy(glyph->fImage, image.data(), imageSize); + } } -} +} bool SkStrikeClient::generatePath( - const SkTypefaceProxy& typefaceProxy, - const SkScalerContextRec& rec, - SkGlyphID glyphID, - SkPath* path) -{ - fBuffer.clear(); - - Serializer serializer{&fBuffer}; - Op *op = serializer.emplace_back( - OpCode::kGlyphPath, typefaceProxy.remoteTypefaceID(), rec); - op->glyphID = glyphID; - - auto outBuffer = SkData::MakeWithoutCopy(fBuffer.data(), fBuffer.size()); - auto inbuffer = fClientRPC(*outBuffer); - Deserializer deserializer(*inbuffer); - size_t pathSize = *deserializer.read(); - if (pathSize == 0) { - return false; + const SkTypefaceProxy& typefaceProxy, + const SkScalerContextRec& rec, + SkGlyphID glyphID, + SkPath* path) { + { + fBuffer.clear(); + Serializer serializer{&fBuffer}; + Op *op = serializer.emplace_back( + OpCode::kGlyphPath, typefaceProxy.remoteTypefaceID(), rec); + op->glyphID = glyphID; + fTransport->writeVector(fBuffer); + } + + { + fBuffer.clear(); + fTransport->readVector(&fBuffer); + Deserializer deserializer{fBuffer}; + size_t pathSize = *deserializer.read(); + if (pathSize == 0) { + return false; + } + auto rawPath = deserializer.readArray(pathSize); + path->readFromMemory(rawPath.data(), rawPath.size()); } - auto rawPath = deserializer.readArray(pathSize); - path->readFromMemory(rawPath.data(), rawPath.size()); return true; } void SkStrikeClient::primeStrikeCache(const SkStrikeCacheDifferenceSpec& strikeDifferences) { - fBuffer.clear(); - fBuffer.reserve(strikeDifferences.sizeBytes()); - - Serializer serializer{&fBuffer}; - write_strikes_spec(strikeDifferences, &serializer); - - auto outBuffer = SkData::MakeWithoutCopy(fBuffer.data(), fBuffer.size()); - auto inbuffer = fClientRPC(*outBuffer); - Deserializer deserializer(*inbuffer); - update_caches_from_strikes_data(this, &deserializer); + { + fBuffer.clear(); + fBuffer.reserve(strikeDifferences.sizeBytes()); + Serializer serializer{&fBuffer}; + write_strikes_spec(strikeDifferences, &serializer); + fTransport->writeVector(fBuffer); + } + { + fBuffer.clear(); + fTransport->readVector(&fBuffer); + Deserializer deserializer{fBuffer}; + update_caches_from_strikes_data(this, &deserializer); + } } void SkStrikeClient::prepareDeserializeProcs(SkDeserialProcs* procs) { diff --git a/src/core/SkRemoteGlyphCache.h b/src/core/SkRemoteGlyphCache.h index 04d72a083b..3dfa8c28e5 100644 --- a/src/core/SkRemoteGlyphCache.h +++ b/src/core/SkRemoteGlyphCache.h @@ -19,15 +19,26 @@ #include "SkGlyphCache.h" #include "SkMakeUnique.h" #include "SkNoDrawCanvas.h" -#include "SkRefCnt.h" #include "SkSerialProcs.h" #include "SkTextBlobRunIterator.h" #include "SkTHash.h" #include "SkTypeface.h" #include "SkTypeface_remote.h" -// The client uses a SkStrikeCacheClientRPC to send and receive data. -using SkStrikeCacheClientRPC = std::function(const SkData&)>; +class SkScalerContextRecDescriptor; + +class SkRemoteStrikeTransport { +public: + enum IOResult : bool {kFail = false, kSuccess = true}; + + virtual ~SkRemoteStrikeTransport() {} + virtual IOResult write(const void*, size_t) = 0; + virtual std::tuple read(void*, size_t) = 0; + IOResult writeSkData(const SkData&); + sk_sp readSkData(); + IOResult writeVector(const std::vector&); + IOResult readVector(std::vector*); +}; class SkScalerContextRecDescriptor { public: @@ -83,7 +94,7 @@ private: } fDescriptor; }; -class SK_API SkStrikeCacheDifferenceSpec { +class SkStrikeCacheDifferenceSpec { class StrikeDifferences; public: @@ -120,7 +131,7 @@ private: DescMap fDescriptorToDifferencesMap{16, DescHash(), DescEq()}; }; -class SK_API SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas { +class SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas { public: SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix, @@ -153,14 +164,13 @@ private: SkStrikeCacheDifferenceSpec* const fStrikeCacheDiff; }; -class SK_API SkStrikeServer { +class SkStrikeServer { public: - SkStrikeServer(); + SkStrikeServer(SkRemoteStrikeTransport* transport); ~SkStrikeServer(); // embedding clients call these methods - void serve(const SkData&, std::vector*); - + int serve(); // very negotiable void prepareSerializeProcs(SkSerialProcs* procs); // mostly called internally by Skia @@ -175,13 +185,14 @@ private: sk_sp encodeTypeface(SkTypeface* tf); int fOpCount = 0; + SkRemoteStrikeTransport* const fTransport; SkTHashMap> fTypefaceMap; DescriptorToContextMap fScalerContextMap; }; -class SK_API SkStrikeClient { +class SkStrikeClient { public: - SkStrikeClient(SkStrikeCacheClientRPC); + SkStrikeClient(SkRemoteStrikeTransport*); // embedding clients call these methods void primeStrikeCache(const SkStrikeCacheDifferenceSpec&); @@ -202,7 +213,7 @@ private: // TODO: Figure out how to manage the entries for the following maps. SkTHashMap> fMapIdToTypeface; - SkStrikeCacheClientRPC fClientRPC; + SkRemoteStrikeTransport* const fTransport; std::vector fBuffer; }; diff --git a/tools/remote_demo.cpp b/tools/remote_demo.cpp index 8fc96cadb8..a5e0a367de 100644 --- a/tools/remote_demo.cpp +++ b/tools/remote_demo.cpp @@ -25,52 +25,35 @@ static bool gUseGpu = true; static bool gPurgeFontCaches = true; static bool gUseProcess = true; -static bool write_SkData(int fd, const SkData& data) { - size_t size = data.size(); - ssize_t bytesWritten = ::write(fd, &size, sizeof(size)); - if (bytesWritten < 0) { - err(1,"Failed write %zu", size); - return false; - } - - bytesWritten = ::write(fd, data.data(), data.size()); - if (bytesWritten < 0) { - err(1,"Failed write %zu", size); - return false; +class ReadWriteTransport : public SkRemoteStrikeTransport { +public: + ReadWriteTransport(int readFd, int writeFd) : fReadFd{readFd}, fWriteFd{writeFd} {} + ~ReadWriteTransport() override { + close(fWriteFd); + close(fReadFd); } - - return true; -} - -static sk_sp read_SkData(int fd) { - - size_t size; - ssize_t readSize = ::read(fd, &size, sizeof(size)); - if (readSize <= 0) { - if (readSize < 0) { - err(1, "Failed read %zu", size); + IOResult write(const void* buffer, size_t size) override { + ssize_t writeSize = ::write(fWriteFd, buffer, size); + if (writeSize < 0) { + err(1,"Failed write %zu", size); + return kFail; } - return nullptr; + return kSuccess; } - auto out = SkData::MakeUninitialized(size); - auto data = (uint8_t*)out->data(); - - size_t totalRead = 0; - while (totalRead < size) { - ssize_t sizeRead; - sizeRead = ::read(fd, &data[totalRead], size - totalRead); - if (sizeRead <= 0) { - if (readSize < 0) { - err(1, "Failed read %zu", size); - } - return nullptr; + std::tuple read(void* buffer, size_t size) override { + ssize_t readSize = ::read(fReadFd, buffer, size); + if (readSize < 0) { + err(1,"Failed read %zu", size); + return {size, kFail}; } - totalRead += sizeRead; + return {readSize, kSuccess}; } - return out; -} +private: + const int fReadFd, + fWriteFd; +}; class Timer { public: @@ -150,17 +133,14 @@ 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); - }; + ReadWriteTransport rwTransport{readFd, writeFd}; - auto picData = read_SkData(readFd); + auto picData = rwTransport.readSkData(); if (picData == nullptr) { return; } - SkStrikeClient client{clientRPC}; + SkStrikeClient client{&rwTransport}; SkDeserialProcs procs; client.prepareDeserializeProcs(&procs); @@ -168,20 +148,14 @@ static void gpu(int readFd, int writeFd) { final_draw("test.png", &procs, picData.get(), &client); } - ::close(writeFd); - ::close(readFd); - printf("GPU is exiting\n"); } static int renderer( const std::string& skpName, int readFd, int writeFd) { - SkStrikeServer server{}; - auto closeAll = [readFd, writeFd]() { - ::close(writeFd); - ::close(readFd); - }; + ReadWriteTransport rwTransport{readFd, writeFd}; + SkStrikeServer server{&rwTransport}; auto skpData = SkData::MakeFromFileName(skpName.c_str()); std::cout << "skp stream is " << skpData->size() << " bytes long " << std::endl; @@ -193,28 +167,16 @@ static int renderer( server.prepareSerializeProcs(&procs); stream = pic->serialize(&procs); - if (!write_SkData(writeFd, *stream)) { - closeAll(); + if (rwTransport.writeSkData(*stream) == SkRemoteStrikeTransport::kFail) { return 1; } - std::vector tmpBuffer; - while (true) { - auto inBuffer = read_SkData(readFd); - if (inBuffer == nullptr) { - closeAll(); - return 0; - } + std::cout << "Waiting for scaler context ops." << std::endl; - tmpBuffer.clear(); - server.serve(*inBuffer, &tmpBuffer); - auto outBuffer = SkData::MakeWithoutCopy(tmpBuffer.data(), tmpBuffer.size()); - write_SkData(writeFd, *outBuffer); - } + return server.serve(); } else { stream = skpData; final_draw("test-correct.png", nullptr, stream.get(), nullptr); - closeAll(); return 0; } } -- cgit v1.2.3