blob: d1286be77ffd7c0989ad1b542fe545617a2ebbcc [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
Brian Osmand8a90f92019-01-28 13:41:19 -050010#include "SkJSONWriter.h"
joshualitte0449cf2016-03-09 10:07:02 -080011#include "SkPictureRecorder.h"
Hal Canarydb683012016-11-23 08:55:18 -070012#include "sk_tool_utils.h"
joshualitt4dcbe432016-02-25 10:50:28 -080013
bsalomon3724e572016-03-30 18:56:19 -070014using namespace sk_gpu_test;
15
joshualittae47aee2016-03-10 13:29:36 -080016static int kDefaultWidth = 1920;
17static int kDefaultHeight = 1080;
jcgregorio9a7acdc2016-06-30 07:54:14 -070018static int kMaxWidth = 8192;
19static int kMaxHeight = 8192;
joshualittae47aee2016-03-10 13:29:36 -080020
joshualitt4dcbe432016-02-25 10:50:28 -080021
joshualittee5348b2016-02-26 08:36:25 -080022Request::Request(SkString rootUrl)
23 : fUploadContext(nullptr)
24 , fUrlDataManager(rootUrl)
brianosman78312952016-04-19 10:16:53 -070025 , fGPUEnabled(false)
Ben Wagnerc03e1c52016-10-17 15:20:02 -040026 , fOverdraw(false)
brianosman78312952016-04-19 10:16:53 -070027 , fColorMode(0) {
joshualittee5348b2016-02-26 08:36:25 -080028 // create surface
29 GrContextOptions grContextOpts;
joshualitt40836102016-03-11 11:45:53 -080030 fContextFactory = new GrContextFactory(grContextOpts);
joshualitt40836102016-03-11 11:45:53 -080031}
32
33Request::~Request() {
joshualitt40836102016-03-11 11:45:53 -080034 if (fContextFactory) {
35 delete fContextFactory;
36 }
joshualittee5348b2016-02-26 08:36:25 -080037}
38
bungeman38d909e2016-08-02 14:40:46 -070039sk_sp<SkData> Request::writeCanvasToPng(SkCanvas* canvas) {
joshualitt4dcbe432016-02-25 10:50:28 -080040 // capture pixels
Brian Osmand9ea8162018-08-08 17:03:39 -040041 SkBitmap bmp;
42 bmp.allocPixels(canvas->imageInfo());
43 SkAssertResult(canvas->readPixels(bmp, 0, 0));
brianosman78312952016-04-19 10:16:53 -070044
msaretta5cf4f42016-06-30 10:06:51 -070045 // write to an opaque png (black background)
joshualitt4dcbe432016-02-25 10:50:28 -080046 SkDynamicMemoryWStream buffer;
Brian Osmand9ea8162018-08-08 17:03:39 -040047 SkDrawCommand::WritePNG(bmp, buffer);
reed42943c82016-09-12 12:01:44 -070048 return buffer.detachAsData();
joshualitt4dcbe432016-02-25 10:50:28 -080049}
50
51SkCanvas* Request::getCanvas() {
52 GrContextFactory* factory = fContextFactory;
Brian Salomon6405e712017-03-20 08:54:16 -040053 GLTestContext* gl = factory->getContextInfo(GrContextFactory::kGL_ContextType,
54 GrContextFactory::ContextOverrides::kNone).glContext();
55 if (!gl) {
56 gl = factory->getContextInfo(GrContextFactory::kGLES_ContextType,
57 GrContextFactory::ContextOverrides::kNone).glContext();
58 }
ethannicholas2ec06c92016-06-13 10:20:52 -070059 if (gl) {
60 gl->makeCurrent();
61 }
joshualitt4dcbe432016-02-25 10:50:28 -080062 SkASSERT(fDebugCanvas);
joshualitte0449cf2016-03-09 10:07:02 -080063
64 // create the appropriate surface if necessary
65 if (!fSurface) {
66 this->enableGPU(fGPUEnabled);
67 }
joshualitt4dcbe432016-02-25 10:50:28 -080068 SkCanvas* target = fSurface->getCanvas();
69 return target;
70}
71
bungeman38d909e2016-08-02 14:40:46 -070072sk_sp<SkData> Request::drawToPng(int n, int m) {
Ben Wagnerc03e1c52016-10-17 15:20:02 -040073 //fDebugCanvas->setOverdrawViz(true);
Brian Osmand9ea8162018-08-08 17:03:39 -040074 fDebugCanvas->drawTo(this->getCanvas(), n, m);
Ben Wagnerc03e1c52016-10-17 15:20:02 -040075 //fDebugCanvas->setOverdrawViz(false);
joshualitt4dcbe432016-02-25 10:50:28 -080076 return writeCanvasToPng(this->getCanvas());
77}
78
bungeman38d909e2016-08-02 14:40:46 -070079sk_sp<SkData> Request::writeOutSkp() {
joshualitte0449cf2016-03-09 10:07:02 -080080 // Playback into picture recorder
joshualittae47aee2016-03-10 13:29:36 -080081 SkIRect bounds = this->getBounds();
joshualitte0449cf2016-03-09 10:07:02 -080082 SkPictureRecorder recorder;
brianosman82996b82016-04-20 10:52:54 -070083 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bounds.width()),
84 SkIntToScalar(bounds.height()));
joshualitte0449cf2016-03-09 10:07:02 -080085
86 fDebugCanvas->draw(canvas);
87
Mike Reedef038482017-12-16 08:41:28 -050088 return recorder.finishRecordingAsPicture()->serialize();
joshualitte0449cf2016-03-09 10:07:02 -080089}
90
joshualittae47aee2016-03-10 13:29:36 -080091GrContext* Request::getContext() {
Brian Salomon6405e712017-03-20 08:54:16 -040092 GrContext* result = fContextFactory->get(GrContextFactory::kGL_ContextType,
csmartdaltone812d492017-02-21 12:36:05 -070093 GrContextFactory::ContextOverrides::kNone);
ethannicholas2ec06c92016-06-13 10:20:52 -070094 if (!result) {
Brian Salomon6405e712017-03-20 08:54:16 -040095 result = fContextFactory->get(GrContextFactory::kGLES_ContextType,
96 GrContextFactory::ContextOverrides::kNone);
97 }
ethannicholas2ec06c92016-06-13 10:20:52 -070098 return result;
joshualittae47aee2016-03-10 13:29:36 -080099}
100
101SkIRect Request::getBounds() {
102 SkIRect bounds;
103 if (fPicture) {
104 bounds = fPicture->cullRect().roundOut();
105 if (fGPUEnabled) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400106 int maxRTSize = this->getContext()->maxRenderTargetSize();
joshualittae47aee2016-03-10 13:29:36 -0800107 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), maxRTSize),
108 SkTMin(bounds.height(), maxRTSize));
109 }
110 } else {
111 bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight);
112 }
113
jcgregorio9a7acdc2016-06-30 07:54:14 -0700114 // We clip to kMaxWidth / kMaxHeight for performance reasons.
joshualittae47aee2016-03-10 13:29:36 -0800115 // TODO make this configurable
jcgregorio9a7acdc2016-06-30 07:54:14 -0700116 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kMaxWidth),
117 SkTMin(bounds.height(), kMaxHeight));
joshualittae47aee2016-03-10 13:29:36 -0800118 return bounds;
119}
120
brianosman78312952016-04-19 10:16:53 -0700121namespace {
122
123struct ColorAndProfile {
124 SkColorType fColorType;
brianosmanb109b8c2016-06-16 13:03:24 -0700125 bool fSRGB;
brianosman78312952016-04-19 10:16:53 -0700126};
127
128ColorAndProfile ColorModes[] = {
brianosman3a0dbde2016-07-26 11:36:05 -0700129 { kN32_SkColorType, false },
130 { kN32_SkColorType, true },
131 { kRGBA_F16_SkColorType, true },
brianosman78312952016-04-19 10:16:53 -0700132};
133
134}
135
joshualitt4dcbe432016-02-25 10:50:28 -0800136SkSurface* Request::createCPUSurface() {
joshualittae47aee2016-03-10 13:29:36 -0800137 SkIRect bounds = this->getBounds();
brianosman78312952016-04-19 10:16:53 -0700138 ColorAndProfile cap = ColorModes[fColorMode];
raftias7c602de2016-10-13 10:45:44 -0700139 auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500140 ? SkColorSpace::MakeSRGBLinear()
141 : SkColorSpace::MakeSRGB();
brianosman78312952016-04-19 10:16:53 -0700142 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
brianosman0e22eb82016-08-30 07:07:59 -0700143 kPremul_SkAlphaType, cap.fSRGB ? colorSpace : nullptr);
brianosman3a0dbde2016-07-26 11:36:05 -0700144 return SkSurface::MakeRaster(info).release();
joshualitt4dcbe432016-02-25 10:50:28 -0800145}
146
147SkSurface* Request::createGPUSurface() {
joshualittae47aee2016-03-10 13:29:36 -0800148 GrContext* context = this->getContext();
149 SkIRect bounds = this->getBounds();
brianosman78312952016-04-19 10:16:53 -0700150 ColorAndProfile cap = ColorModes[fColorMode];
raftias7c602de2016-10-13 10:45:44 -0700151 auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500152 ? SkColorSpace::MakeSRGBLinear()
153 : SkColorSpace::MakeSRGB();
brianosman78312952016-04-19 10:16:53 -0700154 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
brianosman0e22eb82016-08-30 07:07:59 -0700155 kPremul_SkAlphaType, cap.fSRGB ? colorSpace: nullptr);
brianosman3a0dbde2016-07-26 11:36:05 -0700156 SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info).release();
joshualitt4dcbe432016-02-25 10:50:28 -0800157 return surface;
158}
159
Ben Wagnerc03e1c52016-10-17 15:20:02 -0400160bool Request::setOverdraw(bool enable) {
161 fOverdraw = enable;
162 return true;
163}
164
brianosman78312952016-04-19 10:16:53 -0700165bool Request::setColorMode(int mode) {
166 fColorMode = mode;
167 return enableGPU(fGPUEnabled);
168}
169
halcanary9d524f22016-03-29 09:03:52 -0700170bool Request::enableGPU(bool enable) {
joshualittee5348b2016-02-26 08:36:25 -0800171 if (enable) {
172 SkSurface* surface = this->createGPUSurface();
173 if (surface) {
174 fSurface.reset(surface);
175 fGPUEnabled = true;
joshualitt98bd5b12016-03-11 12:08:15 -0800176
177 // When we switch to GPU, there seems to be some mystery draws in the canvas. So we
178 // draw once to flush the pipe
179 // TODO understand what is actually happening here
brianosman78312952016-04-19 10:16:53 -0700180 if (fDebugCanvas) {
181 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
182 this->getCanvas()->flush();
183 }
joshualitt98bd5b12016-03-11 12:08:15 -0800184
joshualittee5348b2016-02-26 08:36:25 -0800185 return true;
186 }
187 return false;
188 }
189 fSurface.reset(this->createCPUSurface());
190 fGPUEnabled = false;
191 return true;
halcanary9d524f22016-03-29 09:03:52 -0700192}
joshualitt6bc96792016-02-29 05:35:04 -0800193
194bool Request::initPictureFromStream(SkStream* stream) {
195 // parse picture from stream
reedca2622b2016-03-18 07:25:55 -0700196 fPicture = SkPicture::MakeFromStream(stream);
197 if (!fPicture) {
joshualitt6bc96792016-02-29 05:35:04 -0800198 fprintf(stderr, "Could not create picture from stream.\n");
199 return false;
200 }
201
joshualittae47aee2016-03-10 13:29:36 -0800202 // reinitialize canvas with the new picture dimensions
203 this->enableGPU(fGPUEnabled);
204
joshualitt6bc96792016-02-29 05:35:04 -0800205 // pour picture into debug canvas
joshualittae47aee2016-03-10 13:29:36 -0800206 SkIRect bounds = this->getBounds();
joshualitte0449cf2016-03-09 10:07:02 -0800207 fDebugCanvas.reset(new SkDebugCanvas(bounds.width(), bounds.height()));
joshualitt6bc96792016-02-29 05:35:04 -0800208 fDebugCanvas->drawPicture(fPicture);
joshualitt3a9be692016-02-29 11:38:11 -0800209
210 // for some reason we need to 'flush' the debug canvas by drawing all of the ops
211 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
joshualittb0666ad2016-03-08 10:43:41 -0800212 this->getCanvas()->flush();
joshualitt6bc96792016-02-29 05:35:04 -0800213 return true;
joshualittee5348b2016-02-26 08:36:25 -0800214}
215
bungeman38d909e2016-08-02 14:40:46 -0700216sk_sp<SkData> Request::getJsonOps(int n) {
joshualitt1e5884b2016-02-26 08:22:49 -0800217 SkCanvas* canvas = this->getCanvas();
joshualitt1e5884b2016-02-26 08:22:49 -0800218 SkDynamicMemoryWStream stream;
Brian Osmand8a90f92019-01-28 13:41:19 -0500219 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
220 writer.beginObject(); // root
joshualitt1e5884b2016-02-26 08:22:49 -0800221
Brian Osmand8a90f92019-01-28 13:41:19 -0500222 writer.appendString("mode", fGPUEnabled ? "gpu" : "cpu");
223 writer.appendBool("drawGpuOpBounds", fDebugCanvas->getDrawGpuOpBounds());
224 writer.appendS32("colorMode", fColorMode);
225 fDebugCanvas->toJSON(writer, fUrlDataManager, n, canvas);
226
227 writer.endObject(); // root
228 writer.flush();
reed42943c82016-09-12 12:01:44 -0700229 return stream.detachAsData();
joshualitt1e5884b2016-02-26 08:22:49 -0800230}
231
Brian Salomon144a5c52016-12-20 16:48:59 -0500232sk_sp<SkData> Request::getJsonOpList(int n) {
joshualitt1e5884b2016-02-26 08:22:49 -0800233 SkCanvas* canvas = this->getCanvas();
234 SkASSERT(fGPUEnabled);
joshualitt1e5884b2016-02-26 08:22:49 -0800235 SkDynamicMemoryWStream stream;
Brian Osmand8a90f92019-01-28 13:41:19 -0500236 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
joshualitt1e5884b2016-02-26 08:22:49 -0800237
Brian Osmand8a90f92019-01-28 13:41:19 -0500238 fDebugCanvas->toJSONOpList(writer, n, canvas);
239
240 writer.flush();
reed42943c82016-09-12 12:01:44 -0700241 return stream.detachAsData();
joshualitt1e5884b2016-02-26 08:22:49 -0800242}
joshualittee5348b2016-02-26 08:36:25 -0800243
bungeman38d909e2016-08-02 14:40:46 -0700244sk_sp<SkData> Request::getJsonInfo(int n) {
joshualittee5348b2016-02-26 08:36:25 -0800245 // drawTo
Hal Canary1b612a82016-11-03 16:26:13 -0400246 sk_sp<SkSurface> surface(this->createCPUSurface());
joshualittee5348b2016-02-26 08:36:25 -0800247 SkCanvas* canvas = surface->getCanvas();
248
249 // TODO this is really slow and we should cache the matrix and clip
250 fDebugCanvas->drawTo(canvas, n);
251
252 // make some json
Brian Osmand8a90f92019-01-28 13:41:19 -0500253 SkDynamicMemoryWStream stream;
254 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
255
joshualittee5348b2016-02-26 08:36:25 -0800256 SkMatrix vm = fDebugCanvas->getCurrentMatrix();
257 SkIRect clip = fDebugCanvas->getCurrentClip();
joshualittee5348b2016-02-26 08:36:25 -0800258
Brian Osmand8a90f92019-01-28 13:41:19 -0500259 writer.beginObject(); // root
260 writer.appendName("ViewMatrix"); SkDrawCommand::MakeJsonMatrix(writer, vm);
261 writer.appendName("ClipRect"); SkDrawCommand::MakeJsonIRect(writer, clip);
262 writer.endObject(); // root
joshualittee5348b2016-02-26 08:36:25 -0800263
Brian Osmand8a90f92019-01-28 13:41:19 -0500264 // TODO: Old code explicitly avoided the null terminator in the returned data. Important?
265 writer.flush();
266 return stream.detachAsData();
joshualittee5348b2016-02-26 08:36:25 -0800267}
joshualitte0449cf2016-03-09 10:07:02 -0800268
269SkColor Request::getPixel(int x, int y) {
Brian Osmand9ea8162018-08-08 17:03:39 -0400270 SkBitmap bmp;
271 bmp.allocPixels(this->getCanvas()->imageInfo().makeWH(1, 1));
272 SkAssertResult(this->getCanvas()->readPixels(bmp, x, y));
273 return bmp.getColor(0, 0);
joshualitte0449cf2016-03-09 10:07:02 -0800274}