blob: 982bd362eac23be4bd6d96080b8a5e2f01a7cc70 [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"
Hal Canarydb683012016-11-23 08:55:18 -070011#include "sk_tool_utils.h"
joshualitt4dcbe432016-02-25 10:50:28 -080012
bsalomon3724e572016-03-30 18:56:19 -070013using namespace sk_gpu_test;
14
joshualittae47aee2016-03-10 13:29:36 -080015static int kDefaultWidth = 1920;
16static int kDefaultHeight = 1080;
jcgregorio9a7acdc2016-06-30 07:54:14 -070017static int kMaxWidth = 8192;
18static int kMaxHeight = 8192;
joshualittae47aee2016-03-10 13:29:36 -080019
joshualitt4dcbe432016-02-25 10:50:28 -080020
joshualittee5348b2016-02-26 08:36:25 -080021Request::Request(SkString rootUrl)
22 : fUploadContext(nullptr)
23 , fUrlDataManager(rootUrl)
brianosman78312952016-04-19 10:16:53 -070024 , fGPUEnabled(false)
Ben Wagnerc03e1c52016-10-17 15:20:02 -040025 , fOverdraw(false)
brianosman78312952016-04-19 10:16:53 -070026 , fColorMode(0) {
joshualittee5348b2016-02-26 08:36:25 -080027 // create surface
28 GrContextOptions grContextOpts;
joshualitt40836102016-03-11 11:45:53 -080029 fContextFactory = new GrContextFactory(grContextOpts);
joshualitt40836102016-03-11 11:45:53 -080030}
31
32Request::~Request() {
joshualitt40836102016-03-11 11:45:53 -080033 if (fContextFactory) {
34 delete fContextFactory;
35 }
joshualittee5348b2016-02-26 08:36:25 -080036}
37
bungeman38d909e2016-08-02 14:40:46 -070038sk_sp<SkData> Request::writeCanvasToPng(SkCanvas* canvas) {
joshualitt4dcbe432016-02-25 10:50:28 -080039 // capture pixels
Brian Osmand9ea8162018-08-08 17:03:39 -040040 SkBitmap bmp;
41 bmp.allocPixels(canvas->imageInfo());
42 SkAssertResult(canvas->readPixels(bmp, 0, 0));
brianosman78312952016-04-19 10:16:53 -070043
msaretta5cf4f42016-06-30 10:06:51 -070044 // write to an opaque png (black background)
joshualitt4dcbe432016-02-25 10:50:28 -080045 SkDynamicMemoryWStream buffer;
Brian Osmand9ea8162018-08-08 17:03:39 -040046 SkDrawCommand::WritePNG(bmp, buffer);
reed42943c82016-09-12 12:01:44 -070047 return buffer.detachAsData();
joshualitt4dcbe432016-02-25 10:50:28 -080048}
49
50SkCanvas* Request::getCanvas() {
51 GrContextFactory* factory = fContextFactory;
Brian Salomon6405e712017-03-20 08:54:16 -040052 GLTestContext* gl = factory->getContextInfo(GrContextFactory::kGL_ContextType,
53 GrContextFactory::ContextOverrides::kNone).glContext();
54 if (!gl) {
55 gl = factory->getContextInfo(GrContextFactory::kGLES_ContextType,
56 GrContextFactory::ContextOverrides::kNone).glContext();
57 }
ethannicholas2ec06c92016-06-13 10:20:52 -070058 if (gl) {
59 gl->makeCurrent();
60 }
joshualitt4dcbe432016-02-25 10:50:28 -080061 SkASSERT(fDebugCanvas);
joshualitte0449cf2016-03-09 10:07:02 -080062
63 // create the appropriate surface if necessary
64 if (!fSurface) {
65 this->enableGPU(fGPUEnabled);
66 }
joshualitt4dcbe432016-02-25 10:50:28 -080067 SkCanvas* target = fSurface->getCanvas();
68 return target;
69}
70
bungeman38d909e2016-08-02 14:40:46 -070071sk_sp<SkData> Request::drawToPng(int n, int m) {
Ben Wagnerc03e1c52016-10-17 15:20:02 -040072 //fDebugCanvas->setOverdrawViz(true);
Brian Osmand9ea8162018-08-08 17:03:39 -040073 fDebugCanvas->drawTo(this->getCanvas(), n, m);
Ben Wagnerc03e1c52016-10-17 15:20:02 -040074 //fDebugCanvas->setOverdrawViz(false);
joshualitt4dcbe432016-02-25 10:50:28 -080075 return writeCanvasToPng(this->getCanvas());
76}
77
bungeman38d909e2016-08-02 14:40:46 -070078sk_sp<SkData> Request::writeOutSkp() {
joshualitte0449cf2016-03-09 10:07:02 -080079 // Playback into picture recorder
joshualittae47aee2016-03-10 13:29:36 -080080 SkIRect bounds = this->getBounds();
joshualitte0449cf2016-03-09 10:07:02 -080081 SkPictureRecorder recorder;
brianosman82996b82016-04-20 10:52:54 -070082 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bounds.width()),
83 SkIntToScalar(bounds.height()));
joshualitte0449cf2016-03-09 10:07:02 -080084
85 fDebugCanvas->draw(canvas);
86
Mike Reedef038482017-12-16 08:41:28 -050087 return recorder.finishRecordingAsPicture()->serialize();
joshualitte0449cf2016-03-09 10:07:02 -080088}
89
joshualittae47aee2016-03-10 13:29:36 -080090GrContext* Request::getContext() {
Brian Salomon6405e712017-03-20 08:54:16 -040091 GrContext* result = fContextFactory->get(GrContextFactory::kGL_ContextType,
csmartdaltone812d492017-02-21 12:36:05 -070092 GrContextFactory::ContextOverrides::kNone);
ethannicholas2ec06c92016-06-13 10:20:52 -070093 if (!result) {
Brian Salomon6405e712017-03-20 08:54:16 -040094 result = fContextFactory->get(GrContextFactory::kGLES_ContextType,
95 GrContextFactory::ContextOverrides::kNone);
96 }
ethannicholas2ec06c92016-06-13 10:20:52 -070097 return result;
joshualittae47aee2016-03-10 13:29:36 -080098}
99
100SkIRect Request::getBounds() {
101 SkIRect bounds;
102 if (fPicture) {
103 bounds = fPicture->cullRect().roundOut();
104 if (fGPUEnabled) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400105 int maxRTSize = this->getContext()->maxRenderTargetSize();
joshualittae47aee2016-03-10 13:29:36 -0800106 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), maxRTSize),
107 SkTMin(bounds.height(), maxRTSize));
108 }
109 } else {
110 bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight);
111 }
112
jcgregorio9a7acdc2016-06-30 07:54:14 -0700113 // We clip to kMaxWidth / kMaxHeight for performance reasons.
joshualittae47aee2016-03-10 13:29:36 -0800114 // TODO make this configurable
jcgregorio9a7acdc2016-06-30 07:54:14 -0700115 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kMaxWidth),
116 SkTMin(bounds.height(), kMaxHeight));
joshualittae47aee2016-03-10 13:29:36 -0800117 return bounds;
118}
119
brianosman78312952016-04-19 10:16:53 -0700120namespace {
121
122struct ColorAndProfile {
123 SkColorType fColorType;
brianosmanb109b8c2016-06-16 13:03:24 -0700124 bool fSRGB;
brianosman78312952016-04-19 10:16:53 -0700125};
126
127ColorAndProfile ColorModes[] = {
brianosman3a0dbde2016-07-26 11:36:05 -0700128 { kN32_SkColorType, false },
129 { kN32_SkColorType, true },
130 { kRGBA_F16_SkColorType, true },
brianosman78312952016-04-19 10:16:53 -0700131};
132
133}
134
joshualitt4dcbe432016-02-25 10:50:28 -0800135SkSurface* Request::createCPUSurface() {
joshualittae47aee2016-03-10 13:29:36 -0800136 SkIRect bounds = this->getBounds();
brianosman78312952016-04-19 10:16:53 -0700137 ColorAndProfile cap = ColorModes[fColorMode];
raftias7c602de2016-10-13 10:45:44 -0700138 auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500139 ? SkColorSpace::MakeSRGBLinear()
140 : SkColorSpace::MakeSRGB();
brianosman78312952016-04-19 10:16:53 -0700141 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
brianosman0e22eb82016-08-30 07:07:59 -0700142 kPremul_SkAlphaType, cap.fSRGB ? colorSpace : nullptr);
brianosman3a0dbde2016-07-26 11:36:05 -0700143 return SkSurface::MakeRaster(info).release();
joshualitt4dcbe432016-02-25 10:50:28 -0800144}
145
146SkSurface* Request::createGPUSurface() {
joshualittae47aee2016-03-10 13:29:36 -0800147 GrContext* context = this->getContext();
148 SkIRect bounds = this->getBounds();
brianosman78312952016-04-19 10:16:53 -0700149 ColorAndProfile cap = ColorModes[fColorMode];
raftias7c602de2016-10-13 10:45:44 -0700150 auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500151 ? SkColorSpace::MakeSRGBLinear()
152 : SkColorSpace::MakeSRGB();
brianosman78312952016-04-19 10:16:53 -0700153 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
brianosman0e22eb82016-08-30 07:07:59 -0700154 kPremul_SkAlphaType, cap.fSRGB ? colorSpace: nullptr);
brianosman3a0dbde2016-07-26 11:36:05 -0700155 SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info).release();
joshualitt4dcbe432016-02-25 10:50:28 -0800156 return surface;
157}
158
Ben Wagnerc03e1c52016-10-17 15:20:02 -0400159bool Request::setOverdraw(bool enable) {
160 fOverdraw = enable;
161 return true;
162}
163
brianosman78312952016-04-19 10:16:53 -0700164bool Request::setColorMode(int mode) {
165 fColorMode = mode;
166 return enableGPU(fGPUEnabled);
167}
168
halcanary9d524f22016-03-29 09:03:52 -0700169bool Request::enableGPU(bool enable) {
joshualittee5348b2016-02-26 08:36:25 -0800170 if (enable) {
171 SkSurface* surface = this->createGPUSurface();
172 if (surface) {
173 fSurface.reset(surface);
174 fGPUEnabled = true;
joshualitt98bd5b12016-03-11 12:08:15 -0800175
176 // When we switch to GPU, there seems to be some mystery draws in the canvas. So we
177 // draw once to flush the pipe
178 // TODO understand what is actually happening here
brianosman78312952016-04-19 10:16:53 -0700179 if (fDebugCanvas) {
180 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
181 this->getCanvas()->flush();
182 }
joshualitt98bd5b12016-03-11 12:08:15 -0800183
joshualittee5348b2016-02-26 08:36:25 -0800184 return true;
185 }
186 return false;
187 }
188 fSurface.reset(this->createCPUSurface());
189 fGPUEnabled = false;
190 return true;
halcanary9d524f22016-03-29 09:03:52 -0700191}
joshualitt6bc96792016-02-29 05:35:04 -0800192
193bool Request::initPictureFromStream(SkStream* stream) {
194 // parse picture from stream
reedca2622b2016-03-18 07:25:55 -0700195 fPicture = SkPicture::MakeFromStream(stream);
196 if (!fPicture) {
joshualitt6bc96792016-02-29 05:35:04 -0800197 fprintf(stderr, "Could not create picture from stream.\n");
198 return false;
199 }
200
joshualittae47aee2016-03-10 13:29:36 -0800201 // reinitialize canvas with the new picture dimensions
202 this->enableGPU(fGPUEnabled);
203
joshualitt6bc96792016-02-29 05:35:04 -0800204 // pour picture into debug canvas
joshualittae47aee2016-03-10 13:29:36 -0800205 SkIRect bounds = this->getBounds();
joshualitte0449cf2016-03-09 10:07:02 -0800206 fDebugCanvas.reset(new SkDebugCanvas(bounds.width(), bounds.height()));
joshualitt6bc96792016-02-29 05:35:04 -0800207 fDebugCanvas->drawPicture(fPicture);
joshualitt3a9be692016-02-29 11:38:11 -0800208
209 // for some reason we need to 'flush' the debug canvas by drawing all of the ops
210 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
joshualittb0666ad2016-03-08 10:43:41 -0800211 this->getCanvas()->flush();
joshualitt6bc96792016-02-29 05:35:04 -0800212 return true;
joshualittee5348b2016-02-26 08:36:25 -0800213}
214
bungeman38d909e2016-08-02 14:40:46 -0700215sk_sp<SkData> Request::getJsonOps(int n) {
joshualitt1e5884b2016-02-26 08:22:49 -0800216 SkCanvas* canvas = this->getCanvas();
217 Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas);
218 root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu");
Brian Salomonf09492b2016-12-21 15:40:26 -0500219 root["drawGpuOpBounds"] = Json::Value(fDebugCanvas->getDrawGpuOpBounds());
brianosman78312952016-04-19 10:16:53 -0700220 root["colorMode"] = Json::Value(fColorMode);
joshualitt1e5884b2016-02-26 08:22:49 -0800221 SkDynamicMemoryWStream stream;
222 stream.writeText(Json::FastWriter().write(root).c_str());
223
reed42943c82016-09-12 12:01:44 -0700224 return stream.detachAsData();
joshualitt1e5884b2016-02-26 08:22:49 -0800225}
226
Brian Salomon144a5c52016-12-20 16:48:59 -0500227sk_sp<SkData> Request::getJsonOpList(int n) {
joshualitt1e5884b2016-02-26 08:22:49 -0800228 SkCanvas* canvas = this->getCanvas();
229 SkASSERT(fGPUEnabled);
230
Brian Salomon144a5c52016-12-20 16:48:59 -0500231 Json::Value result = fDebugCanvas->toJSONOpList(n, canvas);
joshualitt1e5884b2016-02-26 08:22:49 -0800232
233 SkDynamicMemoryWStream stream;
joshualittae47aee2016-03-10 13:29:36 -0800234 stream.writeText(Json::FastWriter().write(result).c_str());
joshualitt1e5884b2016-02-26 08:22:49 -0800235
reed42943c82016-09-12 12:01:44 -0700236 return stream.detachAsData();
joshualitt1e5884b2016-02-26 08:22:49 -0800237}
joshualittee5348b2016-02-26 08:36:25 -0800238
bungeman38d909e2016-08-02 14:40:46 -0700239sk_sp<SkData> Request::getJsonInfo(int n) {
joshualittee5348b2016-02-26 08:36:25 -0800240 // drawTo
Hal Canary1b612a82016-11-03 16:26:13 -0400241 sk_sp<SkSurface> surface(this->createCPUSurface());
joshualittee5348b2016-02-26 08:36:25 -0800242 SkCanvas* canvas = surface->getCanvas();
243
244 // TODO this is really slow and we should cache the matrix and clip
245 fDebugCanvas->drawTo(canvas, n);
246
247 // make some json
248 SkMatrix vm = fDebugCanvas->getCurrentMatrix();
249 SkIRect clip = fDebugCanvas->getCurrentClip();
250 Json::Value info(Json::objectValue);
joshualittbd724132016-03-03 11:39:38 -0800251 info["ViewMatrix"] = SkDrawCommand::MakeJsonMatrix(vm);
252 info["ClipRect"] = SkDrawCommand::MakeJsonIRect(clip);
joshualittee5348b2016-02-26 08:36:25 -0800253
254 std::string json = Json::FastWriter().write(info);
255
256 // We don't want the null terminator so strlen is correct
bungeman38d909e2016-08-02 14:40:46 -0700257 return SkData::MakeWithCopy(json.c_str(), strlen(json.c_str()));
joshualittee5348b2016-02-26 08:36:25 -0800258}
joshualitte0449cf2016-03-09 10:07:02 -0800259
260SkColor Request::getPixel(int x, int y) {
Brian Osmand9ea8162018-08-08 17:03:39 -0400261 SkBitmap bmp;
262 bmp.allocPixels(this->getCanvas()->imageInfo().makeWH(1, 1));
263 SkAssertResult(this->getCanvas()->readPixels(bmp, x, y));
264 return bmp.getColor(0, 0);
joshualitte0449cf2016-03-09 10:07:02 -0800265}