Revert "Remove all notion of transport from the API."

This reverts commit 4961a93858.

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 <herb@google.com>
> Reviewed-by: Khushal Sagar <khushalsagar@google.com>

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 <herb@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2018-04-08 03:56:42 +00:00 committed by Skia Commit-Bot
parent 87fa2b08aa
commit 4473907dee
3 changed files with 285 additions and 201 deletions

View File

@ -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<SkData> SkRemoteStrikeTransport::readSkData() {
size_t size;
if(std::get<1>(this->read(&size, sizeof(size))) == kFail) {
return nullptr;
}
auto data = std::unique_ptr<uint8_t[]>{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<uint8_t>& vector) {
return write_data(vector.size(), vector.data(), this);
}
SkRemoteStrikeTransport::IOResult SkRemoteStrikeTransport::readVector(
std::vector<uint8_t>* 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<uint8_t>& buffer) : fBuffer{buffer} { }
template <typename T>
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<T> 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<T> result = ArraySlice<T>{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<uint8_t>& 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<uint8_t>* outBuffer) {
int SkStrikeServer::serve() {
fOpCount += 1;
std::vector<uint8_t> inBuffer;
std::vector<uint8_t> outBuffer;
Serializer serializer{outBuffer};
Deserializer deserializer{inBuffer};
Op* op = deserializer.read<Op>();
switch (op->opCode) {
case OpCode::kFontMetrics : {
auto scaler = this->generateScalerContext(op->descriptor, op->typefaceId);
SkPaint::FontMetrics metrics;
scaler->getFontMetrics(&metrics);
serializer.push_back<SkPaint::FontMetrics>(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<size_t>(pathSize);
auto pathData = serializer.allocateArray<uint8_t>(pathSize);
path.writeToMemory(pathData);
Deserializer deserializer{inBuffer};
Op* op = deserializer.read<Op>();
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<SkPaint::FontMetrics>(metrics);
break;
}
break;
}
case OpCode::kGlyphMetricsAndImage : {
auto scaler = this->generateScalerContext(op->descriptor, op->typefaceId);
auto glyph = serializer.emplace_back<SkGlyph>();
// 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<uint8_t>(imageSize);
scaler->getImage(stationaryGlyph);
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<size_t>(pathSize);
auto pathData = serializer.allocateArray<uint8_t>(pathSize);
path.writeToMemory(pathData);
}
break;
}
break;
}
case OpCode::kPrepopulateCache : {
read_strikes_spec_write_strikes_data(
&deserializer, &serializer, this);
break;
case OpCode::kGlyphMetricsAndImage : {
auto scaler = this->generateScalerContext(op->descriptor, op->typefaceId);
auto glyph = serializer.emplace_back<SkGlyph>();
// 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<uint8_t>(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<SkData> SkStrikeServer::encodeTypeface(SkTypeface* tf) {
}
// -- SkStrikeClient -------------------------------------------------------------------------------
SkStrikeClient::SkStrikeClient(SkStrikeCacheClientRPC clientRPC)
: fClientRPC{clientRPC} { }
SkStrikeClient::SkStrikeClient(SkRemoteStrikeTransport* transport)
: fTransport{transport} { }
void SkStrikeClient::generateFontMetrics(
const SkTypefaceProxy& typefaceProxy,
const SkScalerContextRec& rec,
SkPaint::FontMetrics* metrics)
{
fBuffer.clear();
const SkTypefaceProxy& typefaceProxy,
const SkScalerContextRec& rec,
SkPaint::FontMetrics* metrics) {
// Send generateFontMetrics
{
fBuffer.clear();
Serializer serializer{&fBuffer};
serializer.emplace_back<Op>(OpCode::kFontMetrics, typefaceProxy.remoteTypefaceID(), rec);
fTransport->writeVector(fBuffer);
}
Serializer serializer{&fBuffer};
serializer.emplace_back<Op>(OpCode::kFontMetrics, typefaceProxy.remoteTypefaceID(), rec);
auto outBuffer = SkData::MakeWithoutCopy(fBuffer.data(), fBuffer.size());
auto inbuffer = fClientRPC(*outBuffer);
Deserializer deserializer(*inbuffer);
*metrics = *deserializer.read<SkPaint::FontMetrics>();
// Receive generateFontMetrics
{
fBuffer.clear();
fTransport->readVector(&fBuffer);
Deserializer deserializer(fBuffer);
*metrics = *deserializer.read<SkPaint::FontMetrics>();
}
}
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<Op>(
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<SkGlyph>();
auto imageSize = glyph->computeImageSize();
glyph->fPathData = nullptr;
glyph->fImage = nullptr;
if (imageSize > 0) {
auto image = deserializer.readArray<uint8_t>(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<SkGlyph>();
auto imageSize = glyph->computeImageSize();
glyph->fPathData = nullptr;
glyph->fImage = nullptr;
if (imageSize > 0) {
auto image = deserializer.readArray<uint8_t>(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<Op>(
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<size_t>();
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<Op>(
OpCode::kGlyphPath, typefaceProxy.remoteTypefaceID(), rec);
op->glyphID = glyphID;
fTransport->writeVector(fBuffer);
}
{
fBuffer.clear();
fTransport->readVector(&fBuffer);
Deserializer deserializer{fBuffer};
size_t pathSize = *deserializer.read<size_t>();
if (pathSize == 0) {
return false;
}
auto rawPath = deserializer.readArray<uint8_t>(pathSize);
path->readFromMemory(rawPath.data(), rawPath.size());
}
auto rawPath = deserializer.readArray<uint8_t>(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) {

View File

@ -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<sk_sp<SkData>(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<size_t, IOResult> read(void*, size_t) = 0;
IOResult writeSkData(const SkData&);
sk_sp<SkData> readSkData();
IOResult writeVector(const std::vector<uint8_t>&);
IOResult readVector(std::vector<uint8_t>*);
};
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<uint8_t>*);
int serve(); // very negotiable
void prepareSerializeProcs(SkSerialProcs* procs);
// mostly called internally by Skia
@ -175,13 +185,14 @@ private:
sk_sp<SkData> encodeTypeface(SkTypeface* tf);
int fOpCount = 0;
SkRemoteStrikeTransport* const fTransport;
SkTHashMap<SkFontID, sk_sp<SkTypeface>> 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<SkFontID, sk_sp<SkTypefaceProxy>> fMapIdToTypeface;
SkStrikeCacheClientRPC fClientRPC;
SkRemoteStrikeTransport* const fTransport;
std::vector<uint8_t> fBuffer;
};

View File

@ -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;
class ReadWriteTransport : public SkRemoteStrikeTransport {
public:
ReadWriteTransport(int readFd, int writeFd) : fReadFd{readFd}, fWriteFd{writeFd} {}
~ReadWriteTransport() override {
close(fWriteFd);
close(fReadFd);
}
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 kSuccess;
}
bytesWritten = ::write(fd, data.data(), data.size());
if (bytesWritten < 0) {
err(1,"Failed write %zu", size);
return false;
}
return true;
}
static sk_sp<SkData> read_SkData(int fd) {
size_t size;
ssize_t readSize = ::read(fd, &size, sizeof(size));
if (readSize <= 0) {
std::tuple<size_t, IOResult> read(void* buffer, size_t size) override {
ssize_t readSize = ::read(fReadFd, buffer, size);
if (readSize < 0) {
err(1, "Failed read %zu", size);
err(1,"Failed read %zu", size);
return {size, kFail};
}
return nullptr;
return {readSize, 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;
}
totalRead += sizeRead;
}
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<uint8_t> 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;
}
}