Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 21 | #include <chrono> |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 82 | class Op { |
| 83 | public: |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 84 | explicit Op(const SkScalerContextRec& rec) : descriptor{rec} {} |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | }; |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 98 | ScalerContextRecDescriptor descriptor; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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)); |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 111 | read(fReadFd, fBuffer, sizeof(fBuffer)); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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)); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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) { |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 152 | Op* op = new (fBuffer) Op(rec); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 153 | op->op = opID; |
| 154 | op->typeface_id = tf.fontID(); |
| 155 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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) { |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 165 | static std::unordered_map<SkFontID, sk_sp<SkTypefaceProxy>> mapIdToTypeface; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 166 | WireTypeface wire; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 167 | if (len >= sizeof(wire)) { |
| 168 | memcpy(&wire, buf, sizeof(wire)); |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 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; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 182 | } |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 183 | SK_ABORT("Bad data"); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 184 | return nullptr; |
| 185 | } |
| 186 | |
| 187 | std::unordered_map<SkFontID, sk_sp<SkTypeface>> gTypefaceMap; |
| 188 | |
| 189 | |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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()); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 198 | |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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)); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 216 | } |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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()) { |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 230 | gTypefaceMap.insert({SkTypeface::UniqueID(tf), sk_ref_sp(tf)}); |
| 231 | } |
| 232 | return SkData::MakeWithCopy(&wire, sizeof(wire)); |
| 233 | } |
| 234 | |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 235 | static void final_draw(std::string outFilename, |
| 236 | SkDeserialProcs* procs, |
| 237 | uint8_t* picData, |
| 238 | size_t picSize) { |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 239 | |
| 240 | auto pic = SkPicture::MakeFromData(picData, picSize, procs); |
| 241 | |
| 242 | auto cullRect = pic->cullRect(); |
| 243 | auto r = cullRect.round(); |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 244 | |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 245 | auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height()); |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 246 | auto c = s->getCanvas(); |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 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 | } |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 268 | static void gpu(int readFd, int writeFd) { |
| 269 | |
| 270 | size_t picSize = 0; |
| 271 | read(readFd, &picSize, sizeof(picSize)); |
| 272 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 284 | } |
| 285 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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(); |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 291 | final_draw("test.png", &procs, picBuffer.get(), picSize); |
| 292 | /* |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 302 | auto i = s->makeImageSnapshot(); |
| 303 | auto data = i->encodeToData(); |
| 304 | SkFILEWStream f("test.png"); |
| 305 | f.write(data->data(), data->size()); |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 306 | */ |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 307 | close(writeFd); |
| 308 | close(readFd); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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"}; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 314 | |
| 315 | auto skp = SkData::MakeFromFileName(fileName.c_str()); |
| 316 | auto pic = SkPicture::MakeFromData(skp.get()); |
| 317 | |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 318 | bool toGpu = true; |
| 319 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 320 | SkSerialProcs procs; |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 321 | if (toGpu) { |
| 322 | procs.fTypefaceProc = renderer_to_gpu_by_ID; |
| 323 | } |
| 324 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 325 | auto stream = pic->serialize(&procs); |
| 326 | |
| 327 | std::cerr << "stream is " << stream->size() << " bytes long" << std::endl; |
| 328 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 329 | size_t picSize = stream->size(); |
| 330 | uint8_t* picBuffer = (uint8_t*) stream->data(); |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 331 | |
| 332 | if (!toGpu) { |
| 333 | final_draw("test-direct.png", nullptr, picBuffer, picSize); |
| 334 | close(writeFd); |
| 335 | close(readFd); |
| 336 | return 0; |
| 337 | } |
| 338 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | } |
Herb Derby | 4f505f9 | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 393 | write(writeFd, glyphBuffer.get(), writeSize); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 394 | } |
| 395 | |
| 396 | close(readFd); |
| 397 | close(writeFd); |
| 398 | |
| 399 | std::cerr << "Returning from render" << std::endl; |
| 400 | |
| 401 | return 0; |
| 402 | } |
| 403 | |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 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 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 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 | |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 438 | bool useProcess = true; |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 439 | |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 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 | } |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 451 | } else { |
Herb Derby | d08c682 | 2018-01-09 12:34:11 -0500 | [diff] [blame^] | 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]); |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 455 | } |
| 456 | |
Mike Klein | a8a51ce | 2018-01-09 12:34:11 -0500 | [diff] [blame] | 457 | return 0; |
| 458 | } |
| 459 | |