| 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 "GrCaps.h" | 8 #include "GrCaps.h" |
| 9 #include "GrContextFactory.h" | 9 #include "GrContextFactory.h" |
| 10 | 10 |
| 11 #include "Request.h" | 11 #include "Request.h" |
| 12 | 12 |
| 13 #include "SkCanvas.h" | 13 #include "SkCanvas.h" |
| 14 #include "SkCommandLineFlags.h" | 14 #include "SkCommandLineFlags.h" |
| 15 #include "SkJSONCanvas.h" | 15 #include "SkJSONCanvas.h" |
| 16 #include "SkPictureRecorder.h" | 16 #include "SkPictureRecorder.h" |
| 17 #include "SkPixelSerializer.h" | 17 #include "SkPixelSerializer.h" |
| 18 | 18 |
| 19 #include <sys/socket.h> | 19 #include <sys/socket.h> |
| 20 #include <microhttpd.h> | 20 #include <microhttpd.h> |
| 21 #include "png.h" | |
| 22 | 21 |
| 23 // To get image decoders linked in we have to do the below magic | 22 // To get image decoders linked in we have to do the below magic |
| 24 #include "SkForceLinking.h" | 23 #include "SkForceLinking.h" |
| 25 #include "SkImageDecoder.h" | 24 #include "SkImageDecoder.h" |
| 26 __SK_FORCE_IMAGE_DECODER_LINKING; | 25 __SK_FORCE_IMAGE_DECODER_LINKING; |
| 27 | 26 |
| 28 DEFINE_string(source, "https://debugger.skia.org", "Where to load the web UI fro
m."); | 27 DEFINE_string(source, "https://debugger.skia.org", "Where to load the web UI fro
m."); |
| 29 DEFINE_int32(port, 8888, "The port to listen on."); | 28 DEFINE_int32(port, 8888, "The port to listen on."); |
| 30 | 29 |
| 31 // TODO probably want to make this configurable | |
| 32 static const int kImageWidth = 1920; | |
| 33 static const int kImageHeight = 1080; | |
| 34 | |
| 35 SkString generateTemplate(SkString source) { | 30 SkString generateTemplate(SkString source) { |
| 36 SkString debuggerTemplate; | 31 SkString debuggerTemplate; |
| 37 debuggerTemplate.appendf( | 32 debuggerTemplate.appendf( |
| 38 "<!DOCTYPE html>\n" | 33 "<!DOCTYPE html>\n" |
| 39 "<html>\n" | 34 "<html>\n" |
| 40 "<head>\n" | 35 "<head>\n" |
| 41 " <title>SkDebugger</title>\n" | 36 " <title>SkDebugger</title>\n" |
| 42 " <meta charset=\"utf-8\" />\n" | 37 " <meta charset=\"utf-8\" />\n" |
| 43 " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\
n" | 38 " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\
n" |
| 44 " <meta name=\"viewport\" content=\"width=device-width, initial-scale
=1.0\">\n" | 39 " <meta name=\"viewport\" content=\"width=device-width, initial-scale
=1.0\">\n" |
| 45 " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=
\"utf-8\"></script>\n" | 40 " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=
\"utf-8\"></script>\n" |
| 46 " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" | 41 " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" |
| 47 " <link rel='shortcut icon' href='https://debugger.skia.org/res/img/f
avicon.ico' type='image/x-icon'/ >" | 42 " <link rel='shortcut icon' href='https://debugger.skia.org/res/img/f
avicon.ico' type='image/x-icon'/ >" |
| 48 "</head>\n" | 43 "</head>\n" |
| 49 "<body class=\"fullbleed layout vertical\">\n" | 44 "<body class=\"fullbleed layout vertical\">\n" |
| 50 " <debugger-app-sk>This is the app." | 45 " <debugger-app-sk>This is the app." |
| 51 " </debugger-app-sk>\n" | 46 " </debugger-app-sk>\n" |
| 52 "</body>\n" | 47 "</body>\n" |
| 53 "</html>", source.c_str(), source.c_str()); | 48 "</html>", source.c_str(), source.c_str()); |
| 54 return debuggerTemplate; | 49 return debuggerTemplate; |
| 55 | 50 |
| 56 } | 51 } |
| 57 | 52 |
| 58 static void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t l
ength) { | |
| 59 SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr); | |
| 60 out->write(data, length); | |
| 61 } | |
| 62 | |
| 63 static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 heigh
t, SkWStream& out) { | |
| 64 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL); | |
| 65 SkASSERT(png != nullptr); | |
| 66 png_infop info_ptr = png_create_info_struct(png); | |
| 67 SkASSERT(info_ptr != nullptr); | |
| 68 if (setjmp(png_jmpbuf(png))) { | |
| 69 SkFAIL("png encode error"); | |
| 70 } | |
| 71 png_set_IHDR(png, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERL
ACE_NONE, | |
| 72 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); | |
| 73 png_set_compression_level(png, 1); | |
| 74 png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*)); | |
| 75 png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 3); | |
| 76 for (png_size_t y = 0; y < height; ++y) { | |
| 77 const png_bytep src = rgba + y * width * 4; | |
| 78 rows[y] = pixels + y * width * 3; | |
| 79 // convert from RGBA to RGB | |
| 80 for (png_size_t x = 0; x < width; ++x) { | |
| 81 rows[y][x * 3] = src[x * 4]; | |
| 82 rows[y][x * 3 + 1] = src[x * 4 + 1]; | |
| 83 rows[y][x * 3 + 2] = src[x * 4 + 2]; | |
| 84 } | |
| 85 } | |
| 86 png_set_filter(png, 0, PNG_NO_FILTERS); | |
| 87 png_set_rows(png, info_ptr, &rows[0]); | |
| 88 png_set_write_fn(png, &out, write_png_callback, NULL); | |
| 89 png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); | |
| 90 png_destroy_write_struct(&png, NULL); | |
| 91 sk_free(rows); | |
| 92 } | |
| 93 | |
| 94 SkBitmap* getBitmapFromCanvas(SkCanvas* canvas) { | |
| 95 SkBitmap* bmp = new SkBitmap(); | |
| 96 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kRGBA_8888_S
kColorType, | |
| 97 kOpaque_SkAlphaType); | |
| 98 bmp->setInfo(info); | |
| 99 if (!canvas->readPixels(bmp, 0, 0)) { | |
| 100 fprintf(stderr, "Can't read pixels\n"); | |
| 101 return nullptr; | |
| 102 } | |
| 103 return bmp; | |
| 104 } | |
| 105 | |
| 106 SkData* writeCanvasToPng(SkCanvas* canvas) { | |
| 107 // capture pixels | |
| 108 SkAutoTDelete<SkBitmap> bmp(getBitmapFromCanvas(canvas)); | |
| 109 SkASSERT(bmp); | |
| 110 | |
| 111 // write to png | |
| 112 SkDynamicMemoryWStream buffer; | |
| 113 write_png((const png_bytep) bmp->getPixels(), bmp->width(), bmp->height(), b
uffer); | |
| 114 return buffer.copyToData(); | |
| 115 } | |
| 116 | |
| 117 SkCanvas* getCanvasFromRequest(Request* request) { | |
| 118 GrContextFactory* factory = request->fContextFactory; | |
| 119 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex
tType, | |
| 120 GrContextFactory::kNone_GLContextO
ptions).fGLContext; | |
| 121 gl->makeCurrent(); | |
| 122 SkASSERT(request->fDebugCanvas); | |
| 123 SkCanvas* target = request->fSurface->getCanvas(); | |
| 124 return target; | |
| 125 } | |
| 126 | |
| 127 void drawToCanvas(Request* request, int n) { | |
| 128 SkCanvas* target = getCanvasFromRequest(request); | |
| 129 request->fDebugCanvas->drawTo(target, n); | |
| 130 } | |
| 131 | |
| 132 SkData* drawToPng(Request* request, int n) { | |
| 133 drawToCanvas(request, n); | |
| 134 return writeCanvasToPng(getCanvasFromRequest(request)); | |
| 135 } | |
| 136 | |
| 137 SkSurface* createCPUSurface() { | |
| 138 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColor
Type, | |
| 139 kPremul_SkAlphaType); | |
| 140 return SkSurface::NewRaster(info); | |
| 141 } | |
| 142 | |
| 143 SkSurface* createGPUSurface(Request* request) { | |
| 144 GrContext* context = request->fContextFactory->get(GrContextFactory::kNative
_GLContextType, | |
| 145 GrContextFactory::kNone_G
LContextOptions); | |
| 146 int maxRTSize = context->caps()->maxRenderTargetSize(); | |
| 147 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), | |
| 148 SkTMin(kImageHeight, maxRTSize), | |
| 149 kN32_SkColorType, kPremul_SkAlphaType); | |
| 150 uint32_t flags = 0; | |
| 151 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | |
| 152 SkSurface* surface = SkSurface::NewRenderTarget(context, SkBudgeted::kNo, in
fo, 0, | |
| 153 &props); | |
| 154 return surface; | |
| 155 } | |
| 156 | |
| 157 static const size_t kBufferSize = 1024; | 53 static const size_t kBufferSize = 1024; |
| 158 | 54 |
| 159 static int process_upload_data(void* cls, enum MHD_ValueKind kind, | 55 static int process_upload_data(void* cls, enum MHD_ValueKind kind, |
| 160 const char* key, const char* filename, | 56 const char* key, const char* filename, |
| 161 const char* content_type, const char* transfer_en
coding, | 57 const char* content_type, const char* transfer_en
coding, |
| 162 const char* data, uint64_t off, size_t size) { | 58 const char* data, uint64_t off, size_t size) { |
| 163 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); | 59 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); |
| 164 | 60 |
| 165 if (0 != size) { | 61 if (0 != size) { |
| 166 uc->fStream.write(data, size); | 62 uc->fStream.write(data, size); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 if (setContentDisposition) { | 95 if (setContentDisposition) { |
| 200 MHD_add_response_header(response, "Content-Disposition", dispositionStri
ng); | 96 MHD_add_response_header(response, "Content-Disposition", dispositionStri
ng); |
| 201 } | 97 } |
| 202 | 98 |
| 203 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); | 99 int ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
| 204 MHD_destroy_response(response); | 100 MHD_destroy_response(response); |
| 205 return ret; | 101 return ret; |
| 206 } | 102 } |
| 207 | 103 |
| 208 static int SendJSON(MHD_Connection* connection, Request* request, int n) { | 104 static int SendJSON(MHD_Connection* connection, Request* request, int n) { |
| 209 SkCanvas* canvas = getCanvasFromRequest(request); | 105 SkCanvas* canvas = request->getCanvas(); |
| 210 SkDebugCanvas* debugCanvas = request->fDebugCanvas; | 106 SkDebugCanvas* debugCanvas = request->fDebugCanvas; |
| 211 UrlDataManager* urlDataManager = &request->fUrlDataManager; | 107 UrlDataManager* urlDataManager = &request->fUrlDataManager; |
| 212 Json::Value root = debugCanvas->toJSON(*urlDataManager, n, canvas); | 108 Json::Value root = debugCanvas->toJSON(*urlDataManager, n, canvas); |
| 213 root["mode"] = Json::Value(request->fGPUEnabled ? "gpu" : "cpu"); | 109 root["mode"] = Json::Value(request->fGPUEnabled ? "gpu" : "cpu"); |
| 214 SkDynamicMemoryWStream stream; | 110 SkDynamicMemoryWStream stream; |
| 215 stream.writeText(Json::FastWriter().write(root).c_str()); | 111 stream.writeText(Json::FastWriter().write(root).c_str()); |
| 216 | 112 |
| 217 SkAutoTUnref<SkData> data(stream.copyToData()); | 113 SkAutoTUnref<SkData> data(stream.copyToData()); |
| 218 return SendData(connection, data, "application/json"); | 114 return SendData(connection, data, "application/json"); |
| 219 } | 115 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 } | 213 } |
| 318 | 214 |
| 319 int n; | 215 int n; |
| 320 // /img or /img/N | 216 // /img or /img/N |
| 321 if (commands.count() == 1) { | 217 if (commands.count() == 1) { |
| 322 n = request->fDebugCanvas->getSize() - 1; | 218 n = request->fDebugCanvas->getSize() - 1; |
| 323 } else { | 219 } else { |
| 324 sscanf(commands[1].c_str(), "%d", &n); | 220 sscanf(commands[1].c_str(), "%d", &n); |
| 325 } | 221 } |
| 326 | 222 |
| 327 SkAutoTUnref<SkData> data(drawToPng(request, n)); | 223 SkAutoTUnref<SkData> data(request->drawToPng(n)); |
| 328 return SendData(connection, data, "image/png"); | 224 return SendData(connection, data, "image/png"); |
| 329 } | 225 } |
| 330 }; | 226 }; |
| 331 | 227 |
| 332 class BreakHandler : public UrlHandler { | 228 class BreakHandler : public UrlHandler { |
| 333 public: | 229 public: |
| 334 bool canHandle(const char* method, const char* url) override { | 230 bool canHandle(const char* method, const char* url) override { |
| 335 static const char* kBasePath = "/break"; | 231 static const char* kBasePath = "/break"; |
| 336 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && | 232 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 337 0 == strncmp(url, kBasePath, strlen(kBasePath)); | 233 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
| 338 } | 234 } |
| 339 | 235 |
| 340 static SkColor GetPixel(Request* request, int x, int y) { | 236 static SkColor GetPixel(Request* request, int x, int y) { |
| 341 SkCanvas* canvas = getCanvasFromRequest(request); | 237 SkCanvas* canvas = request->getCanvas(); |
| 342 canvas->flush(); | 238 canvas->flush(); |
| 343 SkAutoTDelete<SkBitmap> bitmap(getBitmapFromCanvas(canvas)); | 239 SkAutoTDelete<SkBitmap> bitmap(request->getBitmapFromCanvas(canvas)); |
| 344 SkASSERT(bitmap); | 240 SkASSERT(bitmap); |
| 345 bitmap->lockPixels(); | 241 bitmap->lockPixels(); |
| 346 uint8_t* start = ((uint8_t*) bitmap->getPixels()) + (y * kImageWidth + x
) * 4; | 242 uint8_t* start = ((uint8_t*) bitmap->getPixels()) + (y * Request::kImage
Width + x) * 4; |
| 347 SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]); | 243 SkColor result = SkColorSetARGB(start[3], start[0], start[1], start[2]); |
| 348 bitmap->unlockPixels(); | 244 bitmap->unlockPixels(); |
| 349 return result; | 245 return result; |
| 350 } | 246 } |
| 351 | 247 |
| 352 int handle(Request* request, MHD_Connection* connection, | 248 int handle(Request* request, MHD_Connection* connection, |
| 353 const char* url, const char* method, | 249 const char* url, const char* method, |
| 354 const char* upload_data, size_t* upload_data_size) override { | 250 const char* upload_data, size_t* upload_data_size) override { |
| 355 SkTArray<SkString> commands; | 251 SkTArray<SkString> commands; |
| 356 SkStrSplit(url, "/", &commands); | 252 SkStrSplit(url, "/", &commands); |
| 357 | 253 |
| 358 if (!request->fPicture.get() || commands.count() != 4) { | 254 if (!request->fPicture.get() || commands.count() != 4) { |
| 359 return MHD_NO; | 255 return MHD_NO; |
| 360 } | 256 } |
| 361 | 257 |
| 362 // /break/<n>/<x>/<y> | 258 // /break/<n>/<x>/<y> |
| 363 int n; | 259 int n; |
| 364 sscanf(commands[1].c_str(), "%d", &n); | 260 sscanf(commands[1].c_str(), "%d", &n); |
| 365 int x; | 261 int x; |
| 366 sscanf(commands[2].c_str(), "%d", &x); | 262 sscanf(commands[2].c_str(), "%d", &x); |
| 367 int y; | 263 int y; |
| 368 sscanf(commands[3].c_str(), "%d", &y); | 264 sscanf(commands[3].c_str(), "%d", &y); |
| 369 | 265 |
| 370 int count = request->fDebugCanvas->getSize(); | 266 int count = request->fDebugCanvas->getSize(); |
| 371 SkASSERT(n < count); | 267 SkASSERT(n < count); |
| 372 | 268 |
| 373 SkCanvas* canvas = getCanvasFromRequest(request); | 269 SkCanvas* canvas = request->getCanvas(); |
| 374 canvas->clear(SK_ColorWHITE); | 270 canvas->clear(SK_ColorWHITE); |
| 375 int saveCount = canvas->save(); | 271 int saveCount = canvas->save(); |
| 376 for (int i = 0; i <= n; ++i) { | 272 for (int i = 0; i <= n; ++i) { |
| 377 request->fDebugCanvas->getDrawCommandAt(i)->execute(canvas); | 273 request->fDebugCanvas->getDrawCommandAt(i)->execute(canvas); |
| 378 } | 274 } |
| 379 SkColor target = GetPixel(request, x, y); | 275 SkColor target = GetPixel(request, x, y); |
| 380 Json::Value response(Json::objectValue); | 276 Json::Value response(Json::objectValue); |
| 381 Json::Value startColor(Json::arrayValue); | 277 Json::Value startColor(Json::arrayValue); |
| 382 startColor.append(Json::Value(SkColorGetR(target))); | 278 startColor.append(Json::Value(SkColorGetR(target))); |
| 383 startColor.append(Json::Value(SkColorGetG(target))); | 279 startColor.append(Json::Value(SkColorGetG(target))); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 SkStrSplit(url, "/", &commands); | 360 SkStrSplit(url, "/", &commands); |
| 465 | 361 |
| 466 if (commands.count() != 2) { | 362 if (commands.count() != 2) { |
| 467 return MHD_NO; | 363 return MHD_NO; |
| 468 } | 364 } |
| 469 | 365 |
| 470 int enable; | 366 int enable; |
| 471 sscanf(commands[1].c_str(), "%d", &enable); | 367 sscanf(commands[1].c_str(), "%d", &enable); |
| 472 | 368 |
| 473 if (enable) { | 369 if (enable) { |
| 474 SkSurface* surface = createGPUSurface(request); | 370 SkSurface* surface = request->createGPUSurface(); |
| 475 if (surface) { | 371 if (surface) { |
| 476 request->fSurface.reset(surface); | 372 request->fSurface.reset(surface); |
| 477 request->fGPUEnabled = true; | 373 request->fGPUEnabled = true; |
| 478 return SendOK(connection); | 374 return SendOK(connection); |
| 479 } | 375 } |
| 480 return SendError(connection, "Unable to create GPU surface"); | 376 return SendError(connection, "Unable to create GPU surface"); |
| 481 } | 377 } |
| 482 request->fSurface.reset(createCPUSurface()); | 378 request->fSurface.reset(request->createCPUSurface()); |
| 483 request->fGPUEnabled = false; | 379 request->fGPUEnabled = false; |
| 484 return SendOK(connection); | 380 return SendOK(connection); |
| 485 } | 381 } |
| 486 }; | 382 }; |
| 487 | 383 |
| 488 class PostHandler : public UrlHandler { | 384 class PostHandler : public UrlHandler { |
| 489 public: | 385 public: |
| 490 bool canHandle(const char* method, const char* url) override { | 386 bool canHandle(const char* method, const char* url) override { |
| 491 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && | 387 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
| 492 0 == strcmp(url, "/new"); | 388 0 == strcmp(url, "/new"); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 | 420 |
| 525 // parse picture from stream | 421 // parse picture from stream |
| 526 request->fPicture.reset( | 422 request->fPicture.reset( |
| 527 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachA
sStream())); | 423 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachA
sStream())); |
| 528 if (!request->fPicture.get()) { | 424 if (!request->fPicture.get()) { |
| 529 fprintf(stderr, "Could not create picture from stream.\n"); | 425 fprintf(stderr, "Could not create picture from stream.\n"); |
| 530 return MHD_NO; | 426 return MHD_NO; |
| 531 } | 427 } |
| 532 | 428 |
| 533 // pour picture into debug canvas | 429 // pour picture into debug canvas |
| 534 request->fDebugCanvas.reset(new SkDebugCanvas(kImageWidth, kImageHeight)
); | 430 request->fDebugCanvas.reset(new SkDebugCanvas(Request::kImageWidth, |
| 431 Request::kImageHeight)); |
| 535 request->fDebugCanvas->drawPicture(request->fPicture); | 432 request->fDebugCanvas->drawPicture(request->fPicture); |
| 536 | 433 |
| 537 // clear upload context | 434 // clear upload context |
| 538 delete request->fUploadContext; | 435 delete request->fUploadContext; |
| 539 request->fUploadContext = nullptr; | 436 request->fUploadContext = nullptr; |
| 540 | 437 |
| 541 return SendTemplate(connection, true, "/"); | 438 return SendTemplate(connection, true, "/"); |
| 542 } | 439 } |
| 543 }; | 440 }; |
| 544 | 441 |
| 545 class DownloadHandler : public UrlHandler { | 442 class DownloadHandler : public UrlHandler { |
| 546 public: | 443 public: |
| 547 bool canHandle(const char* method, const char* url) override { | 444 bool canHandle(const char* method, const char* url) override { |
| 548 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && | 445 return 0 == strcmp(method, MHD_HTTP_METHOD_GET) && |
| 549 0 == strcmp(url, "/download"); | 446 0 == strcmp(url, "/download"); |
| 550 } | 447 } |
| 551 | 448 |
| 552 int handle(Request* request, MHD_Connection* connection, | 449 int handle(Request* request, MHD_Connection* connection, |
| 553 const char* url, const char* method, | 450 const char* url, const char* method, |
| 554 const char* upload_data, size_t* upload_data_size) override { | 451 const char* upload_data, size_t* upload_data_size) override { |
| 555 if (!request->fPicture.get()) { | 452 if (!request->fPicture.get()) { |
| 556 return MHD_NO; | 453 return MHD_NO; |
| 557 } | 454 } |
| 558 | 455 |
| 559 // TODO move to a function | 456 // TODO move to a function |
| 560 // Playback into picture recorder | 457 // Playback into picture recorder |
| 561 SkPictureRecorder recorder; | 458 SkPictureRecorder recorder; |
| 562 SkCanvas* canvas = recorder.beginRecording(kImageWidth, kImageHeight); | 459 SkCanvas* canvas = recorder.beginRecording(Request::kImageWidth, |
| 460 Request::kImageHeight); |
| 563 | 461 |
| 564 request->fDebugCanvas->draw(canvas); | 462 request->fDebugCanvas->draw(canvas); |
| 565 | 463 |
| 566 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); | 464 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); |
| 567 | 465 |
| 568 SkDynamicMemoryWStream outStream; | 466 SkDynamicMemoryWStream outStream; |
| 569 | 467 |
| 570 SkAutoTUnref<SkPixelSerializer> serializer(SkImageEncoder::CreatePixelSe
rializer()); | 468 SkAutoTUnref<SkPixelSerializer> serializer(SkImageEncoder::CreatePixelSe
rializer()); |
| 571 picture->serialize(&outStream, serializer); | 469 picture->serialize(&outStream, serializer); |
| 572 | 470 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 590 const char* url, const char* method, | 488 const char* url, const char* method, |
| 591 const char* upload_data, size_t* upload_data_size) override { | 489 const char* upload_data, size_t* upload_data_size) override { |
| 592 SkTArray<SkString> commands; | 490 SkTArray<SkString> commands; |
| 593 SkStrSplit(url, "/", &commands); | 491 SkStrSplit(url, "/", &commands); |
| 594 | 492 |
| 595 if (!request->fPicture.get() || commands.count() > 2) { | 493 if (!request->fPicture.get() || commands.count() > 2) { |
| 596 return MHD_NO; | 494 return MHD_NO; |
| 597 } | 495 } |
| 598 | 496 |
| 599 // drawTo | 497 // drawTo |
| 600 SkAutoTUnref<SkSurface> surface(createCPUSurface()); | 498 SkAutoTUnref<SkSurface> surface(request->createCPUSurface()); |
| 601 SkCanvas* canvas = surface->getCanvas(); | 499 SkCanvas* canvas = surface->getCanvas(); |
| 602 | 500 |
| 603 int n; | 501 int n; |
| 604 // /info or /info/N | 502 // /info or /info/N |
| 605 if (commands.count() == 1) { | 503 if (commands.count() == 1) { |
| 606 n = request->fDebugCanvas->getSize() - 1; | 504 n = request->fDebugCanvas->getSize() - 1; |
| 607 } else { | 505 } else { |
| 608 sscanf(commands[1].c_str(), "%d", &n); | 506 sscanf(commands[1].c_str(), "%d", &n); |
| 609 } | 507 } |
| 610 | 508 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 } | 618 } |
| 721 return result; | 619 return result; |
| 722 } | 620 } |
| 723 | 621 |
| 724 int skiaserve_main() { | 622 int skiaserve_main() { |
| 725 Request request(SkString("/data")); // This simple server has one request | 623 Request request(SkString("/data")); // This simple server has one request |
| 726 | 624 |
| 727 // create surface | 625 // create surface |
| 728 GrContextOptions grContextOpts; | 626 GrContextOptions grContextOpts; |
| 729 request.fContextFactory.reset(new GrContextFactory(grContextOpts)); | 627 request.fContextFactory.reset(new GrContextFactory(grContextOpts)); |
| 730 request.fSurface.reset(createCPUSurface()); | 628 request.fSurface.reset(request.createCPUSurface()); |
| 731 | 629 |
| 732 struct MHD_Daemon* daemon; | 630 struct MHD_Daemon* daemon; |
| 733 // TODO Add option to bind this strictly to an address, e.g. localhost, for
security. | 631 // TODO Add option to bind this strictly to an address, e.g. localhost, for
security. |
| 734 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, FLAGS_port, nullptr, nu
llptr, | 632 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, FLAGS_port, nullptr, nu
llptr, |
| 735 &answer_to_connection, &request, | 633 &answer_to_connection, &request, |
| 736 MHD_OPTION_END); | 634 MHD_OPTION_END); |
| 737 if (NULL == daemon) { | 635 if (NULL == daemon) { |
| 738 return 1; | 636 return 1; |
| 739 } | 637 } |
| 740 | 638 |
| 741 getchar(); | 639 getchar(); |
| 742 MHD_stop_daemon(daemon); | 640 MHD_stop_daemon(daemon); |
| 743 return 0; | 641 return 0; |
| 744 } | 642 } |
| 745 | 643 |
| 746 #if !defined SK_BUILD_FOR_IOS | 644 #if !defined SK_BUILD_FOR_IOS |
| 747 int main(int argc, char** argv) { | 645 int main(int argc, char** argv) { |
| 748 SkCommandLineFlags::Parse(argc, argv); | 646 SkCommandLineFlags::Parse(argc, argv); |
| 749 return skiaserve_main(); | 647 return skiaserve_main(); |
| 750 } | 648 } |
| 751 #endif | 649 #endif |
| OLD | NEW |