blob: d572673bcf1b305df97d2a44a584c23e76d2e0d4 [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 Derby39e45df2018-03-27 14:40:53 -040028class ReadWriteTransport : public SkRemoteStrikeTransport {
Herb Derby67c47f22018-02-07 17:47:59 -050029public:
Herb Derby97be88f2018-03-21 16:23:49 -040030 ReadWriteTransport(int readFd, int writeFd) : fReadFd{readFd}, fWriteFd{writeFd} {}
31 ~ReadWriteTransport() override {
32 close(fWriteFd);
33 close(fReadFd);
Herb Derby67c47f22018-02-07 17:47:59 -050034 }
Herb Derby97be88f2018-03-21 16:23:49 -040035 IOResult write(const void* buffer, size_t size) override {
36 ssize_t writeSize = ::write(fWriteFd, buffer, size);
37 if (writeSize < 0) {
38 err(1,"Failed write %zu", size);
Herb Derby67c47f22018-02-07 17:47:59 -050039 return kFail;
40 }
41 return kSuccess;
42 }
43
Herb Derby97be88f2018-03-21 16:23:49 -040044 std::tuple<size_t, IOResult> read(void* buffer, size_t size) override {
45 ssize_t readSize = ::read(fReadFd, buffer, size);
46 if (readSize < 0) {
47 err(1,"Failed read %zu", size);
48 return {size, kFail};
Herb Derby67c47f22018-02-07 17:47:59 -050049 }
Herb Derby97be88f2018-03-21 16:23:49 -040050 return {readSize, kSuccess};
Herb Derby67c47f22018-02-07 17:47:59 -050051 }
52
Herb Derby67c47f22018-02-07 17:47:59 -050053private:
Herb Derby67c47f22018-02-07 17:47:59 -050054 const int fReadFd,
55 fWriteFd;
Herb Derby67c47f22018-02-07 17:47:59 -050056};
57
Herb Derby39e45df2018-03-27 14:40:53 -040058class Timer {
59public:
60 void start() {
61 fStart = std::chrono::high_resolution_clock::now();
62 }
63
64 void stop() {
65 auto end = std::chrono::high_resolution_clock::now();
66 fElapsedSeconds += end - fStart;
67 }
68
69 double elapsedSeconds() {
70 return fElapsedSeconds.count();
71 }
72
73private:
74 decltype(std::chrono::high_resolution_clock::now()) fStart;
75 std::chrono::duration<double> fElapsedSeconds{0.0};
76};
77
78static void build_prime_cache_spec(const SkIRect &bounds,
79 const SkSurfaceProps &props,
80 const SkPicture &pic,
81 SkStrikeCacheDifferenceSpec *strikeDifference) {
Herb Derby97be88f2018-03-21 16:23:49 -040082 SkMatrix deviceMatrix = SkMatrix::I();
Herb Derbyca9c8792018-02-02 17:33:26 -050083
Herb Derby97be88f2018-03-21 16:23:49 -040084 SkTextBlobCacheDiffCanvas filter(
85 bounds.width(), bounds.height(), deviceMatrix, props,
86 SkScalerContextFlags::kFakeGammaAndBoostContrast,
87 strikeDifference);
Mike Kleina8a51ce2018-01-09 12:34:11 -050088
Herb Derby97be88f2018-03-21 16:23:49 -040089 pic.playback(&filter);
Herb Derby67c47f22018-02-07 17:47:59 -050090}
91
Herb Derby67c47f22018-02-07 17:47:59 -050092static void final_draw(std::string outFilename,
Herb Derby39e45df2018-03-27 14:40:53 -040093 SkRemoteStrikeTransport* transport,
Herb Derby67c47f22018-02-07 17:47:59 -050094 SkDeserialProcs* procs,
95 SkData* picData,
Herb Derby97be88f2018-03-21 16:23:49 -040096 SkStrikeClient* client) {
Herb Derby67c47f22018-02-07 17:47:59 -050097
98 auto pic = SkPicture::MakeFromData(picData, procs);
Herb Derby4f505f92018-01-09 12:34:11 -050099
100 auto cullRect = pic->cullRect();
101 auto r = cullRect.round();
Herb Derby4f505f92018-01-09 12:34:11 -0500102
Herb Derbyd08c6822018-01-09 12:34:11 -0500103 auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
Herb Derby4f505f92018-01-09 12:34:11 -0500104 auto c = s->getCanvas();
Herb Derby67c47f22018-02-07 17:47:59 -0500105 auto picUnderTest = SkPicture::MakeFromData(picData, procs);
Herb Derbyd08c6822018-01-09 12:34:11 -0500106
Herb Derby39e45df2018-03-27 14:40:53 -0400107 Timer drawTime;
108 for (int i = 0; i < 100; i++) {
Herb Derby9d021822018-02-02 12:54:55 -0500109 if (gPurgeFontCaches) {
110 SkGraphics::PurgeFontCache();
111 }
Herb Derby39e45df2018-03-27 14:40:53 -0400112 drawTime.start();
Herb Derby97be88f2018-03-21 16:23:49 -0400113 if (client != nullptr) {
114 SkStrikeCacheDifferenceSpec strikeDifference;
Herb Derby39e45df2018-03-27 14:40:53 -0400115 build_prime_cache_spec(r, s->props(), *picUnderTest, &strikeDifference);
Herb Derby97be88f2018-03-21 16:23:49 -0400116 client->primeStrikeCache(strikeDifference);
Herb Derby67c47f22018-02-07 17:47:59 -0500117 }
Herb Derbyd08c6822018-01-09 12:34:11 -0500118 c->drawPicture(picUnderTest);
Herb Derby39e45df2018-03-27 14:40:53 -0400119 drawTime.stop();
Herb Derbyd08c6822018-01-09 12:34:11 -0500120 }
Herb Derby4f505f92018-01-09 12:34:11 -0500121
Herb Derby9d021822018-02-02 12:54:55 -0500122 std::cout << "useProcess: " << gUseProcess
123 << " useGPU: " << gUseGpu
124 << " purgeCache: " << gPurgeFontCaches << std::endl;
Herb Derby67c47f22018-02-07 17:47:59 -0500125 fprintf(stderr, "%s use GPU %s elapsed time %8.6f s\n", gSkpName.c_str(),
Herb Derby39e45df2018-03-27 14:40:53 -0400126 gUseGpu ? "true" : "false", drawTime.elapsedSeconds());
Herb Derby4f505f92018-01-09 12:34:11 -0500127
128 auto i = s->makeImageSnapshot();
129 auto data = i->encodeToData();
130 SkFILEWStream f(outFilename.c_str());
131 f.write(data->data(), data->size());
132}
133
Mike Kleina8a51ce2018-01-09 12:34:11 -0500134static void gpu(int readFd, int writeFd) {
135
Herb Derby39e45df2018-03-27 14:40:53 -0400136 if (gUseGpu) {
137 ReadWriteTransport rwTransport{readFd, writeFd};
Mike Kleina8a51ce2018-01-09 12:34:11 -0500138
Herb Derby39e45df2018-03-27 14:40:53 -0400139 auto picData = rwTransport.readSkData();
140 if (picData == nullptr) {
141 return;
142 }
143
144 SkStrikeClient client{&rwTransport};
145
146 SkDeserialProcs procs;
147 client.prepareDeserializeProcs(&procs);
148
149 final_draw("test.png", &rwTransport, &procs, picData.get(), &client);
Mike Kleina8a51ce2018-01-09 12:34:11 -0500150 }
151
Herb Derby97be88f2018-03-21 16:23:49 -0400152 printf("GPU is exiting\n");
Mike Kleina8a51ce2018-01-09 12:34:11 -0500153}
154
Herb Derbyb2922f62018-01-26 16:47:54 -0500155static int renderer(
156 const std::string& skpName, int readFd, int writeFd)
157{
Herb Derby97be88f2018-03-21 16:23:49 -0400158 ReadWriteTransport rwTransport{readFd, writeFd};
159 SkStrikeServer server{&rwTransport};
Mike Kleina8a51ce2018-01-09 12:34:11 -0500160
Herb Derby67c47f22018-02-07 17:47:59 -0500161 auto skpData = SkData::MakeFromFileName(skpName.c_str());
162 std::cout << "skp stream is " << skpData->size() << " bytes long " << std::endl;
Herb Derby4f505f92018-01-09 12:34:11 -0500163
Mike Kleina8a51ce2018-01-09 12:34:11 -0500164 SkSerialProcs procs;
Herb Derby9d021822018-02-02 12:54:55 -0500165 sk_sp<SkData> stream;
166 if (gUseGpu) {
Herb Derby67c47f22018-02-07 17:47:59 -0500167 auto pic = SkPicture::MakeFromData(skpData.get());
Herb Derby97be88f2018-03-21 16:23:49 -0400168 server.prepareSerializeProcs(&procs);
Herb Derby9d021822018-02-02 12:54:55 -0500169 stream = pic->serialize(&procs);
Herb Derby97be88f2018-03-21 16:23:49 -0400170
Herb Derby39e45df2018-03-27 14:40:53 -0400171 if (rwTransport.writeSkData(*stream) == SkRemoteStrikeTransport::kFail) {
Herb Derby97be88f2018-03-21 16:23:49 -0400172 return 1;
173 }
174
175 std::cout << "Waiting for scaler context ops." << std::endl;
176
177 return server.serve();
Herb Derby9d021822018-02-02 12:54:55 -0500178 } else {
Herb Derby67c47f22018-02-07 17:47:59 -0500179 stream = skpData;
Herb Derby97be88f2018-03-21 16:23:49 -0400180 final_draw("test-correct.png", &rwTransport, nullptr, stream.get(), nullptr);
Herb Derby4f505f92018-01-09 12:34:11 -0500181 return 0;
182 }
Mike Kleina8a51ce2018-01-09 12:34:11 -0500183}
184
185int main(int argc, char** argv) {
Herb Derby67c47f22018-02-07 17:47:59 -0500186 std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"skps/desk_nytimes.skp"};
Herb Derby9d021822018-02-02 12:54:55 -0500187 int mode = argc > 2 ? atoi(argv[2]) : -1;
Mike Kleina8a51ce2018-01-09 12:34:11 -0500188 printf("skp: %s\n", skpName.c_str());
189
Herb Derby67c47f22018-02-07 17:47:59 -0500190 gSkpName = skpName;
191
Herb Derby97be88f2018-03-21 16:23:49 -0400192 enum direction : int {kRead = 0, kWrite = 1};
193
194
Mike Kleina8a51ce2018-01-09 12:34:11 -0500195 int render_to_gpu[2],
196 gpu_to_render[2];
197
Herb Derby9d021822018-02-02 12:54:55 -0500198 for (int m = 0; m < 8; m++) {
199 int r = pipe(render_to_gpu);
200 if (r < 0) {
201 perror("Can't write picture from render to GPU ");
202 return 1;
Herb Derbyd08c6822018-01-09 12:34:11 -0500203 }
Herb Derby9d021822018-02-02 12:54:55 -0500204 r = pipe(gpu_to_render);
205 if (r < 0) {
206 perror("Can't write picture from render to GPU ");
207 return 1;
208 }
209
210 gPurgeFontCaches = (m & 4) == 4;
211 gUseGpu = (m & 2) == 2;
212 gUseProcess = (m & 1) == 1;
213
214 if (mode >= 0 && mode < 8 && mode != m) {
215 continue;
216 }
217
218 if (gUseProcess) {
219 pid_t child = fork();
220 SkGraphics::Init();
221
222 if (child == 0) {
Herb Derby97be88f2018-03-21 16:23:49 -0400223 close(gpu_to_render[kRead]);
224 close(render_to_gpu[kWrite]);
225 gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
Herb Derby9d021822018-02-02 12:54:55 -0500226 } else {
Herb Derby97be88f2018-03-21 16:23:49 -0400227 close(render_to_gpu[kRead]);
228 close(gpu_to_render[kWrite]);
229 renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
Herb Derby9d021822018-02-02 12:54:55 -0500230 waitpid(child, nullptr, 0);
231 }
232 } else {
233 SkGraphics::Init();
234 std::thread(gpu, render_to_gpu[kRead], gpu_to_render[kWrite]).detach();
235 renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
236 }
Mike Kleina8a51ce2018-01-09 12:34:11 -0500237 }
238
Mike Kleina8a51ce2018-01-09 12:34:11 -0500239 return 0;
240}
241