OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Request.h" | 8 #include "Request.h" |
9 | 9 |
10 #include "SkPictureRecorder.h" | 10 #include "SkPictureRecorder.h" |
11 #include "SkPixelSerializer.h" | 11 #include "SkPixelSerializer.h" |
| 12 #include "picture_utils.h" |
12 | 13 |
13 using namespace sk_gpu_test; | 14 using namespace sk_gpu_test; |
14 | 15 |
15 static int kDefaultWidth = 1920; | 16 static int kDefaultWidth = 1920; |
16 static int kDefaultHeight = 1080; | 17 static int kDefaultHeight = 1080; |
17 | 18 |
18 | 19 |
19 Request::Request(SkString rootUrl) | 20 Request::Request(SkString rootUrl) |
20 : fUploadContext(nullptr) | 21 : fUploadContext(nullptr) |
21 , fUrlDataManager(rootUrl) | 22 , fUrlDataManager(rootUrl) |
22 , fGPUEnabled(false) { | 23 , fGPUEnabled(false) |
| 24 , fColorMode(0) { |
23 // create surface | 25 // create surface |
24 #if SK_SUPPORT_GPU | 26 #if SK_SUPPORT_GPU |
25 GrContextOptions grContextOpts; | 27 GrContextOptions grContextOpts; |
26 fContextFactory = new GrContextFactory(grContextOpts); | 28 fContextFactory = new GrContextFactory(grContextOpts); |
27 #else | 29 #else |
28 fContextFactory = nullptr; | 30 fContextFactory = nullptr; |
29 #endif | 31 #endif |
30 } | 32 } |
31 | 33 |
32 Request::~Request() { | 34 Request::~Request() { |
33 #if SK_SUPPORT_GPU | 35 #if SK_SUPPORT_GPU |
34 if (fContextFactory) { | 36 if (fContextFactory) { |
35 delete fContextFactory; | 37 delete fContextFactory; |
36 } | 38 } |
37 #endif | 39 #endif |
38 } | 40 } |
39 | 41 |
40 SkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) { | 42 SkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) { |
41 SkBitmap* bmp = new SkBitmap(); | 43 SkBitmap* bmp = new SkBitmap(); |
42 SkIRect bounds = this->getBounds(); | 44 bmp->setInfo(canvas->imageInfo()); |
43 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), | |
44 kRGBA_8888_SkColorType, kOpaque_SkAlpha
Type); | |
45 bmp->setInfo(info); | |
46 if (!canvas->readPixels(bmp, 0, 0)) { | 45 if (!canvas->readPixels(bmp, 0, 0)) { |
47 fprintf(stderr, "Can't read pixels\n"); | 46 fprintf(stderr, "Can't read pixels\n"); |
48 return nullptr; | 47 return nullptr; |
49 } | 48 } |
50 return bmp; | 49 return bmp; |
51 } | 50 } |
52 | 51 |
53 SkData* Request::writeCanvasToPng(SkCanvas* canvas) { | 52 SkData* Request::writeCanvasToPng(SkCanvas* canvas) { |
54 // capture pixels | 53 // capture pixels |
55 SkAutoTDelete<SkBitmap> bmp(this->getBitmapFromCanvas(canvas)); | 54 SkAutoTDelete<SkBitmap> bmp(this->getBitmapFromCanvas(canvas)); |
56 SkASSERT(bmp); | 55 SkASSERT(bmp); |
57 | 56 |
| 57 // Convert to format suitable for PNG output |
| 58 sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bmp); |
| 59 SkASSERT(encodedBitmap.get()); |
| 60 |
58 // write to png | 61 // write to png |
59 SkDynamicMemoryWStream buffer; | 62 SkDynamicMemoryWStream buffer; |
60 SkDrawCommand::WritePNG((const png_bytep) bmp->getPixels(), bmp->width(), bm
p->height(), | 63 SkDrawCommand::WritePNG((const png_bytep) encodedBitmap->writable_data(), |
| 64 bmp->width(), bmp->height(), |
61 buffer); | 65 buffer); |
62 return buffer.copyToData(); | 66 return buffer.copyToData(); |
63 } | 67 } |
64 | 68 |
65 SkCanvas* Request::getCanvas() { | 69 SkCanvas* Request::getCanvas() { |
66 #if SK_SUPPORT_GPU | 70 #if SK_SUPPORT_GPU |
67 GrContextFactory* factory = fContextFactory; | 71 GrContextFactory* factory = fContextFactory; |
68 GLTestContext* gl = factory->getContextInfo(GrContextFactory::kNativeGL_Cont
extType, | 72 GLTestContext* gl = factory->getContextInfo(GrContextFactory::kNativeGL_Cont
extType, |
69 GrContextFactory::kNone_ContextOptio
ns).fGLContext; | 73 GrContextFactory::kNone_ContextOptio
ns).fGLContext; |
70 gl->makeCurrent(); | 74 gl->makeCurrent(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight); | 135 bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight); |
132 } | 136 } |
133 | 137 |
134 // We clip to kDefaultWidth / kDefaultHeight for performance reasons | 138 // We clip to kDefaultWidth / kDefaultHeight for performance reasons |
135 // TODO make this configurable | 139 // TODO make this configurable |
136 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kDefaultWidth), | 140 bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kDefaultWidth), |
137 SkTMin(bounds.height(), kDefaultHeight)); | 141 SkTMin(bounds.height(), kDefaultHeight)); |
138 return bounds; | 142 return bounds; |
139 } | 143 } |
140 | 144 |
| 145 namespace { |
| 146 |
| 147 struct ColorAndProfile { |
| 148 SkColorType fColorType; |
| 149 SkColorProfileType fProfileType; |
| 150 bool fGammaCorrect; |
| 151 }; |
| 152 |
| 153 ColorAndProfile ColorModes[] = { |
| 154 { kN32_SkColorType, kLinear_SkColorProfileType, false }, |
| 155 { kN32_SkColorType, kSRGB_SkColorProfileType, true }, |
| 156 { kRGBA_F16_SkColorType, kLinear_SkColorProfileType, true }, |
| 157 }; |
| 158 |
| 159 } |
| 160 |
141 SkSurface* Request::createCPUSurface() { | 161 SkSurface* Request::createCPUSurface() { |
142 SkIRect bounds = this->getBounds(); | 162 SkIRect bounds = this->getBounds(); |
143 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), kN32_S
kColorType, | 163 ColorAndProfile cap = ColorModes[fColorMode]; |
144 kPremul_SkAlphaType); | 164 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fC
olorType, |
145 return SkSurface::MakeRaster(info).release(); | 165 kPremul_SkAlphaType, cap.fProfileType); |
| 166 uint32_t flags = cap.fGammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag : 0; |
| 167 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
| 168 return SkSurface::MakeRaster(info, &props).release(); |
146 } | 169 } |
147 | 170 |
148 SkSurface* Request::createGPUSurface() { | 171 SkSurface* Request::createGPUSurface() { |
149 GrContext* context = this->getContext(); | 172 GrContext* context = this->getContext(); |
150 SkIRect bounds = this->getBounds(); | 173 SkIRect bounds = this->getBounds(); |
151 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), | 174 ColorAndProfile cap = ColorModes[fColorMode]; |
152 kN32_SkColorType, kPremul_SkAlphaType); | 175 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fC
olorType, |
153 uint32_t flags = 0; | 176 kPremul_SkAlphaType, cap.fProfileType); |
| 177 uint32_t flags = cap.fGammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag : 0; |
154 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | 178 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
155 SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, i
nfo, 0, | 179 SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, i
nfo, 0, |
156 &props).release(); | 180 &props).release(); |
157 return surface; | 181 return surface; |
158 } | 182 } |
159 | 183 |
| 184 bool Request::setColorMode(int mode) { |
| 185 fColorMode = mode; |
| 186 return enableGPU(fGPUEnabled); |
| 187 } |
| 188 |
160 bool Request::enableGPU(bool enable) { | 189 bool Request::enableGPU(bool enable) { |
161 if (enable) { | 190 if (enable) { |
162 SkSurface* surface = this->createGPUSurface(); | 191 SkSurface* surface = this->createGPUSurface(); |
163 if (surface) { | 192 if (surface) { |
164 fSurface.reset(surface); | 193 fSurface.reset(surface); |
165 fGPUEnabled = true; | 194 fGPUEnabled = true; |
166 | 195 |
167 // When we switch to GPU, there seems to be some mystery draws in th
e canvas. So we | 196 // When we switch to GPU, there seems to be some mystery draws in th
e canvas. So we |
168 // draw once to flush the pipe | 197 // draw once to flush the pipe |
169 // TODO understand what is actually happening here | 198 // TODO understand what is actually happening here |
170 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp()); | 199 if (fDebugCanvas) { |
171 this->getCanvas()->flush(); | 200 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp()); |
| 201 this->getCanvas()->flush(); |
| 202 } |
172 | 203 |
173 return true; | 204 return true; |
174 } | 205 } |
175 return false; | 206 return false; |
176 } | 207 } |
177 fSurface.reset(this->createCPUSurface()); | 208 fSurface.reset(this->createCPUSurface()); |
178 fGPUEnabled = false; | 209 fGPUEnabled = false; |
179 return true; | 210 return true; |
180 } | 211 } |
181 | 212 |
(...skipping 17 matching lines...) Expand all Loading... |
199 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp()); | 230 fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp()); |
200 this->getCanvas()->flush(); | 231 this->getCanvas()->flush(); |
201 return true; | 232 return true; |
202 } | 233 } |
203 | 234 |
204 SkData* Request::getJsonOps(int n) { | 235 SkData* Request::getJsonOps(int n) { |
205 SkCanvas* canvas = this->getCanvas(); | 236 SkCanvas* canvas = this->getCanvas(); |
206 Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas); | 237 Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas); |
207 root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu"); | 238 root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu"); |
208 root["drawGpuBatchBounds"] = Json::Value(fDebugCanvas->getDrawGpuBatchBounds
()); | 239 root["drawGpuBatchBounds"] = Json::Value(fDebugCanvas->getDrawGpuBatchBounds
()); |
| 240 root["colorMode"] = Json::Value(fColorMode); |
209 SkDynamicMemoryWStream stream; | 241 SkDynamicMemoryWStream stream; |
210 stream.writeText(Json::FastWriter().write(root).c_str()); | 242 stream.writeText(Json::FastWriter().write(root).c_str()); |
211 | 243 |
212 return stream.copyToData(); | 244 return stream.copyToData(); |
213 } | 245 } |
214 | 246 |
215 SkData* Request::getJsonBatchList(int n) { | 247 SkData* Request::getJsonBatchList(int n) { |
216 SkCanvas* canvas = this->getCanvas(); | 248 SkCanvas* canvas = this->getCanvas(); |
217 SkASSERT(fGPUEnabled); | 249 SkASSERT(fGPUEnabled); |
218 | 250 |
(...skipping 24 matching lines...) Expand all Loading... |
243 | 275 |
244 // We don't want the null terminator so strlen is correct | 276 // We don't want the null terminator so strlen is correct |
245 return SkData::NewWithCopy(json.c_str(), strlen(json.c_str())); | 277 return SkData::NewWithCopy(json.c_str(), strlen(json.c_str())); |
246 } | 278 } |
247 | 279 |
248 SkColor Request::getPixel(int x, int y) { | 280 SkColor Request::getPixel(int x, int y) { |
249 SkCanvas* canvas = this->getCanvas(); | 281 SkCanvas* canvas = this->getCanvas(); |
250 canvas->flush(); | 282 canvas->flush(); |
251 SkAutoTDelete<SkBitmap> bitmap(this->getBitmapFromCanvas(canvas)); | 283 SkAutoTDelete<SkBitmap> bitmap(this->getBitmapFromCanvas(canvas)); |
252 SkASSERT(bitmap); | 284 SkASSERT(bitmap); |
253 bitmap->lockPixels(); | 285 |
254 uint8_t* start = ((uint8_t*) bitmap->getPixels()) + (y * bitmap->width() + x
) * 4; | 286 // Convert to format suitable for inspection |
| 287 sk_sp<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(*bitmap); |
| 288 SkASSERT(encodedBitmap.get()); |
| 289 |
| 290 const uint8_t* start = encodedBitmap->bytes() + ((y * bitmap->width() + x) *
4); |
255 SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]); | 291 SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]); |
256 bitmap->unlockPixels(); | |
257 return result; | 292 return result; |
258 } | 293 } |
OLD | NEW |