blob: 0fbccc39b33f39ecfed29b2b336b363a5cb7d091 [file] [log] [blame]
joshualitt4dcbe432016-02-25 10:50:28 -08001/*
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
8#include "Request.h"
9
joshualitte0449cf2016-03-09 10:07:02 -080010#include "SkPictureRecorder.h"
11#include "SkPixelSerializer.h"
brianosman312aa6a2016-04-19 12:47:54 -070012#include "SkPM4fPriv.h"
brianosman78312952016-04-19 10:16:53 -070013#include "picture_utils.h"
Hal Canarydb683012016-11-23 08:55:18 -070014#include "sk_tool_utils.h"
joshualitt4dcbe432016-02-25 10:50:28 -080015
bsalomon3724e572016-03-30 18:56:19 -070016using namespace sk_gpu_test;
17
joshualittae47aee2016-03-10 13:29:36 -080018static int kDefaultWidth = 1920;
19static int kDefaultHeight = 1080;
jcgregorio9a7acdc2016-06-30 07:54:14 -070020static int kMaxWidth = 8192;
21static int kMaxHeight = 8192;
joshualittae47aee2016-03-10 13:29:36 -080022
joshualitt4dcbe432016-02-25 10:50:28 -080023
joshualittee5348b2016-02-26 08:36:25 -080024Request::Request(SkString rootUrl)
25 : fUploadContext(nullptr)
26 , fUrlDataManager(rootUrl)
brianosman78312952016-04-19 10:16:53 -070027 , fGPUEnabled(false)
Ben Wagnerc03e1c52016-10-17 15:20:02 -040028 , fOverdraw(false)
brianosman78312952016-04-19 10:16:53 -070029 , fColorMode(0) {
joshualittee5348b2016-02-26 08:36:25 -080030 // create surface
joshualitt40836102016-03-11 11:45:53 -080031#if SK_SUPPORT_GPU
joshualittee5348b2016-02-26 08:36:25 -080032 GrContextOptions grContextOpts;
joshualitt40836102016-03-11 11:45:53 -080033 fContextFactory = new GrContextFactory(grContextOpts);
34#else
35 fContextFactory = nullptr;
36#endif
37}
38
39Request::~Request() {
40#if SK_SUPPORT_GPU
41 if (fContextFactory) {
42 delete fContextFactory;
43 }
44#endif
joshualittee5348b2016-02-26 08:36:25 -080045}
46
joshualitt4dcbe432016-02-25 10:50:28 -080047SkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) {
48 SkBitmap* bmp = new SkBitmap();
brianosman78312952016-04-19 10:16:53 -070049 bmp->setInfo(canvas->imageInfo());
joshualitt4dcbe432016-02-25 10:50:28 -080050 if (!canvas->readPixels(bmp, 0, 0)) {
51 fprintf(stderr, "Can't read pixels\n");
52 return nullptr;
53 }
54 return bmp;
55}
56
bungeman38d909e2016-08-02 14:40:46 -070057sk_sp<SkData> Request::writeCanvasToPng(SkCanvas* canvas) {
joshualitt4dcbe432016-02-25 10:50:28 -080058 // capture pixels
Ben Wagner145dbcd2016-11-03 14:40:50 -040059 std::unique_ptr<SkBitmap> bmp(this->getBitmapFromCanvas(canvas));
joshualitt4dcbe432016-02-25 10:50:28 -080060 SkASSERT(bmp);
61
brianosman78312952016-04-19 10:16:53 -070062 // Convert to format suitable for PNG output
63 sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bmp);
64 SkASSERT(encodedBitmap.get());
65
msaretta5cf4f42016-06-30 10:06:51 -070066 // write to an opaque png (black background)
joshualitt4dcbe432016-02-25 10:50:28 -080067 SkDynamicMemoryWStream buffer;
halcanarya73d76a2016-10-17 13:19:02 -070068 SkDrawCommand::WritePNG(encodedBitmap->bytes(), bmp->width(), bmp->height(),
msaretta5cf4f42016-06-30 10:06:51 -070069 buffer, true);
reed42943c82016-09-12 12:01:44 -070070 return buffer.detachAsData();
joshualitt4dcbe432016-02-25 10:50:28 -080071}
72
73SkCanvas* Request::getCanvas() {
joshualitt40836102016-03-11 11:45:53 -080074#if SK_SUPPORT_GPU
joshualitt4dcbe432016-02-25 10:50:28 -080075 GrContextFactory* factory = fContextFactory;
bsalomon85b4b532016-04-05 11:06:27 -070076 GLTestContext* gl = factory->getContextInfo(GrContextFactory::kNativeGL_ContextType,
csmartdalton6270e552016-09-13 10:41:49 -070077 GrContextFactory::ContextOptions::kNone).glContext();
ethannicholas2ec06c92016-06-13 10:20:52 -070078 if (!gl) {
79 gl = factory->getContextInfo(GrContextFactory::kMESA_ContextType,
csmartdalton6270e552016-09-13 10:41:49 -070080 GrContextFactory::ContextOptions::kNone).glContext();
ethannicholas2ec06c92016-06-13 10:20:52 -070081 }
82 if (gl) {
83 gl->makeCurrent();
84 }
joshualitt40836102016-03-11 11:45:53 -080085#endif
joshualitt4dcbe432016-02-25 10:50:28 -080086 SkASSERT(fDebugCanvas);
joshualitte0449cf2016-03-09 10:07:02 -080087
88 // create the appropriate surface if necessary
89 if (!fSurface) {
90 this->enableGPU(fGPUEnabled);
91 }
joshualitt4dcbe432016-02-25 10:50:28 -080092 SkCanvas* target = fSurface->getCanvas();
93 return target;
94}
95
joshualitt46b301d2016-03-02 08:32:37 -080096void Request::drawToCanvas(int n, int m) {
joshualitt4dcbe432016-02-25 10:50:28 -080097 SkCanvas* target = this->getCanvas();
joshualitt46b301d2016-03-02 08:32:37 -080098 fDebugCanvas->drawTo(target, n, m);
joshualitt4dcbe432016-02-25 10:50:28 -080099}
100
bungeman38d909e2016-08-02 14:40:46 -0700101sk_sp<SkData> Request::drawToPng(int n, int m) {
Ben Wagnerc03e1c52016-10-17 15:20:02 -0400102 //fDebugCanvas->setOverdrawViz(true);
joshualitt46b301d2016-03-02 08:32:37 -0800103 this->drawToCanvas(n, m);
Ben Wagnerc03e1c52016-10-17 15:20:02 -0400104 //fDebugCanvas->setOverdrawViz(false);
joshualitt4dcbe432016-02-25 10:50:28 -0800105 return writeCanvasToPng(this->getCanvas());
106}
107
bungeman38d909e2016-08-02 14:40:46 -0700108sk_sp<SkData> Request::writeOutSkp() {
joshualitte0449cf2016-03-09 10:07:02 -0800109 // Playback into picture recorder
joshualittae47aee2016-03-10 13:29:36 -0800110 SkIRect bounds = this->getBounds();
joshualitte0449cf2016-03-09 10:07:02 -0800111 SkPictureRecorder recorder;
brianosman82996b82016-04-20 10:52:54 -0700112 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bounds.width()),
113 SkIntToScalar(bounds.height()));
joshualitte0449cf2016-03-09 10:07:02 -0800114
115 fDebugCanvas->draw(canvas);
116
reedca2622b2016-03-18 07:25:55 -0700117 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
joshualitte0449cf2016-03-09 10:07:02 -0800118
119 SkDynamicMemoryWStream outStream;
120
Hal Canarydb683012016-11-23 08:55:18 -0700121 sk_sp<SkPixelSerializer> serializer = sk_tool_utils::MakePixelSerializer();
Hal Canary1b612a82016-11-03 16:26:13 -0400122 picture->serialize(&outStream, serializer.get());
joshualitte0449cf2016-03-09 10:07:02 -0800123
reed42943c82016-09-12 12:01:44 -0700124 return outStream.detachAsData();
joshualitte0449cf2016-03-09 10:07:02 -0800125}
126
joshualittae47aee2016-03-10 13:29:36 -0800127GrContext* Request::getContext() {
joshualitt40836102016-03-11 11:45:53 -0800128#if SK_SUPPORT_GPU
ethannicholas2ec06c92016-06-13 10:20:52 -0700129 GrContext* result = fContextFactory->get(GrContextFactory::kNativeGL_ContextType,
csmartdalton6270e552016-09-13 10:41:49 -0700130 GrContextFactory::ContextOptions::kNone);
ethannicholas2ec06c92016-06-13 10:20:52 -0700131 if (!result) {
132 result = fContextFactory->get(GrContextFactory::kMESA_ContextType,
csmartdalton6270e552016-09-13 10:41:49 -0700133 GrContextFactory::ContextOptions::kNone);
jcgregorio9a7acdc2016-06-30 07:54:14 -0700134 }
ethannicholas2ec06c92016-06-13 10:20:52 -0700135 return result;
joshualitt40836102016-03-11 11:45:53 -0800136#else
ethannicholas2ec06c92016-06-13 10:20:52 -0700137 return nullptr;
joshualitt40836102016-03-11 11:45:53 -0800138#endif
joshualittae47aee2016-03-10 13:29:36 -0800139}
140
141SkIRect Request::getBounds() {
142 SkIRect bounds;
143 if (fPicture) {
144 bounds = fPicture->cullRect().roundOut();
145 if (fGPUEnabled) {
joshualitt40836102016-03-11 11:45:53 -0800146#if SK_SUPPORT_GPU
joshualittae47aee2016-03-10 13:29:36 -0800147 int maxRTSize = this->getContext()->caps()->maxRenderTargetSize();
148 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), maxRTSize),
149 SkTMin(bounds.height(), maxRTSize));
joshualitt40836102016-03-11 11:45:53 -0800150#endif
joshualittae47aee2016-03-10 13:29:36 -0800151 }
152 } else {
153 bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight);
154 }
155
jcgregorio9a7acdc2016-06-30 07:54:14 -0700156 // We clip to kMaxWidth / kMaxHeight for performance reasons.
joshualittae47aee2016-03-10 13:29:36 -0800157 // TODO make this configurable
jcgregorio9a7acdc2016-06-30 07:54:14 -0700158 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kMaxWidth),
159 SkTMin(bounds.height(), kMaxHeight));
joshualittae47aee2016-03-10 13:29:36 -0800160 return bounds;
161}
162
brianosman78312952016-04-19 10:16:53 -0700163namespace {
164
165struct ColorAndProfile {
166 SkColorType fColorType;
brianosmanb109b8c2016-06-16 13:03:24 -0700167 bool fSRGB;
brianosman78312952016-04-19 10:16:53 -0700168};
169
170ColorAndProfile ColorModes[] = {
brianosman3a0dbde2016-07-26 11:36:05 -0700171 { kN32_SkColorType, false },
172 { kN32_SkColorType, true },
173 { kRGBA_F16_SkColorType, true },
brianosman78312952016-04-19 10:16:53 -0700174};
175
176}
177
joshualitt4dcbe432016-02-25 10:50:28 -0800178SkSurface* Request::createCPUSurface() {
joshualittae47aee2016-03-10 13:29:36 -0800179 SkIRect bounds = this->getBounds();
brianosman78312952016-04-19 10:16:53 -0700180 ColorAndProfile cap = ColorModes[fColorMode];
raftias7c602de2016-10-13 10:45:44 -0700181 auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500182 ? SkColorSpace::MakeSRGBLinear()
183 : SkColorSpace::MakeSRGB();
brianosman78312952016-04-19 10:16:53 -0700184 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
brianosman0e22eb82016-08-30 07:07:59 -0700185 kPremul_SkAlphaType, cap.fSRGB ? colorSpace : nullptr);
brianosman3a0dbde2016-07-26 11:36:05 -0700186 return SkSurface::MakeRaster(info).release();
joshualitt4dcbe432016-02-25 10:50:28 -0800187}
188
189SkSurface* Request::createGPUSurface() {
joshualittae47aee2016-03-10 13:29:36 -0800190 GrContext* context = this->getContext();
191 SkIRect bounds = this->getBounds();
brianosman78312952016-04-19 10:16:53 -0700192 ColorAndProfile cap = ColorModes[fColorMode];
raftias7c602de2016-10-13 10:45:44 -0700193 auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500194 ? SkColorSpace::MakeSRGBLinear()
195 : SkColorSpace::MakeSRGB();
brianosman78312952016-04-19 10:16:53 -0700196 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
brianosman0e22eb82016-08-30 07:07:59 -0700197 kPremul_SkAlphaType, cap.fSRGB ? colorSpace: nullptr);
brianosman3a0dbde2016-07-26 11:36:05 -0700198 SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info).release();
joshualitt4dcbe432016-02-25 10:50:28 -0800199 return surface;
200}
201
Ben Wagnerc03e1c52016-10-17 15:20:02 -0400202bool Request::setOverdraw(bool enable) {
203 fOverdraw = enable;
204 return true;
205}
206
brianosman78312952016-04-19 10:16:53 -0700207bool Request::setColorMode(int mode) {
208 fColorMode = mode;
209 return enableGPU(fGPUEnabled);
210}
211
halcanary9d524f22016-03-29 09:03:52 -0700212bool Request::enableGPU(bool enable) {
joshualittee5348b2016-02-26 08:36:25 -0800213 if (enable) {
214 SkSurface* surface = this->createGPUSurface();
215 if (surface) {
216 fSurface.reset(surface);
217 fGPUEnabled = true;
joshualitt98bd5b12016-03-11 12:08:15 -0800218
219 // When we switch to GPU, there seems to be some mystery draws in the canvas. So we
220 // draw once to flush the pipe
221 // TODO understand what is actually happening here
brianosman78312952016-04-19 10:16:53 -0700222 if (fDebugCanvas) {
223 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
224 this->getCanvas()->flush();
225 }
joshualitt98bd5b12016-03-11 12:08:15 -0800226
joshualittee5348b2016-02-26 08:36:25 -0800227 return true;
228 }
229 return false;
230 }
231 fSurface.reset(this->createCPUSurface());
232 fGPUEnabled = false;
233 return true;
halcanary9d524f22016-03-29 09:03:52 -0700234}
joshualitt6bc96792016-02-29 05:35:04 -0800235
236bool Request::initPictureFromStream(SkStream* stream) {
237 // parse picture from stream
reedca2622b2016-03-18 07:25:55 -0700238 fPicture = SkPicture::MakeFromStream(stream);
239 if (!fPicture) {
joshualitt6bc96792016-02-29 05:35:04 -0800240 fprintf(stderr, "Could not create picture from stream.\n");
241 return false;
242 }
243
joshualittae47aee2016-03-10 13:29:36 -0800244 // reinitialize canvas with the new picture dimensions
245 this->enableGPU(fGPUEnabled);
246
joshualitt6bc96792016-02-29 05:35:04 -0800247 // pour picture into debug canvas
joshualittae47aee2016-03-10 13:29:36 -0800248 SkIRect bounds = this->getBounds();
joshualitte0449cf2016-03-09 10:07:02 -0800249 fDebugCanvas.reset(new SkDebugCanvas(bounds.width(), bounds.height()));
joshualitt6bc96792016-02-29 05:35:04 -0800250 fDebugCanvas->drawPicture(fPicture);
joshualitt3a9be692016-02-29 11:38:11 -0800251
252 // for some reason we need to 'flush' the debug canvas by drawing all of the ops
253 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
joshualittb0666ad2016-03-08 10:43:41 -0800254 this->getCanvas()->flush();
joshualitt6bc96792016-02-29 05:35:04 -0800255 return true;
joshualittee5348b2016-02-26 08:36:25 -0800256}
257
bungeman38d909e2016-08-02 14:40:46 -0700258sk_sp<SkData> Request::getJsonOps(int n) {
joshualitt1e5884b2016-02-26 08:22:49 -0800259 SkCanvas* canvas = this->getCanvas();
260 Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas);
261 root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu");
Brian Salomonf09492b2016-12-21 15:40:26 -0500262 root["drawGpuOpBounds"] = Json::Value(fDebugCanvas->getDrawGpuOpBounds());
brianosman78312952016-04-19 10:16:53 -0700263 root["colorMode"] = Json::Value(fColorMode);
joshualitt1e5884b2016-02-26 08:22:49 -0800264 SkDynamicMemoryWStream stream;
265 stream.writeText(Json::FastWriter().write(root).c_str());
266
reed42943c82016-09-12 12:01:44 -0700267 return stream.detachAsData();
joshualitt1e5884b2016-02-26 08:22:49 -0800268}
269
Brian Salomon144a5c52016-12-20 16:48:59 -0500270sk_sp<SkData> Request::getJsonOpList(int n) {
joshualitt1e5884b2016-02-26 08:22:49 -0800271 SkCanvas* canvas = this->getCanvas();
272 SkASSERT(fGPUEnabled);
273
Brian Salomon144a5c52016-12-20 16:48:59 -0500274 Json::Value result = fDebugCanvas->toJSONOpList(n, canvas);
joshualitt1e5884b2016-02-26 08:22:49 -0800275
276 SkDynamicMemoryWStream stream;
joshualittae47aee2016-03-10 13:29:36 -0800277 stream.writeText(Json::FastWriter().write(result).c_str());
joshualitt1e5884b2016-02-26 08:22:49 -0800278
reed42943c82016-09-12 12:01:44 -0700279 return stream.detachAsData();
joshualitt1e5884b2016-02-26 08:22:49 -0800280}
joshualittee5348b2016-02-26 08:36:25 -0800281
bungeman38d909e2016-08-02 14:40:46 -0700282sk_sp<SkData> Request::getJsonInfo(int n) {
joshualittee5348b2016-02-26 08:36:25 -0800283 // drawTo
Hal Canary1b612a82016-11-03 16:26:13 -0400284 sk_sp<SkSurface> surface(this->createCPUSurface());
joshualittee5348b2016-02-26 08:36:25 -0800285 SkCanvas* canvas = surface->getCanvas();
286
287 // TODO this is really slow and we should cache the matrix and clip
288 fDebugCanvas->drawTo(canvas, n);
289
290 // make some json
291 SkMatrix vm = fDebugCanvas->getCurrentMatrix();
292 SkIRect clip = fDebugCanvas->getCurrentClip();
293 Json::Value info(Json::objectValue);
joshualittbd724132016-03-03 11:39:38 -0800294 info["ViewMatrix"] = SkDrawCommand::MakeJsonMatrix(vm);
295 info["ClipRect"] = SkDrawCommand::MakeJsonIRect(clip);
joshualittee5348b2016-02-26 08:36:25 -0800296
297 std::string json = Json::FastWriter().write(info);
298
299 // We don't want the null terminator so strlen is correct
bungeman38d909e2016-08-02 14:40:46 -0700300 return SkData::MakeWithCopy(json.c_str(), strlen(json.c_str()));
joshualittee5348b2016-02-26 08:36:25 -0800301}
joshualitte0449cf2016-03-09 10:07:02 -0800302
303SkColor Request::getPixel(int x, int y) {
304 SkCanvas* canvas = this->getCanvas();
305 canvas->flush();
Ben Wagner145dbcd2016-11-03 14:40:50 -0400306 std::unique_ptr<SkBitmap> bitmap(this->getBitmapFromCanvas(canvas));
joshualitte0449cf2016-03-09 10:07:02 -0800307 SkASSERT(bitmap);
brianosman78312952016-04-19 10:16:53 -0700308
309 // Convert to format suitable for inspection
310 sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bitmap);
reed42943c82016-09-12 12:01:44 -0700311 SkASSERT(encodedBitmap);
brianosman78312952016-04-19 10:16:53 -0700312
313 const uint8_t* start = encodedBitmap->bytes() + ((y * bitmap->width() + x) * 4);
joshualitte0449cf2016-03-09 10:07:02 -0800314 SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]);
joshualitte0449cf2016-03-09 10:07:02 -0800315 return result;
316}