diff options
author | Herb Derby <herb@google.com> | 2018-01-09 12:34:11 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-25 22:33:07 +0000 |
commit | 4f505f9c7763df96a97bfb2b8a682da6cb6bf7f1 (patch) | |
tree | b42d9ddd4e5e5dbb997b20e71d2349c32e68ad9a /tools/remote_demo.cpp | |
parent | 5d4dd8bef5d681648d1eff081959531aab3ecd30 (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.cpp | 168 |
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; } |