remote_demo.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. #include <chrono>
  8. #include <err.h>
  9. #include <iostream>
  10. #include <memory>
  11. #include <string>
  12. #include <sys/types.h>
  13. #include <sys/uio.h>
  14. #include <sys/wait.h>
  15. #include <thread>
  16. #include <unistd.h>
  17. #include "include/core/SkGraphics.h"
  18. #include "include/core/SkSurface.h"
  19. #include "src/core/SkRemoteGlyphCache.h"
  20. #include "src/core/SkScalerContext.h"
  21. static std::string gSkpName;
  22. static bool gUseGpu = true;
  23. static bool gPurgeFontCaches = true;
  24. static bool gUseProcess = true;
  25. class ServerDiscardableManager : public SkStrikeServer::DiscardableHandleManager {
  26. public:
  27. ServerDiscardableManager() = default;
  28. ~ServerDiscardableManager() override = default;
  29. SkDiscardableHandleId createHandle() override { return ++nextHandleId; }
  30. bool lockHandle(SkDiscardableHandleId handleId) override {
  31. return handleId > lastPurgedHandleId;
  32. }
  33. void purgeAll() { lastPurgedHandleId = nextHandleId; }
  34. private:
  35. SkDiscardableHandleId nextHandleId = 0u;
  36. SkDiscardableHandleId lastPurgedHandleId = 0u;
  37. };
  38. class ClientDiscardableManager : public SkStrikeClient::DiscardableHandleManager {
  39. public:
  40. class ScopedPurgeCache {
  41. public:
  42. ScopedPurgeCache(ClientDiscardableManager* manager) : fManager(manager) {
  43. if (fManager) fManager->allowPurging = true;
  44. }
  45. ~ScopedPurgeCache() {
  46. if (fManager) fManager->allowPurging = false;
  47. }
  48. private:
  49. ClientDiscardableManager* fManager;
  50. };
  51. ClientDiscardableManager() = default;
  52. ~ClientDiscardableManager() override = default;
  53. bool deleteHandle(SkDiscardableHandleId) override { return allowPurging; }
  54. private:
  55. bool allowPurging = false;
  56. };
  57. static bool write_SkData(int fd, const SkData& data) {
  58. size_t size = data.size();
  59. ssize_t bytesWritten = ::write(fd, &size, sizeof(size));
  60. if (bytesWritten < 0) {
  61. err(1,"Failed write %zu", size);
  62. return false;
  63. }
  64. bytesWritten = ::write(fd, data.data(), data.size());
  65. if (bytesWritten < 0) {
  66. err(1,"Failed write %zu", size);
  67. return false;
  68. }
  69. return true;
  70. }
  71. static sk_sp<SkData> read_SkData(int fd) {
  72. size_t size;
  73. ssize_t readSize = ::read(fd, &size, sizeof(size));
  74. if (readSize <= 0) {
  75. if (readSize < 0) {
  76. err(1, "Failed read %zu", size);
  77. }
  78. return nullptr;
  79. }
  80. auto out = SkData::MakeUninitialized(size);
  81. auto data = (uint8_t*)out->data();
  82. size_t totalRead = 0;
  83. while (totalRead < size) {
  84. ssize_t sizeRead;
  85. sizeRead = ::read(fd, &data[totalRead], size - totalRead);
  86. if (sizeRead <= 0) {
  87. if (readSize < 0) {
  88. err(1, "Failed read %zu", size);
  89. }
  90. return nullptr;
  91. }
  92. totalRead += sizeRead;
  93. }
  94. return out;
  95. }
  96. class Timer {
  97. public:
  98. void start() {
  99. fStart = std::chrono::high_resolution_clock::now();
  100. }
  101. void stop() {
  102. auto end = std::chrono::high_resolution_clock::now();
  103. fElapsedSeconds += end - fStart;
  104. }
  105. double elapsedSeconds() {
  106. return fElapsedSeconds.count();
  107. }
  108. private:
  109. decltype(std::chrono::high_resolution_clock::now()) fStart;
  110. std::chrono::duration<double> fElapsedSeconds{0.0};
  111. };
  112. static bool push_font_data(const SkPicture& pic, SkStrikeServer* strikeServer,
  113. sk_sp<SkColorSpace> colorSpace, int writeFd) {
  114. const SkIRect bounds = pic.cullRect().round();
  115. const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
  116. SkTextBlobCacheDiffCanvas filter(bounds.width(), bounds.height(), props,
  117. strikeServer, std::move(colorSpace));
  118. pic.playback(&filter);
  119. std::vector<uint8_t> fontData;
  120. strikeServer->writeStrikeData(&fontData);
  121. auto data = SkData::MakeWithoutCopy(fontData.data(), fontData.size());
  122. return write_SkData(writeFd, *data);
  123. }
  124. static void final_draw(std::string outFilename, SkData* picData, SkStrikeClient* client,
  125. ClientDiscardableManager* discardableManager, int readFd, int writeFd) {
  126. SkDeserialProcs procs;
  127. auto decode = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
  128. return reinterpret_cast<SkStrikeClient*>(ctx)->deserializeTypeface(data, length);
  129. };
  130. procs.fTypefaceProc = decode;
  131. procs.fTypefaceCtx = client;
  132. auto pic = SkPicture::MakeFromData(picData, &procs);
  133. auto cullRect = pic->cullRect();
  134. auto r = cullRect.round();
  135. auto s = SkSurface::MakeRasterN32Premul(r.width(), r.height());
  136. auto c = s->getCanvas();
  137. auto picUnderTest = SkPicture::MakeFromData(picData, &procs);
  138. Timer drawTime;
  139. auto randomData = SkData::MakeUninitialized(1u);
  140. for (int i = 0; i < 100; i++) {
  141. if (gPurgeFontCaches) {
  142. ClientDiscardableManager::ScopedPurgeCache purge(discardableManager);
  143. SkGraphics::PurgeFontCache();
  144. SkASSERT(SkGraphics::GetFontCacheUsed() == 0u);
  145. }
  146. drawTime.start();
  147. if (client != nullptr) {
  148. // Kick the renderer to send us the fonts.
  149. write_SkData(writeFd, *randomData);
  150. auto fontData = read_SkData(readFd);
  151. if (fontData && !fontData->isEmpty()) {
  152. if (!client->readStrikeData(fontData->data(), fontData->size()))
  153. SK_ABORT("Bad serialization");
  154. }
  155. }
  156. c->drawPicture(picUnderTest);
  157. drawTime.stop();
  158. }
  159. std::cout << "useProcess: " << gUseProcess
  160. << " useGPU: " << gUseGpu
  161. << " purgeCache: " << gPurgeFontCaches << std::endl;
  162. fprintf(stderr, "%s use GPU %s elapsed time %8.6f s\n", gSkpName.c_str(),
  163. gUseGpu ? "true" : "false", drawTime.elapsedSeconds());
  164. auto i = s->makeImageSnapshot();
  165. auto data = i->encodeToData();
  166. SkFILEWStream f(outFilename.c_str());
  167. f.write(data->data(), data->size());
  168. }
  169. static void gpu(int readFd, int writeFd) {
  170. if (gUseGpu) {
  171. auto picData = read_SkData(readFd);
  172. if (picData == nullptr) {
  173. return;
  174. }
  175. sk_sp<ClientDiscardableManager> discardableManager = sk_make_sp<ClientDiscardableManager>();
  176. SkStrikeClient strikeClient(discardableManager);
  177. final_draw("test.png", picData.get(), &strikeClient, discardableManager.get(), readFd,
  178. writeFd);
  179. }
  180. ::close(writeFd);
  181. ::close(readFd);
  182. printf("GPU is exiting\n");
  183. }
  184. static int renderer(
  185. const std::string& skpName, int readFd, int writeFd)
  186. {
  187. ServerDiscardableManager discardableManager;
  188. SkStrikeServer server(&discardableManager);
  189. auto closeAll = [readFd, writeFd]() {
  190. ::close(writeFd);
  191. ::close(readFd);
  192. };
  193. auto skpData = SkData::MakeFromFileName(skpName.c_str());
  194. std::cout << "skp stream is " << skpData->size() << " bytes long " << std::endl;
  195. sk_sp<SkData> stream;
  196. if (gUseGpu) {
  197. auto pic = SkPicture::MakeFromData(skpData.get());
  198. auto colorSpace = SkColorSpace::MakeSRGB();
  199. SkSerialProcs procs;
  200. auto encode = [](SkTypeface* tf, void* ctx) -> sk_sp<SkData> {
  201. return reinterpret_cast<SkStrikeServer*>(ctx)->serializeTypeface(tf);
  202. };
  203. procs.fTypefaceProc = encode;
  204. procs.fTypefaceCtx = &server;
  205. stream = pic->serialize(&procs);
  206. if (!write_SkData(writeFd, *stream)) {
  207. closeAll();
  208. return 1;
  209. }
  210. while (true) {
  211. auto inBuffer = read_SkData(readFd);
  212. if (inBuffer == nullptr) {
  213. closeAll();
  214. return 0;
  215. }
  216. if (gPurgeFontCaches) discardableManager.purgeAll();
  217. push_font_data(*pic.get(), &server, colorSpace, writeFd);
  218. }
  219. } else {
  220. stream = skpData;
  221. final_draw("test-correct.png", stream.get(), nullptr, nullptr, -1, -1);
  222. closeAll();
  223. return 0;
  224. }
  225. }
  226. int main(int argc, char** argv) {
  227. std::string skpName = argc > 1 ? std::string{argv[1]} : std::string{"skps/desk_nytimes.skp"};
  228. int mode = argc > 2 ? atoi(argv[2]) : -1;
  229. printf("skp: %s\n", skpName.c_str());
  230. gSkpName = skpName;
  231. enum direction : int {kRead = 0, kWrite = 1};
  232. int render_to_gpu[2],
  233. gpu_to_render[2];
  234. for (int m = 0; m < 8; m++) {
  235. int r = pipe(render_to_gpu);
  236. if (r < 0) {
  237. perror("Can't write picture from render to GPU ");
  238. return 1;
  239. }
  240. r = pipe(gpu_to_render);
  241. if (r < 0) {
  242. perror("Can't write picture from render to GPU ");
  243. return 1;
  244. }
  245. gPurgeFontCaches = (m & 4) == 4;
  246. gUseGpu = (m & 2) == 2;
  247. gUseProcess = (m & 1) == 1;
  248. if (mode >= 0 && mode < 8 && mode != m) {
  249. continue;
  250. }
  251. if (gUseProcess) {
  252. pid_t child = fork();
  253. SkGraphics::Init();
  254. if (child == 0) {
  255. close(gpu_to_render[kRead]);
  256. close(render_to_gpu[kWrite]);
  257. gpu(render_to_gpu[kRead], gpu_to_render[kWrite]);
  258. } else {
  259. close(render_to_gpu[kRead]);
  260. close(gpu_to_render[kWrite]);
  261. renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
  262. waitpid(child, nullptr, 0);
  263. }
  264. } else {
  265. SkGraphics::Init();
  266. std::thread(gpu, render_to_gpu[kRead], gpu_to_render[kWrite]).detach();
  267. renderer(skpName, gpu_to_render[kRead], render_to_gpu[kWrite]);
  268. }
  269. }
  270. return 0;
  271. }