blob: 4fbec34fec74fa2c7b2750f64b02d2040c0e998c [file] [log] [blame]
Mike Kleina8a51ce2018-01-09 12:34:11 -05001/*
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
Herb Derby4f505f92018-01-09 12:34:11 -050021#include <chrono>
Mike Kleina8a51ce2018-01-09 12:34:11 -050022#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
36static const size_t kPageSize = 4096;
37
38struct WireTypeface {
39 std::thread::id thread_id;
40 SkFontID typeface_id;
41 SkFontStyle style;
42 bool is_fixed;
43};
44
Herb Derby4f505f92018-01-09 12:34:11 -050045class ScalerContextRecDescriptor {
46public:
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
70private:
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
Mike Kleina8a51ce2018-01-09 12:34:11 -050082class Op {
83public:
Herb Derby4f505f92018-01-09 12:34:11 -050084 explicit Op(const SkScalerContextRec& rec) : descriptor{rec} {}
Mike Kleina8a51ce2018-01-09 12:34:11 -050085 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 };
Herb Derby4f505f92018-01-09 12:34:11 -050098 ScalerContextRecDescriptor descriptor;
Mike Kleina8a51ce2018-01-09 12:34:11 -050099};
100
101class RemoteScalerContextPassThread : public SkRemoteScalerContext {
102public:
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));
Herb Derby4f505f92018-01-09 12:34:11 -0500111 read(fReadFd, fBuffer, sizeof(fBuffer));
Mike Kleina8a51ce2018-01-09 12:34:11 -0500112 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((SkGlyph *)&glyph, &op->glyph, sizeof(op->glyph));
135 //((SkGlyph*)&glyph)->fImage = oldImage;
Mike Kleina8a51ce2018-01-09 12:34:11 -0500136 memcpy(glyph.fImage, fBuffer + sizeof(Op), glyph.rowBytes() * glyph.fHeight);
137 op->~Op();
138 }
139
140 void generatePath(const SkTypefaceProxy& tf,
141 const SkScalerContextRec& rec,
142 SkGlyphID glyph, SkPath* path) override {
143 Op* op = this->createOp(3, tf, rec);
144 op->glyphId = glyph;
145 write(fWriteFd, fBuffer, sizeof(*op));
146 read(fReadFd, fBuffer, sizeof(fBuffer));
147 path->readFromMemory(fBuffer + sizeof(Op), op->pathSize);
148 op->~Op();
149 }
150
151private:
152 Op* createOp(uint32_t opID, const SkTypefaceProxy& tf,
153 const SkScalerContextRec& rec) {
Herb Derby4f505f92018-01-09 12:34:11 -0500154 Op* op = new (fBuffer) Op(rec);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500155 op->op = opID;
156 op->typeface_id = tf.fontID();
157
Mike Kleina8a51ce2018-01-09 12:34:11 -0500158 return op;
159 }
160
161 const int fReadFd,
162 fWriteFd;
163 uint8_t fBuffer[1024 * kPageSize];
164};
165
166static sk_sp<SkTypeface> gpu_from_renderer_by_ID(const void* buf, size_t len, void* ctx) {
167 WireTypeface wire;
Mike Kleina8a51ce2018-01-09 12:34:11 -0500168 if (len >= sizeof(wire)) {
169 memcpy(&wire, buf, sizeof(wire));
Mike Kleina8a51ce2018-01-09 12:34:11 -0500170 return sk_sp<SkTypeface>(
171 new SkTypefaceProxy(
172 wire.typeface_id,
173 wire.thread_id,
174 wire.style,
175 wire.is_fixed,
176 (SkRemoteScalerContext*) ctx));
177 }
178 return nullptr;
179}
180
181std::unordered_map<SkFontID, sk_sp<SkTypeface>> gTypefaceMap;
182
183
Herb Derby4f505f92018-01-09 12:34:11 -0500184// TODO: Figure out how to manage the entries.
185std::unordered_map<ScalerContextRecDescriptor,
186 std::unique_ptr<SkScalerContext>,
187 ScalerContextRecDescriptor::Hash,
188 ScalerContextRecDescriptor::Equal>
189 gScalerContextMap(16,
190 ScalerContextRecDescriptor::Hash(),
191 ScalerContextRecDescriptor::Equal());
Mike Kleina8a51ce2018-01-09 12:34:11 -0500192
Herb Derby4f505f92018-01-09 12:34:11 -0500193static SkScalerContext* scaler_context_from_op(Op* op) {
194
195 SkScalerContext* sc;
196 auto j = gScalerContextMap.find(op->descriptor);
197 if (j != gScalerContextMap.end()) {
198 sc = j->second.get();
199 } else {
200 auto i = gTypefaceMap.find(op->typeface_id);
201 if (i == gTypefaceMap.end()) {
202 std::cerr << "bad typeface id: " << op->typeface_id << std::endl;
203 SK_ABORT("unknown type face");
204 }
205 auto tf = i->second;
206 SkScalerContextEffects effects;
207 auto mapSc = tf->createScalerContext(effects, &op->descriptor.desc(), false);
208 sc = mapSc.get();
209 gScalerContextMap.emplace_hint(j, op->descriptor, std::move(mapSc));
Mike Kleina8a51ce2018-01-09 12:34:11 -0500210 }
Mike Kleina8a51ce2018-01-09 12:34:11 -0500211 return sc;
212
213}
214
215static sk_sp<SkData> renderer_to_gpu_by_ID(SkTypeface* tf, void* ctx) {
216 WireTypeface wire = {
217 std::this_thread::get_id(),
218 SkTypeface::UniqueID(tf),
219 tf->fontStyle(),
220 tf->isFixedPitch()
221 };
222 auto i = gTypefaceMap.find(SkTypeface::UniqueID(tf));
223 if (i == gTypefaceMap.end()) {
Mike Kleina8a51ce2018-01-09 12:34:11 -0500224 gTypefaceMap.insert({SkTypeface::UniqueID(tf), sk_ref_sp(tf)});
225 }
226 return SkData::MakeWithCopy(&wire, sizeof(wire));
227}
228
Herb Derby4f505f92018-01-09 12:34:11 -0500229static void final_draw(std::string outFilename,
230 SkDeserialProcs* procs,
231 uint8_t* picData,
232 size_t picSize) {
233 auto start = std::chrono::high_resolution_clock::now();
234
235 auto pic = SkPicture::MakeFromData(picData, picSize, procs);
236
237 auto cullRect = pic->cullRect();
238 auto r = cullRect.round();
239 auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
240
241 auto c = s->getCanvas();
242 c->drawPicture(pic);
243
244 auto end = std::chrono::high_resolution_clock::now();
245
246 std::chrono::duration<double> elapsed_seconds = end-start;
247
248 std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
249
250 auto i = s->makeImageSnapshot();
251 auto data = i->encodeToData();
252 SkFILEWStream f(outFilename.c_str());
253 f.write(data->data(), data->size());
254}
255
Mike Kleina8a51ce2018-01-09 12:34:11 -0500256static void gpu(int readFd, int writeFd) {
257
258 size_t picSize = 0;
259 read(readFd, &picSize, sizeof(picSize));
260
Mike Kleina8a51ce2018-01-09 12:34:11 -0500261 static constexpr size_t kBufferSize = 10 * 1024 * kPageSize;
262 std::unique_ptr<uint8_t[]> picBuffer{new uint8_t[kBufferSize]};
263
264 size_t readSoFar = 0;
265 while (readSoFar < picSize) {
266 ssize_t readSize;
267 if((readSize = read(readFd, &picBuffer[readSoFar], kBufferSize - readSoFar)) <= 0) {
268 if (readSize == 0) return;
269 err(1, "gpu pic read error %d", errno);
270 }
271 readSoFar += readSize;
Mike Kleina8a51ce2018-01-09 12:34:11 -0500272 }
273
Mike Kleina8a51ce2018-01-09 12:34:11 -0500274 SkDeserialProcs procs;
275 std::unique_ptr<SkRemoteScalerContext> rsc{
276 new RemoteScalerContextPassThread{readFd, writeFd}};
277 procs.fTypefaceProc = gpu_from_renderer_by_ID;
278 procs.fTypefaceCtx = rsc.get();
Herb Derby4f505f92018-01-09 12:34:11 -0500279 final_draw("test.png", &procs, picBuffer.get(), picSize);
280 /*
Mike Kleina8a51ce2018-01-09 12:34:11 -0500281 auto pic = SkPicture::MakeFromData(picBuffer.get(), picSize, &procs);
282
283 auto cullRect = pic->cullRect();
284 auto r = cullRect.round();
285 auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
286
287 auto c = s->getCanvas();
288 c->drawPicture(pic);
289
Mike Kleina8a51ce2018-01-09 12:34:11 -0500290 auto i = s->makeImageSnapshot();
291 auto data = i->encodeToData();
292 SkFILEWStream f("test.png");
293 f.write(data->data(), data->size());
Herb Derby4f505f92018-01-09 12:34:11 -0500294 */
Mike Kleina8a51ce2018-01-09 12:34:11 -0500295 close(writeFd);
296 close(readFd);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500297}
298
299static int renderer(const std::string& skpName, int readFd, int writeFd) {
300 std::string prefix{"skps/"};
301 std::string fileName{prefix + skpName + ".skp"};
Mike Kleina8a51ce2018-01-09 12:34:11 -0500302
303 auto skp = SkData::MakeFromFileName(fileName.c_str());
304 auto pic = SkPicture::MakeFromData(skp.get());
305
Herb Derby4f505f92018-01-09 12:34:11 -0500306 bool toGpu = true;
307
Mike Kleina8a51ce2018-01-09 12:34:11 -0500308 SkSerialProcs procs;
Herb Derby4f505f92018-01-09 12:34:11 -0500309 if (toGpu) {
310 procs.fTypefaceProc = renderer_to_gpu_by_ID;
311 }
312
Mike Kleina8a51ce2018-01-09 12:34:11 -0500313 auto stream = pic->serialize(&procs);
314
315 std::cerr << "stream is " << stream->size() << " bytes long" << std::endl;
316
Mike Kleina8a51ce2018-01-09 12:34:11 -0500317 size_t picSize = stream->size();
318 uint8_t* picBuffer = (uint8_t*) stream->data();
Herb Derby4f505f92018-01-09 12:34:11 -0500319
320 if (!toGpu) {
321 final_draw("test-direct.png", nullptr, picBuffer, picSize);
322 close(writeFd);
323 close(readFd);
324 return 0;
325 }
326
Mike Kleina8a51ce2018-01-09 12:34:11 -0500327 write(writeFd, &picSize, sizeof(picSize));
328
329 size_t writeSoFar = 0;
330 while (writeSoFar < picSize) {
331 ssize_t writeSize = write(writeFd, &picBuffer[writeSoFar], picSize - writeSoFar);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500332 if (writeSize <= 0) {
333 if (writeSize == 0) {
334 std::cerr << "Exit" << std::endl;
335 return 1;
336 }
337 perror("Can't write picture from render to GPU ");
338 return 1;
339 }
340 writeSoFar += writeSize;
341 }
342 std::cerr << "Waiting for scaler context ops." << std::endl;
343
344 static constexpr size_t kBufferSize = 1024 * kPageSize;
345 std::unique_ptr<uint8_t[]> glyphBuffer{new uint8_t[kBufferSize]};
346
347 Op* op = (Op*)glyphBuffer.get();
348 while (true) {
349 ssize_t size = read(readFd, glyphBuffer.get(), sizeof(*op));
350 if (size <= 0) { std::cerr << "Exit op loop" << std::endl; break;}
351 size_t writeSize = sizeof(*op);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500352
353 auto sc = scaler_context_from_op(op);
354 switch (op->op) {
355 case 0: {
356 sc->getFontMetrics(&op->fontMetrics);
357 break;
358 }
359 case 1: {
360 sc->getMetrics(&op->glyph);
361 break;
362 }
363 case 2: {
364 // TODO: check for buffer overflow.
365 op->glyph.fImage = &glyphBuffer[sizeof(Op)];
366 sc->getImage(op->glyph);
367 writeSize += op->glyph.rowBytes() * op->glyph.fHeight;
368 break;
369 }
370 case 3: {
371 // TODO: check for buffer overflow.
372 SkPath path;
373 sc->getPath(op->glyphId, &path);
374 op->pathSize = path.writeToMemory(&glyphBuffer[sizeof(Op)]);
375 writeSize += op->pathSize;
376 break;
377 }
378 default:
379 SkASSERT("Bad op");
380 }
Herb Derby4f505f92018-01-09 12:34:11 -0500381 write(writeFd, glyphBuffer.get(), writeSize);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500382 }
383
384 close(readFd);
385 close(writeFd);
386
387 std::cerr << "Returning from render" << std::endl;
388
389 return 0;
390}
391
392int main(int argc, char** argv) {
393 std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"desk_nytimes"};
394 printf("skp: %s\n", skpName.c_str());
395
396 int render_to_gpu[2],
397 gpu_to_render[2];
398
399 enum direction : int {kRead = 0, kWrite = 1};
400
401 int r = pipe(render_to_gpu);
402 if (r < 0) {
403 perror("Can't write picture from render to GPU ");
404 return 1;
405 }
406 r = pipe(gpu_to_render);
407 if (r < 0) {
408 perror("Can't write picture from render to GPU ");
409 return 1;
410 }
411
412 pid_t child = fork();
413 SkGraphics::Init();
414
415 if (child == 0) {
416 // The child - renderer
417 // Close unused pipe ends.
418 close(render_to_gpu[kRead]);
419 close(gpu_to_render[kWrite]);
420 std::cerr << "Starting renderer" << std::endl;
421 printf("skp: %s\n", skpName.c_str());
Herb Derby4f505f92018-01-09 12:34:11 -0500422 //renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
423 gpu(gpu_to_render[kRead], render_to_gpu[kWrite]);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500424 } else {
425 // The parent - GPU
426 // Close unused pipe ends.
427 std::cerr << "child id - " << child << std::endl;
428 close(gpu_to_render[kRead]);
429 close(render_to_gpu[kWrite]);
Herb Derby4f505f92018-01-09 12:34:11 -0500430 //gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
431 renderer(skpName, render_to_gpu[kRead], gpu_to_render[kWrite]);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500432
433 std::cerr << "Waiting for renderer." << std::endl;
434 waitpid(child, nullptr, 0);
435 }
436
Mike Kleina8a51ce2018-01-09 12:34:11 -0500437 return 0;
438}
439