aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/remote_demo.cpp
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2018-01-09 12:34:11 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-25 22:33:07 +0000
commit4f505f9c7763df96a97bfb2b8a682da6cb6bf7f1 (patch)
treeb42d9ddd4e5e5dbb997b20e71d2349c32e68ad9a /tools/remote_demo.cpp
parent5d4dd8bef5d681648d1eff081959531aab3ecd30 (diff)
Add cache for handling of contexts.
Added scaler context cache on the Renderer side that maps descriptors to scaler contexts. Added preliminary timing code. Remove unused print statements. BUG=skia:7515 Change-Id: I156ba656aab113e0ceae0c2ea0f9f3c1d3d61d6a Reviewed-on: https://skia-review.googlesource.com/99540 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'tools/remote_demo.cpp')
-rw-r--r--tools/remote_demo.cpp168
1 files changed, 116 insertions, 52 deletions
diff --git a/tools/remote_demo.cpp b/tools/remote_demo.cpp
index fbc2480278..4fbec34fec 100644
--- a/tools/remote_demo.cpp
+++ b/tools/remote_demo.cpp
@@ -18,6 +18,7 @@
#include "SkTypeface.h"
#include "SkWriteBuffer.h"
+#include <chrono>
#include <ctype.h>
#include <err.h>
#include <memory>
@@ -41,9 +42,46 @@ struct WireTypeface {
bool is_fixed;
};
+class ScalerContextRecDescriptor {
+public:
+ explicit ScalerContextRecDescriptor(const SkScalerContextRec& rec) {
+ auto desc = reinterpret_cast<SkDescriptor*>(&fDescriptor);
+ desc->init();
+ desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+ }
+
+ const SkDescriptor& desc() const {
+ return *reinterpret_cast<const SkDescriptor*>(&fDescriptor);
+ }
+
+ struct Hash {
+ size_t operator()(ScalerContextRecDescriptor const& s) const {
+ return SkOpts::hash_fn(&s.desc(), sizeof(s), 0);
+ }
+ };
+
+ struct Equal {
+ bool operator()( const ScalerContextRecDescriptor& lhs,
+ const ScalerContextRecDescriptor& rhs ) const {
+ return lhs.desc() == rhs.desc();
+ }
+ };
+
+private:
+ // The system only passes descriptors without effects. That is why it uses a fixed size
+ // descriptor. storageFor is needed because some of the constructors below are private.
+ template <typename T>
+ using storageFor = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
+ struct {
+ storageFor<SkDescriptor> dummy1;
+ storageFor<SkDescriptor::Entry> dummy2;
+ storageFor<SkScalerContextRec> dummy3;
+ } fDescriptor;
+};
+
class Op {
public:
- Op() {}
+ explicit Op(const SkScalerContextRec& rec) : descriptor{rec} {}
int32_t op;
SkFontID typeface_id;
union {
@@ -57,15 +95,7 @@ public:
size_t pathSize;
};
};
- // The system only passes descriptors without effects. That is why it uses a fixed size
- // descriptor. storageFor is needed because some of the constructors below are private.
- template <typename T>
- using storageFor = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
- struct {
- storageFor<SkDescriptor> dummy1;
- storageFor<SkDescriptor::Entry> dummy2;
- storageFor<SkScalerContextRec> dummy3;
- } descriptor;
+ ScalerContextRecDescriptor descriptor;
};
class RemoteScalerContextPassThread : public SkRemoteScalerContext {
@@ -78,8 +108,7 @@ public:
SkPaint::FontMetrics* metrics) override {
Op* op = this->createOp(0, tf, rec);
write(fWriteFd, fBuffer, sizeof(*op));
- ssize_t readSize = read(fReadFd, fBuffer, sizeof(fBuffer));
- std::cerr << "gpu - op 0 read size: " << readSize << std::endl;
+ read(fReadFd, fBuffer, sizeof(fBuffer));
memcpy(metrics, &op->fontMetrics, sizeof(op->fontMetrics));
op->~Op();
}
@@ -104,7 +133,6 @@ public:
read(fReadFd, fBuffer, sizeof(fBuffer));
//memcpy((SkGlyph *)&glyph, &op->glyph, sizeof(op->glyph));
//((SkGlyph*)&glyph)->fImage = oldImage;
- std::cerr << "rb: " << glyph.rowBytes() << " h: " << glyph.fHeight << std::endl;
memcpy(glyph.fImage, fBuffer + sizeof(Op), glyph.rowBytes() * glyph.fHeight);
op->~Op();
}
@@ -123,15 +151,10 @@ public:
private:
Op* createOp(uint32_t opID, const SkTypefaceProxy& tf,
const SkScalerContextRec& rec) {
- Op* op = new (fBuffer) Op();
+ Op* op = new (fBuffer) Op(rec);
op->op = opID;
op->typeface_id = tf.fontID();
- SkASSERT(SkScalerContext::CheckBufferSizeForRec(
- rec, SkScalerContextEffects{}, sizeof(op->descriptor)));
-
- SkScalerContext::DescriptorBufferGiveRec(rec, &op->descriptor);
-
return op;
}
@@ -142,10 +165,8 @@ private:
static sk_sp<SkTypeface> gpu_from_renderer_by_ID(const void* buf, size_t len, void* ctx) {
WireTypeface wire;
- std::cerr << "gpu - typeface from rendere size: " << len << std::endl;
if (len >= sizeof(wire)) {
memcpy(&wire, buf, sizeof(wire));
- std::cerr << wire.thread_id << " " << wire.typeface_id << std::endl;
return sk_sp<SkTypeface>(
new SkTypefaceProxy(
wire.typeface_id,
@@ -160,18 +181,33 @@ static sk_sp<SkTypeface> gpu_from_renderer_by_ID(const void* buf, size_t len, vo
std::unordered_map<SkFontID, sk_sp<SkTypeface>> gTypefaceMap;
-static std::unique_ptr<SkScalerContext> scaler_context_from_op(Op* op) {
+// TODO: Figure out how to manage the entries.
+std::unordered_map<ScalerContextRecDescriptor,
+ std::unique_ptr<SkScalerContext>,
+ ScalerContextRecDescriptor::Hash,
+ ScalerContextRecDescriptor::Equal>
+ gScalerContextMap(16,
+ ScalerContextRecDescriptor::Hash(),
+ ScalerContextRecDescriptor::Equal());
- auto i = gTypefaceMap.find(op->typeface_id);
- if (i == gTypefaceMap.end()) {
- std::cerr << "bad typeface id: " << op->typeface_id << std::endl;
- SK_ABORT("unknown type face");
+static SkScalerContext* scaler_context_from_op(Op* op) {
+
+ SkScalerContext* sc;
+ auto j = gScalerContextMap.find(op->descriptor);
+ if (j != gScalerContextMap.end()) {
+ sc = j->second.get();
+ } else {
+ auto i = gTypefaceMap.find(op->typeface_id);
+ if (i == gTypefaceMap.end()) {
+ std::cerr << "bad typeface id: " << op->typeface_id << std::endl;
+ SK_ABORT("unknown type face");
+ }
+ auto tf = i->second;
+ SkScalerContextEffects effects;
+ auto mapSc = tf->createScalerContext(effects, &op->descriptor.desc(), false);
+ sc = mapSc.get();
+ gScalerContextMap.emplace_hint(j, op->descriptor, std::move(mapSc));
}
- auto tf = i->second;
- std::cerr << "ops - got typeface: " << i->first << " , " << tf.get() << std::endl;
- SkScalerContextEffects effects;
- auto sc = tf->createScalerContext(effects, (SkDescriptor *)&op->descriptor, false);
- std::cerr << "ops - created sc " << std::endl;
return sc;
}
@@ -185,18 +221,43 @@ static sk_sp<SkData> renderer_to_gpu_by_ID(SkTypeface* tf, void* ctx) {
};
auto i = gTypefaceMap.find(SkTypeface::UniqueID(tf));
if (i == gTypefaceMap.end()) {
- std::cerr << "font id table - inserting: " << SkTypeface::UniqueID(tf) << std::endl;
gTypefaceMap.insert({SkTypeface::UniqueID(tf), sk_ref_sp(tf)});
}
return SkData::MakeWithCopy(&wire, sizeof(wire));
}
+static void final_draw(std::string outFilename,
+ SkDeserialProcs* procs,
+ uint8_t* picData,
+ size_t picSize) {
+ auto start = std::chrono::high_resolution_clock::now();
+
+ auto pic = SkPicture::MakeFromData(picData, picSize, procs);
+
+ auto cullRect = pic->cullRect();
+ auto r = cullRect.round();
+ auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
+
+ auto c = s->getCanvas();
+ c->drawPicture(pic);
+
+ auto end = std::chrono::high_resolution_clock::now();
+
+ std::chrono::duration<double> elapsed_seconds = end-start;
+
+ std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
+
+ auto i = s->makeImageSnapshot();
+ auto data = i->encodeToData();
+ SkFILEWStream f(outFilename.c_str());
+ f.write(data->data(), data->size());
+}
+
static void gpu(int readFd, int writeFd) {
size_t picSize = 0;
read(readFd, &picSize, sizeof(picSize));
- std::cerr << "gpu - reading pic size: " << picSize << std::endl;
static constexpr size_t kBufferSize = 10 * 1024 * kPageSize;
std::unique_ptr<uint8_t[]> picBuffer{new uint8_t[kBufferSize]};
@@ -208,15 +269,15 @@ static void gpu(int readFd, int writeFd) {
err(1, "gpu pic read error %d", errno);
}
readSoFar += readSize;
- //std::cerr << "gpu - recieved so far: " << readSoFar << std::endl;
}
- std::cerr << "gpu - Receiving picture" << std::endl;
SkDeserialProcs procs;
std::unique_ptr<SkRemoteScalerContext> rsc{
new RemoteScalerContextPassThread{readFd, writeFd}};
procs.fTypefaceProc = gpu_from_renderer_by_ID;
procs.fTypefaceCtx = rsc.get();
+ final_draw("test.png", &procs, picBuffer.get(), picSize);
+ /*
auto pic = SkPicture::MakeFromData(picBuffer.get(), picSize, &procs);
auto cullRect = pic->cullRect();
@@ -226,40 +287,48 @@ static void gpu(int readFd, int writeFd) {
auto c = s->getCanvas();
c->drawPicture(pic);
- std::cerr << "gpu - output picture" << std::endl;
auto i = s->makeImageSnapshot();
auto data = i->encodeToData();
SkFILEWStream f("test.png");
f.write(data->data(), data->size());
+ */
close(writeFd);
close(readFd);
-
}
static int renderer(const std::string& skpName, int readFd, int writeFd) {
std::string prefix{"skps/"};
std::string fileName{prefix + skpName + ".skp"};
- std::cerr << "Reading skp: " << fileName << std::endl;
auto skp = SkData::MakeFromFileName(fileName.c_str());
auto pic = SkPicture::MakeFromData(skp.get());
+ bool toGpu = true;
+
SkSerialProcs procs;
- procs.fTypefaceProc = renderer_to_gpu_by_ID;
+ if (toGpu) {
+ procs.fTypefaceProc = renderer_to_gpu_by_ID;
+ }
+
auto stream = pic->serialize(&procs);
std::cerr << "stream is " << stream->size() << " bytes long" << std::endl;
- std::cerr << "render - Sending stream." << std::endl;
-
size_t picSize = stream->size();
uint8_t* picBuffer = (uint8_t*) stream->data();
+
+ if (!toGpu) {
+ final_draw("test-direct.png", nullptr, picBuffer, picSize);
+ close(writeFd);
+ close(readFd);
+ return 0;
+ }
+
write(writeFd, &picSize, sizeof(picSize));
size_t writeSoFar = 0;
while (writeSoFar < picSize) {
ssize_t writeSize = write(writeFd, &picBuffer[writeSoFar], picSize - writeSoFar);
- std::cerr << "renderer - bytes written: " << writeSize << std::endl;
if (writeSize <= 0) {
if (writeSize == 0) {
std::cerr << "Exit" << std::endl;
@@ -280,7 +349,6 @@ static int renderer(const std::string& skpName, int readFd, int writeFd) {
ssize_t size = read(readFd, glyphBuffer.get(), sizeof(*op));
if (size <= 0) { std::cerr << "Exit op loop" << std::endl; break;}
size_t writeSize = sizeof(*op);
- std::cerr << "op: " << op << " op->op: " << op->op << std::endl;
auto sc = scaler_context_from_op(op);
switch (op->op) {
@@ -310,9 +378,7 @@ static int renderer(const std::string& skpName, int readFd, int writeFd) {
default:
SkASSERT("Bad op");
}
- std::cerr << "ops - writing" << std::endl;
- ssize_t written = write(writeFd, glyphBuffer.get(), writeSize);
- std::cerr << " opss - writing : " << writeSize << " written: " << written << std::endl;
+ write(writeFd, glyphBuffer.get(), writeSize);
}
close(readFd);
@@ -353,23 +419,21 @@ int main(int argc, char** argv) {
close(gpu_to_render[kWrite]);
std::cerr << "Starting renderer" << std::endl;
printf("skp: %s\n", skpName.c_str());
- renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
- //gpu(gpu_to_render[kRead], render_to_gpu[kWrite]);
+ //renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
+ gpu(gpu_to_render[kRead], render_to_gpu[kWrite]);
} else {
// The parent - GPU
// Close unused pipe ends.
std::cerr << "child id - " << child << std::endl;
close(gpu_to_render[kRead]);
close(render_to_gpu[kWrite]);
- gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
- //renderer(skpName, render_to_gpu[kRead], gpu_to_render[kWrite]);
-
+ //gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
+ renderer(skpName, render_to_gpu[kRead], gpu_to_render[kWrite]);
std::cerr << "Waiting for renderer." << std::endl;
waitpid(child, nullptr, 0);
}
-
return 0;
}