Home | History | Annotate | Download | only in tools
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkCanvas.h"
      9 #include "SkPathEffect.h"
     10 #include "SkMaskFilter.h"
     11 #include "SkData.h"
     12 #include "SkDescriptor.h"
     13 #include "SkGraphics.h"
     14 #include "SkSemaphore.h"
     15 #include "SkPictureRecorder.h"
     16 #include "SkSerialProcs.h"
     17 #include "SkSurface.h"
     18 #include "SkTypeface.h"
     19 #include "SkWriteBuffer.h"
     20 
     21 #include <chrono>
     22 #include <ctype.h>
     23 #include <err.h>
     24 #include <memory>
     25 #include <stdio.h>
     26 #include <thread>
     27 #include <iostream>
     28 #include <unordered_map>
     29 
     30 #include <sys/types.h>
     31 #include <sys/wait.h>
     32 #include <unistd.h>
     33 #include <sys/mman.h>
     34 #include "SkTypeface_remote.h"
     35 
     36 static const size_t kPageSize = 4096;
     37 
     38 struct WireTypeface {
     39     std::thread::id thread_id;
     40     SkFontID        typeface_id;
     41     SkFontStyle     style;
     42     bool            is_fixed;
     43 };
     44 
     45 class ScalerContextRecDescriptor {
     46 public:
     47     explicit ScalerContextRecDescriptor(const SkScalerContextRec& rec) {
     48         auto desc = reinterpret_cast<SkDescriptor*>(&fDescriptor);
     49         desc->init();
     50         desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
     51     }
     52 
     53     const SkDescriptor& desc() const {
     54         return *reinterpret_cast<const SkDescriptor*>(&fDescriptor);
     55     }
     56 
     57     struct Hash {
     58         size_t operator()(ScalerContextRecDescriptor const& s) const {
     59             return SkOpts::hash_fn(&s.desc(), sizeof(s), 0);
     60         }
     61     };
     62 
     63     struct Equal {
     64         bool operator()( const ScalerContextRecDescriptor& lhs,
     65                          const ScalerContextRecDescriptor& rhs ) const {
     66             return lhs.desc() == rhs.desc();
     67         }
     68     };
     69 
     70 private:
     71     // The system only passes descriptors without effects. That is why it uses a fixed size
     72     // descriptor. storageFor is needed because some of the constructors below are private.
     73     template <typename T>
     74     using storageFor = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
     75     struct {
     76         storageFor<SkDescriptor>        dummy1;
     77         storageFor<SkDescriptor::Entry> dummy2;
     78         storageFor<SkScalerContextRec>  dummy3;
     79     } fDescriptor;
     80 };
     81 
     82 class Op {
     83 public:
     84     explicit Op(const SkScalerContextRec& rec) : descriptor{rec} {}
     85     int32_t op;
     86     SkFontID typeface_id;
     87     union {
     88         // op 0
     89         SkPaint::FontMetrics fontMetrics;
     90         // op 1 and 2
     91         SkGlyph glyph;
     92         // op 3
     93         struct {
     94             SkGlyphID glyphId;
     95             size_t pathSize;
     96         };
     97     };
     98     ScalerContextRecDescriptor descriptor;
     99 };
    100 
    101 class RemoteScalerContextPassThread : public SkRemoteScalerContext {
    102 public:
    103     explicit RemoteScalerContextPassThread(int readFd, int writeFd)
    104         : fReadFd{readFd}
    105         , fWriteFd{writeFd} { }
    106     void generateFontMetrics(const SkTypefaceProxy& tf,
    107                              const SkScalerContextRec& rec,
    108                              SkPaint::FontMetrics* metrics) override {
    109         Op* op = this->createOp(0, tf, rec);
    110         write(fWriteFd, fBuffer, sizeof(*op));
    111         read(fReadFd, fBuffer, sizeof(fBuffer));
    112         memcpy(metrics, &op->fontMetrics, sizeof(op->fontMetrics));
    113         op->~Op();
    114     }
    115 
    116     void generateMetrics(const SkTypefaceProxy& tf,
    117                          const SkScalerContextRec& rec,
    118                          SkGlyph* glyph) override {
    119         Op* op = this->createOp(1, tf, rec);
    120         memcpy(&op->glyph, glyph, sizeof(*glyph));
    121         write(fWriteFd, fBuffer, sizeof(*op));
    122         read(fReadFd, fBuffer, sizeof(fBuffer));
    123         memcpy(glyph, &op->glyph, sizeof(op->glyph));
    124         op->~Op();
    125     }
    126 
    127     void generateImage(const SkTypefaceProxy& tf,
    128                        const SkScalerContextRec& rec,
    129                        const SkGlyph& glyph) override {
    130         Op* op = this->createOp(2, tf, rec);
    131         memcpy(&op->glyph, &glyph, sizeof(glyph));
    132         write(fWriteFd, fBuffer, sizeof(*op));
    133         read(fReadFd, fBuffer, sizeof(fBuffer));
    134         memcpy(glyph.fImage, fBuffer + sizeof(Op), glyph.rowBytes() * glyph.fHeight);
    135         op->~Op();
    136     }
    137 
    138     void generatePath(const SkTypefaceProxy& tf,
    139                       const SkScalerContextRec& rec,
    140                       SkGlyphID glyph, SkPath* path) override {
    141         Op* op = this->createOp(3, tf, rec);
    142         op->glyphId = glyph;
    143         write(fWriteFd, fBuffer, sizeof(*op));
    144         read(fReadFd, fBuffer, sizeof(fBuffer));
    145         path->readFromMemory(fBuffer + sizeof(Op), op->pathSize);
    146         op->~Op();
    147     }
    148 
    149 private:
    150     Op* createOp(uint32_t opID, const SkTypefaceProxy& tf,
    151                  const SkScalerContextRec& rec) {
    152         Op* op = new (fBuffer) Op(rec);
    153         op->op = opID;
    154         op->typeface_id = tf.fontID();
    155 
    156         return op;
    157     }
    158 
    159     const int fReadFd,
    160               fWriteFd;
    161     uint8_t   fBuffer[1024 * kPageSize];
    162 };
    163 
    164 static sk_sp<SkTypeface> gpu_from_renderer_by_ID(const void* buf, size_t len, void* ctx) {
    165     static std::unordered_map<SkFontID, sk_sp<SkTypefaceProxy>> mapIdToTypeface;
    166     WireTypeface wire;
    167     if (len >= sizeof(wire)) {
    168         memcpy(&wire, buf, sizeof(wire));
    169         auto i = mapIdToTypeface.find(wire.typeface_id);
    170         if (i == mapIdToTypeface.end()) {
    171 
    172             auto newTypeface = sk_make_sp<SkTypefaceProxy>(
    173                 wire.typeface_id,
    174                 wire.thread_id,
    175                 wire.style,
    176                 wire.is_fixed,
    177                 (SkRemoteScalerContext*)ctx);
    178 
    179             i = mapIdToTypeface.emplace_hint(i, wire.typeface_id, newTypeface);
    180         }
    181         return i->second;
    182     }
    183     SK_ABORT("Bad data");
    184     return nullptr;
    185 }
    186 
    187 std::unordered_map<SkFontID, sk_sp<SkTypeface>> gTypefaceMap;
    188 
    189 
    190 // TODO: Figure out how to manage the entries.
    191 std::unordered_map<ScalerContextRecDescriptor,
    192                    std::unique_ptr<SkScalerContext>,
    193                    ScalerContextRecDescriptor::Hash,
    194                    ScalerContextRecDescriptor::Equal>
    195     gScalerContextMap(16,
    196                       ScalerContextRecDescriptor::Hash(),
    197                       ScalerContextRecDescriptor::Equal());
    198 
    199 static SkScalerContext* scaler_context_from_op(Op* op) {
    200 
    201     SkScalerContext* sc;
    202     auto j = gScalerContextMap.find(op->descriptor);
    203     if (j != gScalerContextMap.end()) {
    204         sc = j->second.get();
    205     } else {
    206         auto i = gTypefaceMap.find(op->typeface_id);
    207         if (i == gTypefaceMap.end()) {
    208             std::cerr << "bad typeface id: " << op->typeface_id << std::endl;
    209             SK_ABORT("unknown type face");
    210         }
    211         auto tf = i->second;
    212         SkScalerContextEffects effects;
    213         auto mapSc = tf->createScalerContext(effects, &op->descriptor.desc(), false);
    214         sc = mapSc.get();
    215         gScalerContextMap.emplace_hint(j, op->descriptor, std::move(mapSc));
    216     }
    217     return sc;
    218 
    219 }
    220 
    221 static sk_sp<SkData> renderer_to_gpu_by_ID(SkTypeface* tf, void* ctx) {
    222     WireTypeface wire = {
    223             std::this_thread::get_id(),
    224             SkTypeface::UniqueID(tf),
    225             tf->fontStyle(),
    226             tf->isFixedPitch()
    227     };
    228     auto i = gTypefaceMap.find(SkTypeface::UniqueID(tf));
    229     if (i == gTypefaceMap.end()) {
    230         gTypefaceMap.insert({SkTypeface::UniqueID(tf), sk_ref_sp(tf)});
    231     }
    232     return SkData::MakeWithCopy(&wire, sizeof(wire));
    233 }
    234 
    235 static void final_draw(std::string outFilename,
    236                        SkDeserialProcs* procs,
    237                        uint8_t* picData,
    238                        size_t picSize) {
    239 
    240     auto pic = SkPicture::MakeFromData(picData, picSize, procs);
    241 
    242     auto cullRect = pic->cullRect();
    243     auto r = cullRect.round();
    244 
    245     auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
    246     auto c = s->getCanvas();
    247 
    248     auto picUnderTest = SkPicture::MakeFromData(picData, picSize, procs);
    249     auto start = std::chrono::high_resolution_clock::now();
    250 
    251     for (int i = 0; i < 40; i++) {
    252 
    253         c->drawPicture(picUnderTest);
    254     }
    255 
    256     auto end = std::chrono::high_resolution_clock::now();
    257 
    258     std::chrono::duration<double> elapsed_seconds = end-start;
    259 
    260     std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
    261 
    262     auto i = s->makeImageSnapshot();
    263     auto data = i->encodeToData();
    264     SkFILEWStream f(outFilename.c_str());
    265     f.write(data->data(), data->size());
    266 }
    267 
    268 static void gpu(int readFd, int writeFd) {
    269 
    270     size_t picSize = 0;
    271     read(readFd, &picSize, sizeof(picSize));
    272 
    273     static constexpr size_t kBufferSize = 10 * 1024 * kPageSize;
    274     std::unique_ptr<uint8_t[]> picBuffer{new uint8_t[kBufferSize]};
    275 
    276     size_t readSoFar = 0;
    277     while (readSoFar < picSize) {
    278         ssize_t readSize;
    279         if((readSize = read(readFd, &picBuffer[readSoFar], kBufferSize - readSoFar)) <= 0) {
    280             if (readSize == 0) return;
    281             err(1, "gpu pic read error %d", errno);
    282         }
    283         readSoFar += readSize;
    284     }
    285 
    286     SkDeserialProcs procs;
    287     std::unique_ptr<SkRemoteScalerContext> rsc{
    288             new RemoteScalerContextPassThread{readFd, writeFd}};
    289     procs.fTypefaceProc = gpu_from_renderer_by_ID;
    290     procs.fTypefaceCtx = rsc.get();
    291     final_draw("test.png", &procs, picBuffer.get(), picSize);
    292     /*
    293     auto pic = SkPicture::MakeFromData(picBuffer.get(), picSize, &procs);
    294 
    295     auto cullRect = pic->cullRect();
    296     auto r = cullRect.round();
    297     auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
    298 
    299     auto c = s->getCanvas();
    300     c->drawPicture(pic);
    301 
    302     auto i = s->makeImageSnapshot();
    303     auto data = i->encodeToData();
    304     SkFILEWStream f("test.png");
    305     f.write(data->data(), data->size());
    306      */
    307     close(writeFd);
    308     close(readFd);
    309 }
    310 
    311 static int renderer(const std::string& skpName, int readFd, int writeFd) {
    312     std::string prefix{"skps/"};
    313     std::string fileName{prefix + skpName + ".skp"};
    314 
    315     auto skp = SkData::MakeFromFileName(fileName.c_str());
    316     auto pic = SkPicture::MakeFromData(skp.get());
    317 
    318     bool toGpu = true;
    319 
    320     SkSerialProcs procs;
    321     if (toGpu) {
    322         procs.fTypefaceProc = renderer_to_gpu_by_ID;
    323     }
    324 
    325     auto stream = pic->serialize(&procs);
    326 
    327     std::cerr << "stream is " << stream->size() << " bytes long" << std::endl;
    328 
    329     size_t picSize = stream->size();
    330     uint8_t* picBuffer = (uint8_t*) stream->data();
    331 
    332     if (!toGpu) {
    333         final_draw("test-direct.png", nullptr, picBuffer, picSize);
    334         close(writeFd);
    335         close(readFd);
    336         return 0;
    337     }
    338 
    339     write(writeFd, &picSize, sizeof(picSize));
    340 
    341     size_t writeSoFar = 0;
    342     while (writeSoFar < picSize) {
    343         ssize_t writeSize = write(writeFd, &picBuffer[writeSoFar], picSize - writeSoFar);
    344         if (writeSize <= 0) {
    345             if (writeSize == 0) {
    346                 std::cerr << "Exit" << std::endl;
    347                 return 1;
    348             }
    349             perror("Can't write picture from render to GPU ");
    350             return 1;
    351         }
    352         writeSoFar += writeSize;
    353     }
    354     std::cerr << "Waiting for scaler context ops." << std::endl;
    355 
    356     static constexpr size_t kBufferSize = 1024 * kPageSize;
    357     std::unique_ptr<uint8_t[]> glyphBuffer{new uint8_t[kBufferSize]};
    358 
    359     Op* op = (Op*)glyphBuffer.get();
    360     while (true) {
    361         ssize_t size = read(readFd, glyphBuffer.get(), sizeof(*op));
    362         if (size <= 0) { std::cerr << "Exit op loop" << std::endl; break;}
    363         size_t writeSize = sizeof(*op);
    364 
    365             auto sc = scaler_context_from_op(op);
    366             switch (op->op) {
    367                 case 0: {
    368                     sc->getFontMetrics(&op->fontMetrics);
    369                     break;
    370                 }
    371                 case 1: {
    372                     sc->getMetrics(&op->glyph);
    373                     break;
    374                 }
    375                 case 2: {
    376                     // TODO: check for buffer overflow.
    377                     op->glyph.fImage = &glyphBuffer[sizeof(Op)];
    378                     sc->getImage(op->glyph);
    379                     writeSize += op->glyph.rowBytes() * op->glyph.fHeight;
    380                     break;
    381                 }
    382                 case 3: {
    383                     // TODO: check for buffer overflow.
    384                     SkPath path;
    385                     sc->getPath(op->glyphId, &path);
    386                     op->pathSize = path.writeToMemory(&glyphBuffer[sizeof(Op)]);
    387                     writeSize += op->pathSize;
    388                     break;
    389                 }
    390                 default:
    391                     SkASSERT("Bad op");
    392             }
    393         write(writeFd, glyphBuffer.get(), writeSize);
    394     }
    395 
    396     close(readFd);
    397     close(writeFd);
    398 
    399     std::cerr << "Returning from render" << std::endl;
    400 
    401     return 0;
    402 }
    403 
    404 enum direction : int {kRead = 0, kWrite = 1};
    405 
    406 static void start_gpu(int render_to_gpu[2], int gpu_to_render[2]) {
    407     std::cout << "gpu - Starting GPU" << std::endl;
    408     close(gpu_to_render[kRead]);
    409     close(render_to_gpu[kWrite]);
    410     gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
    411 }
    412 
    413 static void start_render(std::string& skpName, int render_to_gpu[2], int gpu_to_render[2]) {
    414     std::cout << "renderer - Starting Renderer" << std::endl;
    415     close(render_to_gpu[kRead]);
    416     close(gpu_to_render[kWrite]);
    417     renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
    418 }
    419 
    420 int main(int argc, char** argv) {
    421     std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"desk_nytimes"};
    422     printf("skp: %s\n", skpName.c_str());
    423 
    424     int render_to_gpu[2],
    425         gpu_to_render[2];
    426 
    427     int r = pipe(render_to_gpu);
    428     if (r < 0) {
    429         perror("Can't write picture from render to GPU ");
    430         return 1;
    431     }
    432     r = pipe(gpu_to_render);
    433     if (r < 0) {
    434         perror("Can't write picture from render to GPU ");
    435         return 1;
    436     }
    437 
    438     bool useProcess = true;
    439 
    440     if (useProcess) {
    441         pid_t child = fork();
    442         SkGraphics::Init();
    443 
    444         if (child == 0) {
    445             start_render(skpName, render_to_gpu, gpu_to_render);
    446         } else {
    447             start_gpu(render_to_gpu, gpu_to_render);
    448             std::cerr << "Waiting for renderer." << std::endl;
    449             waitpid(child, nullptr, 0);
    450         }
    451     } else {
    452         SkGraphics::Init();
    453         std::thread(gpu, render_to_gpu[kRead], gpu_to_render[kWrite]).detach();
    454         renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
    455     }
    456 
    457     return 0;
    458 }
    459 
    460