Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: tools/skiaserve/skiaserve.cpp

Issue 1640333002: Wire up JsonCanvas in skiaserve (Closed) Base URL: https://skia.googlesource.com/skia.git@skiaserve-6-cleanup
Patch Set: add redirect Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gyp/skiaserve.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "GrCaps.h" 8 #include "GrCaps.h"
9 #include "GrContextFactory.h" 9 #include "GrContextFactory.h"
10 #include "SkCanvas.h" 10 #include "SkCanvas.h"
11 #include "SkCommandLineFlags.h" 11 #include "SkCommandLineFlags.h"
12 #include "SkJSONCanvas.h"
12 #include "SkPicture.h" 13 #include "SkPicture.h"
13 #include "SkStream.h" 14 #include "SkStream.h"
14 #include "SkSurface.h" 15 #include "SkSurface.h"
15 16
16 #include <sys/socket.h> 17 #include <sys/socket.h>
17 #include <microhttpd.h> 18 #include <microhttpd.h>
18 19
19 // To get image decoders linked in we have to do the below magic 20 // To get image decoders linked in we have to do the below magic
20 #include "SkForceLinking.h" 21 #include "SkForceLinking.h"
21 #include "SkImageDecoder.h" 22 #include "SkImageDecoder.h"
22 __SK_FORCE_IMAGE_DECODER_LINKING; 23 __SK_FORCE_IMAGE_DECODER_LINKING;
23 24
24 // TODO make this configurable 25 // TODO make this configurable
25 #define PORT 8888 26 #define PORT 8888
26 27
27 DEFINE_string(dir, "skps", "Directory to read skp."); 28 DEFINE_string(dir, "skps", "Directory to read skp.");
28 DEFINE_string(name, "desk_carsvg", "skp to load."); 29 DEFINE_string(name, "desk_carsvg", "skp to load.");
29 DEFINE_bool(useTemplate, true, "whether or not to use the skdebugger template st ring."); 30 DEFINE_bool(useTemplate, true, "whether or not to use the skdebugger template st ring.");
30 31
31 // TODO probably want to make this configurable 32 // TODO probably want to make this configurable
32 static const int kImageWidth = 1920; 33 static const int kImageWidth = 1920;
33 static const int kImageHeight = 1080; 34 static const int kImageHeight = 1080;
34 35
36 // TODO move to template file
37 SkString generateTemplate(SkString source) {
38 SkString debuggerTemplate;
39 debuggerTemplate.appendf(
40 "<!DOCTYPE html>\n"
41 "<html>\n"
42 "<head>\n"
43 " <title>SkDebugger</title>\n"
44 " <meta charset=\"utf-8\" />\n"
45 " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\ n"
46 " <meta name=\"viewport\" content=\"width=device-width, initial-scale =1.0\">\n"
47 " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset= \"utf-8\"></script>\n"
48 " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n"
49 "</head>\n"
50 "<body class=\"fullbleed layout vertical\">\n"
51 " <debugger-app-sk>This is the app."
52 " </debugger-app-sk>\n"
53 "</body>\n"
54 "</html>", source.c_str(), source.c_str());
55 return debuggerTemplate;
56
57 }
58
59 struct UploadContext {
60 SkDynamicMemoryWStream fStream;
61 MHD_PostProcessor* fPostProcessor;
62 MHD_Connection* connection;
63 };
64
65 struct Request {
66 Request() : fUploadContext(nullptr) {}
67 UploadContext* fUploadContext;
68 SkAutoTUnref<SkData> fPNG;
69 SkAutoTUnref<SkPicture> fPicture;
70 };
71
35 // TODO factor this out into functions, also handle CPU path 72 // TODO factor this out into functions, also handle CPU path
36 SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) { 73 bool setupAndDrawToCanvas(Request* request, SkString* error) {
37 GrContextOptions grContextOpts; 74 GrContextOptions grContextOpts;
38 SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts)) ; 75 SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts)) ;
39 76
40 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, 77 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType,
41 GrContextFactory::kNone_GLContextOptions); 78 GrContextFactory::kNone_GLContextOptions);
42 int maxRTSize = context->caps()->maxRenderTargetSize(); 79 int maxRTSize = context->caps()->maxRenderTargetSize();
43 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), 80 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize),
44 SkTMin(kImageHeight, maxRTSize), 81 SkTMin(kImageHeight, maxRTSize),
45 kN32_SkColorType, kPremul_SkAlphaType); 82 kN32_SkColorType, kPremul_SkAlphaType);
46 uint32_t flags = 0; 83 uint32_t flags = 0;
47 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); 84 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
48 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, 85 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context,
49 SkSurface::kNo_Bu dgeted, info, 86 SkSurface::kNo_Bu dgeted, info,
50 0, &props)); 87 0, &props));
51 SkASSERT(surface.get()); 88 SkASSERT(surface.get());
52 89
53 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex tType, 90 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex tType,
54 GrContextFactory::kNone_GLContextO ptions).fGLContext; 91 GrContextFactory::kNone_GLContextO ptions).fGLContext;
55 gl->makeCurrent(); 92 gl->makeCurrent();
56 93
57 // draw 94 // draw
58 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream)); 95 request->fPicture.reset(
59 if (pic.get() == nullptr) { 96 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachAsStr eam()));
97 if (!request->fPicture.get()) {
60 error->appendf("Could not create picture from stream.\n"); 98 error->appendf("Could not create picture from stream.\n");
61 return nullptr; 99 return false;
62 } 100 }
63 101
64 SkCanvas* canvas = surface->getCanvas(); 102 SkCanvas* canvas = surface->getCanvas();
65 canvas->drawPicture(pic); 103 canvas->drawPicture(request->fPicture);
66 104
67 // capture pixels 105 // capture pixels
68 SkBitmap bmp; 106 SkBitmap bmp;
69 bmp.setInfo(canvas->imageInfo()); 107 bmp.setInfo(canvas->imageInfo());
70 if (!canvas->readPixels(&bmp, 0, 0)) { 108 if (!canvas->readPixels(&bmp, 0, 0)) {
71 error->appendf("Can't read canvas pixels.\n"); 109 error->appendf("Can't read canvas pixels.\n");
72 return nullptr; 110 return false;
73 } 111 }
74 112
75 // write to png 113 // write to png
76 SkData* data = SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 10 0); 114 request->fPNG.reset(SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Typ e, 100));
77 if (!data) { 115 if (!request->fPNG) {
78 error->appendf("Can't encode a PNG.\n"); 116 error->appendf("Can't encode a PNG.\n");
79 return nullptr; 117 return false;
80 } 118 }
81 return data; 119 return true;
82 } 120 }
83 // TODO move to template file
84 SkString generateTemplate(SkString source) {
85 SkString debuggerTemplate;
86 debuggerTemplate.appendf(
87 "<!DOCTYPE html>\n"
88 "<html>\n"
89 "<head>\n"
90 " <title>SkDebugger</title>\n"
91 " <meta charset=\"utf-8\" />\n"
92 " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\ n"
93 " <meta name=\"viewport\" content=\"width=device-width, initial-scale =1.0\">\n"
94 " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset= \"utf-8\"></script>\n"
95 " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n"
96 "</head>\n"
97 "<body class=\"fullbleed layout vertical\">\n"
98 " <debugger-app-sk>This is the app."
99 " </debugger-app-sk>\n"
100 "</body>\n"
101 "</html>", source.c_str(), source.c_str());
102 return debuggerTemplate;
103
104 }
105
106 struct UploadContext {
107 SkDynamicMemoryWStream stream;
108 MHD_PostProcessor* pp;
109 MHD_Connection* connection;
110 };
111
112 struct Request {
113 Request() : fUploadContext(nullptr) {}
114 UploadContext* fUploadContext;
115 SkAutoTUnref<SkData> fPNG;
116 };
117 121
118 static const size_t kBufferSize = 1024; 122 static const size_t kBufferSize = 1024;
119 123
120 static int process_upload_data(void* cls, enum MHD_ValueKind kind, 124 static int process_upload_data(void* cls, enum MHD_ValueKind kind,
121 const char* key, const char* filename, 125 const char* key, const char* filename,
122 const char* content_type, const char* transfer_en coding, 126 const char* content_type, const char* transfer_en coding,
123 const char* data, uint64_t off, size_t size) { 127 const char* data, uint64_t off, size_t size) {
124 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); 128 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls);
125 129
126 if (0 != size) { 130 if (0 != size) {
127 uc->stream.write(data, size); 131 uc->fStream.write(data, size);
128 } 132 }
129 return MHD_YES; 133 return MHD_YES;
130 } 134 }
131 135
132 static int SendImage(MHD_Connection* connection, const SkData* data) { 136 static int SendData(MHD_Connection* connection, const SkData* data, const char* type) {
133 MHD_Response* response = MHD_create_response_from_buffer(data->size(), 137 MHD_Response* response = MHD_create_response_from_buffer(data->size(),
134 const_cast<void*>(d ata->data()), 138 const_cast<void*>(d ata->data()),
135 MHD_RESPMEM_MUST_CO PY); 139 MHD_RESPMEM_MUST_CO PY);
136 MHD_add_response_header(response, "Content-Type", "image/png"); 140 MHD_add_response_header(response, "Content-Type", type);
137 141
138 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); 142 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
139 MHD_destroy_response(response); 143 MHD_destroy_response(response);
140 return ret; 144 return ret;
141 } 145 }
142 146
143 static int SendTemplate(MHD_Connection* connection) { 147 static int SendJSON(MHD_Connection* connection, SkPicture* picture) {
148 SkDynamicMemoryWStream stream;
149 SkAutoTUnref<SkJSONCanvas> jsonCanvas(new SkJSONCanvas(kImageWidth, kImageHe ight, stream));
150 jsonCanvas->drawPicture(picture);
151 jsonCanvas->finish();
152
153 SkAutoTUnref<SkData> data(stream.copyToData());
154 return SendData(connection, data, "application/json");
155 }
156
157 static int SendTemplate(MHD_Connection* connection, bool redirect = false,
158 const char* redirectUrl = nullptr) {
144 SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia. org")); 159 SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia. org"));
145 160
146 MHD_Response* response = MHD_create_response_from_buffer( 161 MHD_Response* response = MHD_create_response_from_buffer(
147 debuggerTemplate.size(), 162 debuggerTemplate.size(),
148 (void*) const_cast<char*>(debuggerTemplate.c_str()), 163 (void*) const_cast<char*>(debuggerTemplate.c_str()),
149 MHD_RESPMEM_MUST_COPY); 164 MHD_RESPMEM_MUST_COPY);
150 165
166 if (redirect) {
167 MHD_add_response_header (response, "Location", redirectUrl);
168 }
169
170
151 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); 171 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
jcgregorio 2016/01/27 19:21:19 If it's a redirect the status code needs to be cha
152 MHD_destroy_response(response); 172 MHD_destroy_response(response);
153 return ret; 173 return ret;
154 } 174 }
155 175
156 typedef int (*UrlHandler)(Request* request, MHD_Connection* connection, 176 typedef int (*UrlHandler)(Request* request, MHD_Connection* connection,
157 const char* upload_data, size_t* upload_data_size); 177 const char* upload_data, size_t* upload_data_size);
158 178
159 int rootHandler(Request* request, MHD_Connection* connection, 179 int rootHandler(Request* request, MHD_Connection* connection,
160 const char* upload_data, size_t* upload_data_size) { 180 const char* upload_data, size_t* upload_data_size) {
161 return SendTemplate(connection); 181 return SendTemplate(connection);
162 } 182 }
163 183
164 int postHandler(Request* request, MHD_Connection* connection, 184 int postHandler(Request* request, MHD_Connection* connection,
165 const char* upload_data, size_t* upload_data_size) { 185 const char* upload_data, size_t* upload_data_size) {
166 UploadContext* uc = request->fUploadContext; 186 UploadContext* uc = request->fUploadContext;
167 187
168 // New connection 188 // New connection
169 if (!uc) { 189 if (!uc) {
170 // TODO make this a method on request 190 // TODO make this a method on request
171 uc = new UploadContext; 191 uc = new UploadContext;
172 uc->connection = connection; 192 uc->connection = connection;
173 uc->pp = MHD_create_post_processor(connection, kBufferSize, &process_upl oad_data, uc); 193 uc->fPostProcessor = MHD_create_post_processor(connection, kBufferSize,
174 SkASSERT(uc->pp); 194 &process_upload_data, uc) ;
195 SkASSERT(uc->fPostProcessor);
175 196
176 request->fUploadContext = uc; 197 request->fUploadContext = uc;
177 return MHD_YES; 198 return MHD_YES;
178 } 199 }
179 200
180 // in process upload 201 // in process upload
181 if (0 != *upload_data_size) { 202 if (0 != *upload_data_size) {
182 SkASSERT(uc->pp); 203 SkASSERT(uc->fPostProcessor);
183 MHD_post_process(uc->pp, upload_data, *upload_data_size); 204 MHD_post_process(uc->fPostProcessor, upload_data, *upload_data_size);
184 *upload_data_size = 0; 205 *upload_data_size = 0;
185 return MHD_YES; 206 return MHD_YES;
186 } 207 }
187 208
188 // end of upload 209 // end of upload
189 MHD_destroy_post_processor(uc->pp); 210 MHD_destroy_post_processor(uc->fPostProcessor);
190 uc->pp = nullptr; 211 uc->fPostProcessor = nullptr;
191 212
192 // TODO response 213 // TODO response
193 SkString error; 214 SkString error;
194 SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error); 215 if (!setupAndDrawToCanvas(request, &error)) {
195 if (!data) {
196 // TODO send error 216 // TODO send error
197 return MHD_YES; 217 return MHD_YES;
198 } 218 }
199 219
200 request->fPNG.reset(data); 220 return SendTemplate(connection, true, "/");
201 return SendTemplate(connection);
202 } 221 }
203 222
204 int imgHandler(Request* request, MHD_Connection* connection, 223 int imgHandler(Request* request, MHD_Connection* connection,
205 const char* upload_data, size_t* upload_data_size) { 224 const char* upload_data, size_t* upload_data_size) {
206 if (request->fPNG.get()) { 225 if (request->fPNG.get()) {
207 SkData* data = request->fPNG.get(); 226 SkData* data = request->fPNG.get();
208 return SendImage(connection, data); 227 return SendData(connection, data, "image/png");
209 } 228 }
210 return MHD_NO; 229 return MHD_NO;
211 } 230 }
231
232 int infoHandler(Request* request, MHD_Connection* connection,
233 const char* upload_data, size_t* upload_data_size) {
234 if (request->fPicture.get()) {
235 return SendJSON(connection, request->fPicture);
236 }
237 return MHD_NO;
238 }
212 239
213 class UrlManager { 240 class UrlManager {
214 public: 241 public:
215 UrlManager() { 242 UrlManager() {
216 // Register handlers 243 // Register handlers
217 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/", rootHandler}); 244 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/", rootHandler});
218 fHandlers.push_back({MHD_HTTP_METHOD_POST, "/new", postHandler}); 245 fHandlers.push_back({MHD_HTTP_METHOD_POST, "/new", postHandler});
219 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/img", imgHandler}); 246 fHandlers.push_back({MHD_HTTP_METHOD_GET, "/img", imgHandler});
247 //fHandlers.push_back({MHD_HTTP_METHOD_GET, "/cmd", infoHandler});
220 } 248 }
221 249
222 // This is clearly not efficient for a large number of urls and handlers 250 // This is clearly not efficient for a large number of urls and handlers
223 int invoke(Request* request, MHD_Connection* connection, const char* url, co nst char* method, 251 int invoke(Request* request, MHD_Connection* connection, const char* url, co nst char* method,
224 const char* upload_data, size_t* upload_data_size) const { 252 const char* upload_data, size_t* upload_data_size) const {
225 for (int i = 0; i < fHandlers.count(); i++) { 253 for (int i = 0; i < fHandlers.count(); i++) {
226 const Url& urlHandler = fHandlers[i]; 254 const Url& urlHandler = fHandlers[i];
227 if (0 == strcmp(method, urlHandler.fMethod) && 255 if (0 == strcmp(method, urlHandler.fMethod) &&
228 0 == strcmp(url, urlHandler.fPath)) { 256 0 == strcmp(url, urlHandler.fPath)) {
229 return (*urlHandler.fHandler)(request, connection, upload_da ta, 257 return (*urlHandler.fHandler)(request, connection, upload_da ta,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 MHD_stop_daemon(daemon); 296 MHD_stop_daemon(daemon);
269 return 0; 297 return 0;
270 } 298 }
271 299
272 #if !defined SK_BUILD_FOR_IOS 300 #if !defined SK_BUILD_FOR_IOS
273 int main(int argc, char** argv) { 301 int main(int argc, char** argv) {
274 SkCommandLineFlags::Parse(argc, argv); 302 SkCommandLineFlags::Parse(argc, argv);
275 return skiaserve_main(); 303 return skiaserve_main();
276 } 304 }
277 #endif 305 #endif
OLDNEW
« no previous file with comments | « gyp/skiaserve.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698