blob: 3d9e9d37b3fbb4d344dff3224404a1ec2f7152a4 [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
10#include "png.h"
11
12const int Request::kImageWidth = 1920;
13const int Request::kImageHeight = 1080;
14
15static void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
16 SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr);
17 out->write(data, length);
18}
19
20static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 height, SkWStream& out) {
21 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
22 SkASSERT(png != nullptr);
23 png_infop info_ptr = png_create_info_struct(png);
24 SkASSERT(info_ptr != nullptr);
25 if (setjmp(png_jmpbuf(png))) {
26 SkFAIL("png encode error");
27 }
28 png_set_IHDR(png, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
29 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
30 png_set_compression_level(png, 1);
31 png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*));
32 png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 3);
33 for (png_size_t y = 0; y < height; ++y) {
34 const png_bytep src = rgba + y * width * 4;
35 rows[y] = pixels + y * width * 3;
36 // convert from RGBA to RGB
37 for (png_size_t x = 0; x < width; ++x) {
38 rows[y][x * 3] = src[x * 4];
39 rows[y][x * 3 + 1] = src[x * 4 + 1];
40 rows[y][x * 3 + 2] = src[x * 4 + 2];
41 }
42 }
43 png_set_filter(png, 0, PNG_NO_FILTERS);
44 png_set_rows(png, info_ptr, &rows[0]);
45 png_set_write_fn(png, &out, write_png_callback, NULL);
46 png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
47 png_destroy_write_struct(&png, NULL);
48 sk_free(rows);
49}
50
51SkBitmap* Request::getBitmapFromCanvas(SkCanvas* canvas) {
52 SkBitmap* bmp = new SkBitmap();
53 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kRGBA_8888_SkColorType,
54 kOpaque_SkAlphaType);
55 bmp->setInfo(info);
56 if (!canvas->readPixels(bmp, 0, 0)) {
57 fprintf(stderr, "Can't read pixels\n");
58 return nullptr;
59 }
60 return bmp;
61}
62
63SkData* Request::writeCanvasToPng(SkCanvas* canvas) {
64 // capture pixels
65 SkAutoTDelete<SkBitmap> bmp(getBitmapFromCanvas(canvas));
66 SkASSERT(bmp);
67
68 // write to png
69 SkDynamicMemoryWStream buffer;
70 write_png((const png_bytep) bmp->getPixels(), bmp->width(), bmp->height(), buffer);
71 return buffer.copyToData();
72}
73
74SkCanvas* Request::getCanvas() {
75 GrContextFactory* factory = fContextFactory;
76 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContextType,
77 GrContextFactory::kNone_GLContextOptions).fGLContext;
78 gl->makeCurrent();
79 SkASSERT(fDebugCanvas);
80 SkCanvas* target = fSurface->getCanvas();
81 return target;
82}
83
84void Request::drawToCanvas(int n) {
85 SkCanvas* target = this->getCanvas();
86 fDebugCanvas->drawTo(target, n);
87}
88
89SkData* Request::drawToPng(int n) {
90 this->drawToCanvas(n);
91 return writeCanvasToPng(this->getCanvas());
92}
93
94SkSurface* Request::createCPUSurface() {
95 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColorType,
96 kPremul_SkAlphaType);
97 return SkSurface::NewRaster(info);
98}
99
100SkSurface* Request::createGPUSurface() {
101 GrContext* context = fContextFactory->get(GrContextFactory::kNative_GLContextType,
102 GrContextFactory::kNone_GLContextOptions);
103 int maxRTSize = context->caps()->maxRenderTargetSize();
104 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize),
105 SkTMin(kImageHeight, maxRTSize),
106 kN32_SkColorType, kPremul_SkAlphaType);
107 uint32_t flags = 0;
108 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
109 SkSurface* surface = SkSurface::NewRenderTarget(context, SkBudgeted::kNo, info, 0,
110 &props);
111 return surface;
112}
113
joshualitt1e5884b2016-02-26 08:22:49 -0800114SkData* Request::getJsonOps(int n) {
115 SkCanvas* canvas = this->getCanvas();
116 Json::Value root = fDebugCanvas->toJSON(fUrlDataManager, n, canvas);
117 root["mode"] = Json::Value(fGPUEnabled ? "gpu" : "cpu");
118 SkDynamicMemoryWStream stream;
119 stream.writeText(Json::FastWriter().write(root).c_str());
120
121 return stream.copyToData();
122}
123
124SkData* Request::getJsonBatchList(int n) {
125 SkCanvas* canvas = this->getCanvas();
126 SkASSERT(fGPUEnabled);
127
128 // TODO if this is inefficient we could add a method to GrAuditTrail which takes
129 // a Json::Value and is only compiled in this file
130 Json::Value parsedFromString;
131#if SK_SUPPORT_GPU
132 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
133 SkASSERT(rt);
134 GrContext* ctx = rt->getContext();
135 SkASSERT(ctx);
136 GrAuditTrail* at = ctx->getAuditTrail();
137 GrAuditTrail::AutoManageBatchList enable(at);
138
139 fDebugCanvas->drawTo(canvas, n);
140
141 Json::Reader reader;
142 SkDEBUGCODE(bool parsingSuccessful = )reader.parse(at->toJson(true).c_str(),
143 parsedFromString);
144 SkASSERT(parsingSuccessful);
145#endif
146
147 SkDynamicMemoryWStream stream;
148 stream.writeText(Json::FastWriter().write(parsedFromString).c_str());
149
150 return stream.copyToData();
151}