blob: fbc2480278e344b37e36a37b65b3bc20a4e592b6 [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
21#include <ctype.h>
22#include <err.h>
23#include <memory>
24#include <stdio.h>
25#include <thread>
26#include <iostream>
27#include <unordered_map>
28
29#include <sys/types.h>
30#include <sys/wait.h>
31#include <unistd.h>
32#include <sys/mman.h>
33#include "SkTypeface_remote.h"
34
35static const size_t kPageSize = 4096;
36
37struct WireTypeface {
38 std::thread::id thread_id;
39 SkFontID typeface_id;
40 SkFontStyle style;
41 bool is_fixed;
42};
43
44class Op {
45public:
46 Op() {}
47 int32_t op;
48 SkFontID typeface_id;
49 union {
50 // op 0
51 SkPaint::FontMetrics fontMetrics;
52 // op 1 and 2
53 SkGlyph glyph;
54 // op 3
55 struct {
56 SkGlyphID glyphId;
57 size_t pathSize;
58 };
59 };
60 // The system only passes descriptors without effects. That is why it uses a fixed size
61 // descriptor. storageFor is needed because some of the constructors below are private.
62 template <typename T>
63 using storageFor = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
64 struct {
65 storageFor<SkDescriptor> dummy1;
66 storageFor<SkDescriptor::Entry> dummy2;
67 storageFor<SkScalerContextRec> dummy3;
68 } descriptor;
69};
70
71class RemoteScalerContextPassThread : public SkRemoteScalerContext {
72public:
73 explicit RemoteScalerContextPassThread(int readFd, int writeFd)
74 : fReadFd{readFd}
75 , fWriteFd{writeFd} { }
76 void generateFontMetrics(const SkTypefaceProxy& tf,
77 const SkScalerContextRec& rec,
78 SkPaint::FontMetrics* metrics) override {
79 Op* op = this->createOp(0, tf, rec);
80 write(fWriteFd, fBuffer, sizeof(*op));
81 ssize_t readSize = read(fReadFd, fBuffer, sizeof(fBuffer));
82 std::cerr << "gpu - op 0 read size: " << readSize << std::endl;
83 memcpy(metrics, &op->fontMetrics, sizeof(op->fontMetrics));
84 op->~Op();
85 }
86
87 void generateMetrics(const SkTypefaceProxy& tf,
88 const SkScalerContextRec& rec,
89 SkGlyph* glyph) override {
90 Op* op = this->createOp(1, tf, rec);
91 memcpy(&op->glyph, glyph, sizeof(*glyph));
92 write(fWriteFd, fBuffer, sizeof(*op));
93 read(fReadFd, fBuffer, sizeof(fBuffer));
94 memcpy(glyph, &op->glyph, sizeof(op->glyph));
95 op->~Op();
96 }
97
98 void generateImage(const SkTypefaceProxy& tf,
99 const SkScalerContextRec& rec,
100 const SkGlyph& glyph) override {
101 Op* op = this->createOp(2, tf, rec);
102 memcpy(&op->glyph, &glyph, sizeof(glyph));
103 write(fWriteFd, fBuffer, sizeof(*op));
104 read(fReadFd, fBuffer, sizeof(fBuffer));
105 //memcpy((SkGlyph *)&glyph, &op->glyph, sizeof(op->glyph));
106 //((SkGlyph*)&glyph)->fImage = oldImage;
107 std::cerr << "rb: " << glyph.rowBytes() << " h: " << glyph.fHeight << std::endl;
108 memcpy(glyph.fImage, fBuffer + sizeof(Op), glyph.rowBytes() * glyph.fHeight);
109 op->~Op();
110 }
111
112 void generatePath(const SkTypefaceProxy& tf,
113 const SkScalerContextRec& rec,
114 SkGlyphID glyph, SkPath* path) override {
115 Op* op = this->createOp(3, tf, rec);
116 op->glyphId = glyph;
117 write(fWriteFd, fBuffer, sizeof(*op));
118 read(fReadFd, fBuffer, sizeof(fBuffer));
119 path->readFromMemory(fBuffer + sizeof(Op), op->pathSize);
120 op->~Op();
121 }
122
123private:
124 Op* createOp(uint32_t opID, const SkTypefaceProxy& tf,
125 const SkScalerContextRec& rec) {
126 Op* op = new (fBuffer) Op();
127 op->op = opID;
128 op->typeface_id = tf.fontID();
129
130 SkASSERT(SkScalerContext::CheckBufferSizeForRec(
131 rec, SkScalerContextEffects{}, sizeof(op->descriptor)));
132
133 SkScalerContext::DescriptorBufferGiveRec(rec, &op->descriptor);
134
135 return op;
136 }
137
138 const int fReadFd,
139 fWriteFd;
140 uint8_t fBuffer[1024 * kPageSize];
141};
142
143static sk_sp<SkTypeface> gpu_from_renderer_by_ID(const void* buf, size_t len, void* ctx) {
144 WireTypeface wire;
145 std::cerr << "gpu - typeface from rendere size: " << len << std::endl;
146 if (len >= sizeof(wire)) {
147 memcpy(&wire, buf, sizeof(wire));
148 std::cerr << wire.thread_id << " " << wire.typeface_id << std::endl;
149 return sk_sp<SkTypeface>(
150 new SkTypefaceProxy(
151 wire.typeface_id,
152 wire.thread_id,
153 wire.style,
154 wire.is_fixed,
155 (SkRemoteScalerContext*) ctx));
156 }
157 return nullptr;
158}
159
160std::unordered_map<SkFontID, sk_sp<SkTypeface>> gTypefaceMap;
161
162
163static std::unique_ptr<SkScalerContext> scaler_context_from_op(Op* op) {
164
165 auto i = gTypefaceMap.find(op->typeface_id);
166 if (i == gTypefaceMap.end()) {
167 std::cerr << "bad typeface id: " << op->typeface_id << std::endl;
168 SK_ABORT("unknown type face");
169 }
170 auto tf = i->second;
171 std::cerr << "ops - got typeface: " << i->first << " , " << tf.get() << std::endl;
172 SkScalerContextEffects effects;
173 auto sc = tf->createScalerContext(effects, (SkDescriptor *)&op->descriptor, false);
174 std::cerr << "ops - created sc " << std::endl;
175 return sc;
176
177}
178
179static sk_sp<SkData> renderer_to_gpu_by_ID(SkTypeface* tf, void* ctx) {
180 WireTypeface wire = {
181 std::this_thread::get_id(),
182 SkTypeface::UniqueID(tf),
183 tf->fontStyle(),
184 tf->isFixedPitch()
185 };
186 auto i = gTypefaceMap.find(SkTypeface::UniqueID(tf));
187 if (i == gTypefaceMap.end()) {
188 std::cerr << "font id table - inserting: " << SkTypeface::UniqueID(tf) << std::endl;
189 gTypefaceMap.insert({SkTypeface::UniqueID(tf), sk_ref_sp(tf)});
190 }
191 return SkData::MakeWithCopy(&wire, sizeof(wire));
192}
193
194static void gpu(int readFd, int writeFd) {
195
196 size_t picSize = 0;
197 read(readFd, &picSize, sizeof(picSize));
198
199 std::cerr << "gpu - reading pic size: " << picSize << std::endl;
200 static constexpr size_t kBufferSize = 10 * 1024 * kPageSize;
201 std::unique_ptr<uint8_t[]> picBuffer{new uint8_t[kBufferSize]};
202
203 size_t readSoFar = 0;
204 while (readSoFar < picSize) {
205 ssize_t readSize;
206 if((readSize = read(readFd, &picBuffer[readSoFar], kBufferSize - readSoFar)) <= 0) {
207 if (readSize == 0) return;
208 err(1, "gpu pic read error %d", errno);
209 }
210 readSoFar += readSize;
211 //std::cerr << "gpu - recieved so far: " << readSoFar << std::endl;
212 }
213
214 std::cerr << "gpu - Receiving picture" << std::endl;
215 SkDeserialProcs procs;
216 std::unique_ptr<SkRemoteScalerContext> rsc{
217 new RemoteScalerContextPassThread{readFd, writeFd}};
218 procs.fTypefaceProc = gpu_from_renderer_by_ID;
219 procs.fTypefaceCtx = rsc.get();
220 auto pic = SkPicture::MakeFromData(picBuffer.get(), picSize, &procs);
221
222 auto cullRect = pic->cullRect();
223 auto r = cullRect.round();
224 auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
225
226 auto c = s->getCanvas();
227 c->drawPicture(pic);
228
229 std::cerr << "gpu - output picture" << std::endl;
230 auto i = s->makeImageSnapshot();
231 auto data = i->encodeToData();
232 SkFILEWStream f("test.png");
233 f.write(data->data(), data->size());
234 close(writeFd);
235 close(readFd);
236
237}
238
239static int renderer(const std::string& skpName, int readFd, int writeFd) {
240 std::string prefix{"skps/"};
241 std::string fileName{prefix + skpName + ".skp"};
242 std::cerr << "Reading skp: " << fileName << std::endl;
243
244 auto skp = SkData::MakeFromFileName(fileName.c_str());
245 auto pic = SkPicture::MakeFromData(skp.get());
246
247 SkSerialProcs procs;
248 procs.fTypefaceProc = renderer_to_gpu_by_ID;
249 auto stream = pic->serialize(&procs);
250
251 std::cerr << "stream is " << stream->size() << " bytes long" << std::endl;
252
253 std::cerr << "render - Sending stream." << std::endl;
254
255 size_t picSize = stream->size();
256 uint8_t* picBuffer = (uint8_t*) stream->data();
257 write(writeFd, &picSize, sizeof(picSize));
258
259 size_t writeSoFar = 0;
260 while (writeSoFar < picSize) {
261 ssize_t writeSize = write(writeFd, &picBuffer[writeSoFar], picSize - writeSoFar);
262 std::cerr << "renderer - bytes written: " << writeSize << std::endl;
263 if (writeSize <= 0) {
264 if (writeSize == 0) {
265 std::cerr << "Exit" << std::endl;
266 return 1;
267 }
268 perror("Can't write picture from render to GPU ");
269 return 1;
270 }
271 writeSoFar += writeSize;
272 }
273 std::cerr << "Waiting for scaler context ops." << std::endl;
274
275 static constexpr size_t kBufferSize = 1024 * kPageSize;
276 std::unique_ptr<uint8_t[]> glyphBuffer{new uint8_t[kBufferSize]};
277
278 Op* op = (Op*)glyphBuffer.get();
279 while (true) {
280 ssize_t size = read(readFd, glyphBuffer.get(), sizeof(*op));
281 if (size <= 0) { std::cerr << "Exit op loop" << std::endl; break;}
282 size_t writeSize = sizeof(*op);
283 std::cerr << "op: " << op << " op->op: " << op->op << std::endl;
284
285 auto sc = scaler_context_from_op(op);
286 switch (op->op) {
287 case 0: {
288 sc->getFontMetrics(&op->fontMetrics);
289 break;
290 }
291 case 1: {
292 sc->getMetrics(&op->glyph);
293 break;
294 }
295 case 2: {
296 // TODO: check for buffer overflow.
297 op->glyph.fImage = &glyphBuffer[sizeof(Op)];
298 sc->getImage(op->glyph);
299 writeSize += op->glyph.rowBytes() * op->glyph.fHeight;
300 break;
301 }
302 case 3: {
303 // TODO: check for buffer overflow.
304 SkPath path;
305 sc->getPath(op->glyphId, &path);
306 op->pathSize = path.writeToMemory(&glyphBuffer[sizeof(Op)]);
307 writeSize += op->pathSize;
308 break;
309 }
310 default:
311 SkASSERT("Bad op");
312 }
313 std::cerr << "ops - writing" << std::endl;
314 ssize_t written = write(writeFd, glyphBuffer.get(), writeSize);
315 std::cerr << " opss - writing : " << writeSize << " written: " << written << std::endl;
316 }
317
318 close(readFd);
319 close(writeFd);
320
321 std::cerr << "Returning from render" << std::endl;
322
323 return 0;
324}
325
326int main(int argc, char** argv) {
327 std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"desk_nytimes"};
328 printf("skp: %s\n", skpName.c_str());
329
330 int render_to_gpu[2],
331 gpu_to_render[2];
332
333 enum direction : int {kRead = 0, kWrite = 1};
334
335 int r = pipe(render_to_gpu);
336 if (r < 0) {
337 perror("Can't write picture from render to GPU ");
338 return 1;
339 }
340 r = pipe(gpu_to_render);
341 if (r < 0) {
342 perror("Can't write picture from render to GPU ");
343 return 1;
344 }
345
346 pid_t child = fork();
347 SkGraphics::Init();
348
349 if (child == 0) {
350 // The child - renderer
351 // Close unused pipe ends.
352 close(render_to_gpu[kRead]);
353 close(gpu_to_render[kWrite]);
354 std::cerr << "Starting renderer" << std::endl;
355 printf("skp: %s\n", skpName.c_str());
356 renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
357 //gpu(gpu_to_render[kRead], render_to_gpu[kWrite]);
358 } else {
359 // The parent - GPU
360 // Close unused pipe ends.
361 std::cerr << "child id - " << child << std::endl;
362 close(gpu_to_render[kRead]);
363 close(render_to_gpu[kWrite]);
364 gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
365 //renderer(skpName, render_to_gpu[kRead], gpu_to_render[kWrite]);
366
367
368 std::cerr << "Waiting for renderer." << std::endl;
369 waitpid(child, nullptr, 0);
370 }
371
372
373 return 0;
374}
375