Request.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright 2016 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 "tools/skiaserve/Request.h"
  8. #include "include/core/SkPictureRecorder.h"
  9. #include "src/utils/SkJSONWriter.h"
  10. #include "tools/ToolUtils.h"
  11. using namespace sk_gpu_test;
  12. static int kDefaultWidth = 1920;
  13. static int kDefaultHeight = 1080;
  14. static int kMaxWidth = 8192;
  15. static int kMaxHeight = 8192;
  16. Request::Request(SkString rootUrl)
  17. : fUploadContext(nullptr)
  18. , fUrlDataManager(rootUrl)
  19. , fGPUEnabled(false)
  20. , fOverdraw(false)
  21. , fColorMode(0) {
  22. // create surface
  23. GrContextOptions grContextOpts;
  24. fContextFactory = new GrContextFactory(grContextOpts);
  25. }
  26. Request::~Request() {
  27. if (fContextFactory) {
  28. delete fContextFactory;
  29. }
  30. }
  31. sk_sp<SkData> Request::writeCanvasToPng(SkCanvas* canvas) {
  32. // capture pixels
  33. SkBitmap bmp;
  34. bmp.allocPixels(canvas->imageInfo());
  35. SkAssertResult(canvas->readPixels(bmp, 0, 0));
  36. // write to an opaque png (black background)
  37. SkDynamicMemoryWStream buffer;
  38. DrawCommand::WritePNG(bmp, buffer);
  39. return buffer.detachAsData();
  40. }
  41. SkCanvas* Request::getCanvas() {
  42. GrContextFactory* factory = fContextFactory;
  43. GLTestContext* gl = factory->getContextInfo(GrContextFactory::kGL_ContextType,
  44. GrContextFactory::ContextOverrides::kNone).glContext();
  45. if (!gl) {
  46. gl = factory->getContextInfo(GrContextFactory::kGLES_ContextType,
  47. GrContextFactory::ContextOverrides::kNone).glContext();
  48. }
  49. if (gl) {
  50. gl->makeCurrent();
  51. }
  52. SkASSERT(fDebugCanvas);
  53. // create the appropriate surface if necessary
  54. if (!fSurface) {
  55. this->enableGPU(fGPUEnabled);
  56. }
  57. SkCanvas* target = fSurface->getCanvas();
  58. return target;
  59. }
  60. sk_sp<SkData> Request::drawToPng(int n, int m) {
  61. //fDebugCanvas->setOverdrawViz(true);
  62. fDebugCanvas->drawTo(this->getCanvas(), n, m);
  63. //fDebugCanvas->setOverdrawViz(false);
  64. return writeCanvasToPng(this->getCanvas());
  65. }
  66. sk_sp<SkData> Request::writeOutSkp() {
  67. // Playback into picture recorder
  68. SkIRect bounds = this->getBounds();
  69. SkPictureRecorder recorder;
  70. SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bounds.width()),
  71. SkIntToScalar(bounds.height()));
  72. fDebugCanvas->draw(canvas);
  73. return recorder.finishRecordingAsPicture()->serialize();
  74. }
  75. GrContext* Request::getContext() {
  76. GrContext* result = fContextFactory->get(GrContextFactory::kGL_ContextType,
  77. GrContextFactory::ContextOverrides::kNone);
  78. if (!result) {
  79. result = fContextFactory->get(GrContextFactory::kGLES_ContextType,
  80. GrContextFactory::ContextOverrides::kNone);
  81. }
  82. return result;
  83. }
  84. SkIRect Request::getBounds() {
  85. SkIRect bounds;
  86. if (fPicture) {
  87. bounds = fPicture->cullRect().roundOut();
  88. if (fGPUEnabled) {
  89. int maxRTSize = this->getContext()->maxRenderTargetSize();
  90. bounds = SkIRect::MakeWH(SkTMin(bounds.width(), maxRTSize),
  91. SkTMin(bounds.height(), maxRTSize));
  92. }
  93. } else {
  94. bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight);
  95. }
  96. // We clip to kMaxWidth / kMaxHeight for performance reasons.
  97. // TODO make this configurable
  98. bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kMaxWidth),
  99. SkTMin(bounds.height(), kMaxHeight));
  100. return bounds;
  101. }
  102. namespace {
  103. struct ColorAndProfile {
  104. SkColorType fColorType;
  105. bool fSRGB;
  106. };
  107. ColorAndProfile ColorModes[] = {
  108. { kN32_SkColorType, false },
  109. { kN32_SkColorType, true },
  110. { kRGBA_F16_SkColorType, true },
  111. };
  112. }
  113. SkSurface* Request::createCPUSurface() {
  114. SkIRect bounds = this->getBounds();
  115. ColorAndProfile cap = ColorModes[fColorMode];
  116. auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
  117. ? SkColorSpace::MakeSRGBLinear()
  118. : SkColorSpace::MakeSRGB();
  119. SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
  120. kPremul_SkAlphaType, cap.fSRGB ? colorSpace : nullptr);
  121. return SkSurface::MakeRaster(info).release();
  122. }
  123. SkSurface* Request::createGPUSurface() {
  124. GrContext* context = this->getContext();
  125. SkIRect bounds = this->getBounds();
  126. ColorAndProfile cap = ColorModes[fColorMode];
  127. auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
  128. ? SkColorSpace::MakeSRGBLinear()
  129. : SkColorSpace::MakeSRGB();
  130. SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
  131. kPremul_SkAlphaType, cap.fSRGB ? colorSpace: nullptr);
  132. SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info).release();
  133. return surface;
  134. }
  135. bool Request::setOverdraw(bool enable) {
  136. fOverdraw = enable;
  137. return true;
  138. }
  139. bool Request::setColorMode(int mode) {
  140. fColorMode = mode;
  141. return enableGPU(fGPUEnabled);
  142. }
  143. bool Request::enableGPU(bool enable) {
  144. if (enable) {
  145. SkSurface* surface = this->createGPUSurface();
  146. if (surface) {
  147. fSurface.reset(surface);
  148. fGPUEnabled = true;
  149. // When we switch to GPU, there seems to be some mystery draws in the canvas. So we
  150. // draw once to flush the pipe
  151. // TODO understand what is actually happening here
  152. if (fDebugCanvas) {
  153. fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
  154. this->getCanvas()->flush();
  155. }
  156. return true;
  157. }
  158. return false;
  159. }
  160. fSurface.reset(this->createCPUSurface());
  161. fGPUEnabled = false;
  162. return true;
  163. }
  164. bool Request::initPictureFromStream(SkStream* stream) {
  165. // parse picture from stream
  166. fPicture = SkPicture::MakeFromStream(stream);
  167. if (!fPicture) {
  168. fprintf(stderr, "Could not create picture from stream.\n");
  169. return false;
  170. }
  171. // reinitialize canvas with the new picture dimensions
  172. this->enableGPU(fGPUEnabled);
  173. // pour picture into debug canvas
  174. SkIRect bounds = this->getBounds();
  175. fDebugCanvas.reset(new DebugCanvas(bounds.width(), bounds.height()));
  176. fDebugCanvas->drawPicture(fPicture);
  177. // for some reason we need to 'flush' the debug canvas by drawing all of the ops
  178. fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
  179. this->getCanvas()->flush();
  180. return true;
  181. }
  182. sk_sp<SkData> Request::getJsonOps(int n) {
  183. SkCanvas* canvas = this->getCanvas();
  184. SkDynamicMemoryWStream stream;
  185. SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
  186. writer.beginObject(); // root
  187. writer.appendString("mode", fGPUEnabled ? "gpu" : "cpu");
  188. writer.appendBool("drawGpuOpBounds", fDebugCanvas->getDrawGpuOpBounds());
  189. writer.appendS32("colorMode", fColorMode);
  190. fDebugCanvas->toJSON(writer, fUrlDataManager, n, canvas);
  191. writer.endObject(); // root
  192. writer.flush();
  193. return stream.detachAsData();
  194. }
  195. sk_sp<SkData> Request::getJsonOpList(int n) {
  196. SkCanvas* canvas = this->getCanvas();
  197. SkASSERT(fGPUEnabled);
  198. SkDynamicMemoryWStream stream;
  199. SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
  200. fDebugCanvas->toJSONOpList(writer, n, canvas);
  201. writer.flush();
  202. return stream.detachAsData();
  203. }
  204. sk_sp<SkData> Request::getJsonInfo(int n) {
  205. // drawTo
  206. sk_sp<SkSurface> surface(this->createCPUSurface());
  207. SkCanvas* canvas = surface->getCanvas();
  208. // TODO this is really slow and we should cache the matrix and clip
  209. fDebugCanvas->drawTo(canvas, n);
  210. // make some json
  211. SkDynamicMemoryWStream stream;
  212. SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
  213. SkMatrix vm = fDebugCanvas->getCurrentMatrix();
  214. SkIRect clip = fDebugCanvas->getCurrentClip();
  215. writer.beginObject(); // root
  216. writer.appendName("ViewMatrix");
  217. DrawCommand::MakeJsonMatrix(writer, vm);
  218. writer.appendName("ClipRect");
  219. DrawCommand::MakeJsonIRect(writer, clip);
  220. writer.endObject(); // root
  221. // TODO: Old code explicitly avoided the null terminator in the returned data. Important?
  222. writer.flush();
  223. return stream.detachAsData();
  224. }
  225. SkColor Request::getPixel(int x, int y) {
  226. SkBitmap bmp;
  227. bmp.allocPixels(this->getCanvas()->imageInfo().makeWH(1, 1));
  228. SkAssertResult(this->getCanvas()->readPixels(bmp, x, y));
  229. return bmp.getColor(0, 0);
  230. }