blob: 8fc96cadb855ade13e47a151372f51489d95fc34 [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
Herb Derby4f505f92018-01-09 12:34:11 -05008#include <chrono>
Mike Kleina8a51ce2018-01-09 12:34:11 -05009#include <err.h>
Mike Kleina8a51ce2018-01-09 12:34:11 -050010#include <iostream>
Herb Derby97be88f2018-03-21 16:23:49 -040011#include <memory>
12#include <string>
Mike Kleina8a51ce2018-01-09 12:34:11 -050013#include <sys/types.h>
Herb Derby67c47f22018-02-07 17:47:59 -050014#include <sys/uio.h>
Mike Kleina8a51ce2018-01-09 12:34:11 -050015#include <sys/wait.h>
Herb Derby97be88f2018-03-21 16:23:49 -040016#include <thread>
Mike Kleina8a51ce2018-01-09 12:34:11 -050017#include <unistd.h>
Herb Derby97be88f2018-03-21 16:23:49 -040018
Herb Derbyb2922f62018-01-26 16:47:54 -050019#include "SkRemoteGlyphCache.h"
Herb Derby97be88f2018-03-21 16:23:49 -040020#include "SkGraphics.h"
21#include "SkSurface.h"
Mike Kleina8a51ce2018-01-09 12:34:11 -050022
Herb Derby97be88f2018-03-21 16:23:49 -040023static std::string gSkpName;
Herb Derby9d021822018-02-02 12:54:55 -050024static bool gUseGpu = true;
25static bool gPurgeFontCaches = true;
26static bool gUseProcess = true;
27
Herb Derby209a5f32018-04-05 16:57:25 -040028static bool write_SkData(int fd, const SkData& data) {
29 size_t size = data.size();
30 ssize_t bytesWritten = ::write(fd, &size, sizeof(size));
31 if (bytesWritten < 0) {
32 err(1,"Failed write %zu", size);
33 return false;
Herb Derby67c47f22018-02-07 17:47:59 -050034 }
35
Herb Derby209a5f32018-04-05 16:57:25 -040036 bytesWritten = ::write(fd, data.data(), data.size());
37 if (bytesWritten < 0) {
38 err(1,"Failed write %zu", size);
39 return false;
40 }
41
42 return true;
43}
44
45static sk_sp<SkData> read_SkData(int fd) {
46
47 size_t size;
48 ssize_t readSize = ::read(fd, &size, sizeof(size));
49 if (readSize <= 0) {
Herb Derby97be88f2018-03-21 16:23:49 -040050 if (readSize < 0) {
Herb Derby209a5f32018-04-05 16:57:25 -040051 err(1, "Failed read %zu", size);
Herb Derby67c47f22018-02-07 17:47:59 -050052 }
Herb Derby209a5f32018-04-05 16:57:25 -040053 return nullptr;
Herb Derby67c47f22018-02-07 17:47:59 -050054 }
55
Herb Derby209a5f32018-04-05 16:57:25 -040056 auto out = SkData::MakeUninitialized(size);
57 auto data = (uint8_t*)out->data();
58
59 size_t totalRead = 0;
60 while (totalRead < size) {
61 ssize_t sizeRead;
62 sizeRead = ::read(fd, &data[totalRead], size - totalRead);
63 if (sizeRead <= 0) {
64 if (readSize < 0) {
65 err(1, "Failed read %zu", size);
66 }
67 return nullptr;
68 }
69 totalRead += sizeRead;
70 }
71
72 return out;
73}
Herb Derby67c47f22018-02-07 17:47:59 -050074
Herb Derby39e45df2018-03-27 14:40:53 -040075class Timer {
76public:
77 void start() {
78 fStart = std::chrono::high_resolution_clock::now();
79 }
80
81 void stop() {
82 auto end = std::chrono::high_resolution_clock::now();
83 fElapsedSeconds += end - fStart;
84 }
85
86 double elapsedSeconds() {
87 return fElapsedSeconds.count();
88 }
89
90private:
91 decltype(std::chrono::high_resolution_clock::now()) fStart;
92 std::chrono::duration<double> fElapsedSeconds{0.0};
93};
94
95static void build_prime_cache_spec(const SkIRect &bounds,
96 const SkSurfaceProps &props,
97 const SkPicture &pic,
98 SkStrikeCacheDifferenceSpec *strikeDifference) {
Herb Derby97be88f2018-03-21 16:23:49 -040099 SkMatrix deviceMatrix = SkMatrix::I();
Herb Derbyca9c8792018-02-02 17:33:26 -0500100
Herb Derby97be88f2018-03-21 16:23:49 -0400101 SkTextBlobCacheDiffCanvas filter(
102 bounds.width(), bounds.height(), deviceMatrix, props,
103 SkScalerContextFlags::kFakeGammaAndBoostContrast,
104 strikeDifference);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500105
Herb Derby97be88f2018-03-21 16:23:49 -0400106 pic.playback(&filter);
Herb Derby67c47f22018-02-07 17:47:59 -0500107}
108
Herb Derby67c47f22018-02-07 17:47:59 -0500109static void final_draw(std::string outFilename,
Herb Derby67c47f22018-02-07 17:47:59 -0500110 SkDeserialProcs* procs,
111 SkData* picData,
Herb Derby97be88f2018-03-21 16:23:49 -0400112 SkStrikeClient* client) {
Herb Derby67c47f22018-02-07 17:47:59 -0500113
114 auto pic = SkPicture::MakeFromData(picData, procs);
Herb Derby4f505f92018-01-09 12:34:11 -0500115
116 auto cullRect = pic->cullRect();
117 auto r = cullRect.round();
Herb Derby4f505f92018-01-09 12:34:11 -0500118
Herb Derbyd08c6822018-01-09 12:34:11 -0500119 auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
Herb Derby4f505f92018-01-09 12:34:11 -0500120 auto c = s->getCanvas();
Herb Derby67c47f22018-02-07 17:47:59 -0500121 auto picUnderTest = SkPicture::MakeFromData(picData, procs);
Herb Derbyd08c6822018-01-09 12:34:11 -0500122
Herb Derby39e45df2018-03-27 14:40:53 -0400123 Timer drawTime;
124 for (int i = 0; i < 100; i++) {
Herb Derby9d021822018-02-02 12:54:55 -0500125 if (gPurgeFontCaches) {
126 SkGraphics::PurgeFontCache();
127 }
Herb Derby39e45df2018-03-27 14:40:53 -0400128 drawTime.start();
Herb Derby97be88f2018-03-21 16:23:49 -0400129 if (client != nullptr) {
130 SkStrikeCacheDifferenceSpec strikeDifference;
Herb Derby39e45df2018-03-27 14:40:53 -0400131 build_prime_cache_spec(r, s->props(), *picUnderTest, &strikeDifference);
Herb Derby97be88f2018-03-21 16:23:49 -0400132 client->primeStrikeCache(strikeDifference);
Herb Derby67c47f22018-02-07 17:47:59 -0500133 }
Herb Derbyd08c6822018-01-09 12:34:11 -0500134 c->drawPicture(picUnderTest);
Herb Derby39e45df2018-03-27 14:40:53 -0400135 drawTime.stop();
Herb Derbyd08c6822018-01-09 12:34:11 -0500136 }
Herb Derby4f505f92018-01-09 12:34:11 -0500137
Herb Derby9d021822018-02-02 12:54:55 -0500138 std::cout << "useProcess: " << gUseProcess
139 << " useGPU: " << gUseGpu
140 << " purgeCache: " << gPurgeFontCaches << std::endl;
Herb Derby67c47f22018-02-07 17:47:59 -0500141 fprintf(stderr, "%s use GPU %s elapsed time %8.6f s\n", gSkpName.c_str(),
Herb Derby39e45df2018-03-27 14:40:53 -0400142 gUseGpu ? "true" : "false", drawTime.elapsedSeconds());
Herb Derby4f505f92018-01-09 12:34:11 -0500143
144 auto i = s->makeImageSnapshot();
145 auto data = i->encodeToData();
146 SkFILEWStream f(outFilename.c_str());
147 f.write(data->data(), data->size());
148}
149
Mike Kleina8a51ce2018-01-09 12:34:11 -0500150static void gpu(int readFd, int writeFd) {
151
Herb Derby39e45df2018-03-27 14:40:53 -0400152 if (gUseGpu) {
Herb Derby209a5f32018-04-05 16:57:25 -0400153 auto clientRPC = [readFd, writeFd](const SkData& inBuffer) {
154 write_SkData(writeFd, inBuffer);
155 return read_SkData(readFd);
156 };
Mike Kleina8a51ce2018-01-09 12:34:11 -0500157
Herb Derby209a5f32018-04-05 16:57:25 -0400158 auto picData = read_SkData(readFd);
Herb Derby39e45df2018-03-27 14:40:53 -0400159 if (picData == nullptr) {
160 return;
161 }
162
Herb Derby209a5f32018-04-05 16:57:25 -0400163 SkStrikeClient client{clientRPC};
Herb Derby39e45df2018-03-27 14:40:53 -0400164
165 SkDeserialProcs procs;
166 client.prepareDeserializeProcs(&procs);
167
Herb Derby46117c82018-04-03 18:44:34 -0400168 final_draw("test.png", &procs, picData.get(), &client);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500169 }
170
Herb Derby209a5f32018-04-05 16:57:25 -0400171 ::close(writeFd);
172 ::close(readFd);
173
Herb Derby97be88f2018-03-21 16:23:49 -0400174 printf("GPU is exiting\n");
Mike Kleina8a51ce2018-01-09 12:34:11 -0500175}
176
Herb Derbyb2922f62018-01-26 16:47:54 -0500177static int renderer(
178 const std::string& skpName, int readFd, int writeFd)
179{
Herb Derby209a5f32018-04-05 16:57:25 -0400180 SkStrikeServer server{};
181 auto closeAll = [readFd, writeFd]() {
182 ::close(writeFd);
183 ::close(readFd);
184 };
Mike Kleina8a51ce2018-01-09 12:34:11 -0500185
Herb Derby67c47f22018-02-07 17:47:59 -0500186 auto skpData = SkData::MakeFromFileName(skpName.c_str());
187 std::cout << "skp stream is " << skpData->size() << " bytes long " << std::endl;
Herb Derby4f505f92018-01-09 12:34:11 -0500188
Mike Kleina8a51ce2018-01-09 12:34:11 -0500189 SkSerialProcs procs;
Herb Derby9d021822018-02-02 12:54:55 -0500190 sk_sp<SkData> stream;
191 if (gUseGpu) {
Herb Derby67c47f22018-02-07 17:47:59 -0500192 auto pic = SkPicture::MakeFromData(skpData.get());
Herb Derby97be88f2018-03-21 16:23:49 -0400193 server.prepareSerializeProcs(&procs);
Herb Derby9d021822018-02-02 12:54:55 -0500194 stream = pic->serialize(&procs);
Herb Derby97be88f2018-03-21 16:23:49 -0400195
Herb Derby209a5f32018-04-05 16:57:25 -0400196 if (!write_SkData(writeFd, *stream)) {
197 closeAll();
Herb Derby97be88f2018-03-21 16:23:49 -0400198 return 1;
199 }
200
Herb Derby209a5f32018-04-05 16:57:25 -0400201 std::vector<uint8_t> tmpBuffer;
202 while (true) {
203 auto inBuffer = read_SkData(readFd);
204 if (inBuffer == nullptr) {
205 closeAll();
206 return 0;
207 }
Herb Derby97be88f2018-03-21 16:23:49 -0400208
Herb Derby209a5f32018-04-05 16:57:25 -0400209 tmpBuffer.clear();
210 server.serve(*inBuffer, &tmpBuffer);
211 auto outBuffer = SkData::MakeWithoutCopy(tmpBuffer.data(), tmpBuffer.size());
212 write_SkData(writeFd, *outBuffer);
213 }
Herb Derby9d021822018-02-02 12:54:55 -0500214 } else {
Herb Derby67c47f22018-02-07 17:47:59 -0500215 stream = skpData;
Herb Derby46117c82018-04-03 18:44:34 -0400216 final_draw("test-correct.png", nullptr, stream.get(), nullptr);
Herb Derby209a5f32018-04-05 16:57:25 -0400217 closeAll();
Herb Derby4f505f92018-01-09 12:34:11 -0500218 return 0;
219 }
Mike Kleina8a51ce2018-01-09 12:34:11 -0500220}
221
222int main(int argc, char** argv) {
Herb Derby67c47f22018-02-07 17:47:59 -0500223 std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"skps/desk_nytimes.skp"};
Herb Derby9d021822018-02-02 12:54:55 -0500224 int mode = argc > 2 ? atoi(argv[2]) : -1;
Mike Kleina8a51ce2018-01-09 12:34:11 -0500225 printf("skp: %s\n", skpName.c_str());
226
Herb Derby67c47f22018-02-07 17:47:59 -0500227 gSkpName = skpName;
228
Herb Derby97be88f2018-03-21 16:23:49 -0400229 enum direction : int {kRead = 0, kWrite = 1};
230
231
Mike Kleina8a51ce2018-01-09 12:34:11 -0500232 int render_to_gpu[2],
233 gpu_to_render[2];
234
Herb Derby9d021822018-02-02 12:54:55 -0500235 for (int m = 0; m < 8; m++) {
236 int r = pipe(render_to_gpu);
237 if (r < 0) {
238 perror("Can't write picture from render to GPU ");
239 return 1;
Herb Derbyd08c6822018-01-09 12:34:11 -0500240 }
Herb Derby9d021822018-02-02 12:54:55 -0500241 r = pipe(gpu_to_render);
242 if (r < 0) {
243 perror("Can't write picture from render to GPU ");
244 return 1;
245 }
246
247 gPurgeFontCaches = (m & 4) == 4;
248 gUseGpu = (m & 2) == 2;
249 gUseProcess = (m & 1) == 1;
250
251 if (mode >= 0 && mode < 8 && mode != m) {
252 continue;
253 }
254
255 if (gUseProcess) {
256 pid_t child = fork();
257 SkGraphics::Init();
258
259 if (child == 0) {
Herb Derby97be88f2018-03-21 16:23:49 -0400260 close(gpu_to_render[kRead]);
261 close(render_to_gpu[kWrite]);
262 gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
Herb Derby9d021822018-02-02 12:54:55 -0500263 } else {
Herb Derby97be88f2018-03-21 16:23:49 -0400264 close(render_to_gpu[kRead]);
265 close(gpu_to_render[kWrite]);
266 renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
Herb Derby9d021822018-02-02 12:54:55 -0500267 waitpid(child, nullptr, 0);
268 }
269 } else {
270 SkGraphics::Init();
271 std::thread(gpu, render_to_gpu[kRead], gpu_to_render[kWrite]).detach();
272 renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
273 }
Mike Kleina8a51ce2018-01-09 12:34:11 -0500274 }
275
Mike Kleina8a51ce2018-01-09 12:34:11 -0500276 return 0;
277}
278