| 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 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 struct Request { | 69 struct Request { |
| 70 Request(SkString rootUrl) : fUploadContext(nullptr), fUrlDataManager(rootUrl
) {} | 70 Request(SkString rootUrl) : fUploadContext(nullptr), fUrlDataManager(rootUrl
) {} |
| 71 UploadContext* fUploadContext; | 71 UploadContext* fUploadContext; |
| 72 SkAutoTUnref<SkPicture> fPicture; | 72 SkAutoTUnref<SkPicture> fPicture; |
| 73 SkAutoTUnref<SkDebugCanvas> fDebugCanvas; | 73 SkAutoTUnref<SkDebugCanvas> fDebugCanvas; |
| 74 SkAutoTDelete<GrContextFactory> fContextFactory; | 74 SkAutoTDelete<GrContextFactory> fContextFactory; |
| 75 SkAutoTUnref<SkSurface> fSurface; | 75 SkAutoTUnref<SkSurface> fSurface; |
| 76 UrlDataManager fUrlDataManager; | 76 UrlDataManager fUrlDataManager; |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 // TODO factor this out into functions, also handle CPU path | |
| 80 SkSurface* setupSurface(GrContextFactory* factory) { | |
| 81 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, | |
| 82 GrContextFactory::kNone_GLContextOptions); | |
| 83 int maxRTSize = context->caps()->maxRenderTargetSize(); | |
| 84 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), | |
| 85 SkTMin(kImageHeight, maxRTSize), | |
| 86 kN32_SkColorType, kPremul_SkAlphaType); | |
| 87 uint32_t flags = 0; | |
| 88 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | |
| 89 SkSurface* surface = SkSurface::NewRenderTarget(context, SkSurface::kNo_Budg
eted, info, 0, | |
| 90 &props); | |
| 91 SkASSERT(surface); | |
| 92 | |
| 93 return surface; | |
| 94 } | |
| 95 | |
| 96 static void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t l
ength) { | 79 static void write_png_callback(png_structp png_ptr, png_bytep data, png_size_t l
ength) { |
| 97 SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr); | 80 SkWStream* out = (SkWStream*) png_get_io_ptr(png_ptr); |
| 98 out->write(data, length); | 81 out->write(data, length); |
| 99 } | 82 } |
| 100 | 83 |
| 101 static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 heigh
t, SkWStream& out) { | 84 static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 heigh
t, SkWStream& out) { |
| 102 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL); | 85 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL); |
| 103 SkASSERT(png != nullptr); | 86 SkASSERT(png != nullptr); |
| 104 png_infop info_ptr = png_create_info_struct(png); | 87 png_infop info_ptr = png_create_info_struct(png); |
| 105 SkASSERT(info_ptr != nullptr); | 88 SkASSERT(info_ptr != nullptr); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 void drawToCanvas(Request* request, int n) { | 148 void drawToCanvas(Request* request, int n) { |
| 166 SkCanvas* target = getCanvasFromRequest(request); | 149 SkCanvas* target = getCanvasFromRequest(request); |
| 167 request->fDebugCanvas->drawTo(target, n); | 150 request->fDebugCanvas->drawTo(target, n); |
| 168 } | 151 } |
| 169 | 152 |
| 170 SkData* drawToPng(Request* request, int n) { | 153 SkData* drawToPng(Request* request, int n) { |
| 171 drawToCanvas(request, n); | 154 drawToCanvas(request, n); |
| 172 return writeCanvasToPng(getCanvasFromRequest(request)); | 155 return writeCanvasToPng(getCanvasFromRequest(request)); |
| 173 } | 156 } |
| 174 | 157 |
| 175 SkSurface* setupCpuSurface() { | 158 SkSurface* createCPUSurface() { |
| 176 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColor
Type, | 159 SkImageInfo info = SkImageInfo::Make(kImageWidth, kImageHeight, kN32_SkColor
Type, |
| 177 kPremul_SkAlphaType); | 160 kPremul_SkAlphaType); |
| 178 return SkSurface::NewRaster(info); | 161 return SkSurface::NewRaster(info); |
| 179 } | 162 } |
| 180 | 163 |
| 164 SkSurface* createGPUSurface(Request* request) { |
| 165 GrContext* context = request->fContextFactory->get(GrContextFactory::kNative
_GLContextType, |
| 166 GrContextFactory::kNone_G
LContextOptions); |
| 167 int maxRTSize = context->caps()->maxRenderTargetSize(); |
| 168 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), |
| 169 SkTMin(kImageHeight, maxRTSize), |
| 170 kN32_SkColorType, kPremul_SkAlphaType); |
| 171 uint32_t flags = 0; |
| 172 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
| 173 SkSurface* surface = SkSurface::NewRenderTarget(context, SkSurface::kNo_Budg
eted, info, 0, |
| 174 &props); |
| 175 return surface; |
| 176 } |
| 177 |
| 181 static const size_t kBufferSize = 1024; | 178 static const size_t kBufferSize = 1024; |
| 182 | 179 |
| 183 static int process_upload_data(void* cls, enum MHD_ValueKind kind, | 180 static int process_upload_data(void* cls, enum MHD_ValueKind kind, |
| 184 const char* key, const char* filename, | 181 const char* key, const char* filename, |
| 185 const char* content_type, const char* transfer_en
coding, | 182 const char* content_type, const char* transfer_en
coding, |
| 186 const char* data, uint64_t off, size_t size) { | 183 const char* data, uint64_t off, size_t size) { |
| 187 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); | 184 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); |
| 188 | 185 |
| 189 if (0 != size) { | 186 if (0 != size) { |
| 190 uc->fStream.write(data, size); | 187 uc->fStream.write(data, size); |
| 191 } | 188 } |
| 192 return MHD_YES; | 189 return MHD_YES; |
| 193 } | 190 } |
| 194 | 191 |
| 195 // SendOK just sends an empty response with a 200 OK status code. | 192 // SendOK just sends an empty response with a 200 OK status code. |
| 196 static int SendOK(MHD_Connection* connection) { | 193 static int SendOK(MHD_Connection* connection) { |
| 197 const char* data = ""; | 194 const char* data = ""; |
| 198 | 195 |
| 199 MHD_Response* response = MHD_create_response_from_buffer(strlen(data), | 196 MHD_Response* response = MHD_create_response_from_buffer(strlen(data), |
| 200 (void*)data, | 197 (void*)data, |
| 201 MHD_RESPMEM_PERSIST
ENT); | 198 MHD_RESPMEM_PERSIST
ENT); |
| 202 int ret = MHD_queue_response(connection, 200, response); | 199 int ret = MHD_queue_response(connection, 200, response); |
| 203 MHD_destroy_response(response); | 200 MHD_destroy_response(response); |
| 204 return ret; | 201 return ret; |
| 205 } | 202 } |
| 206 | 203 |
| 204 static int SendError(MHD_Connection* connection, const char* msg) { |
| 205 MHD_Response* response = MHD_create_response_from_buffer(strlen(msg), |
| 206 (void*) msg, |
| 207 MHD_RESPMEM_PERSIST
ENT); |
| 208 int ret = MHD_queue_response(connection, 500, response); |
| 209 MHD_destroy_response(response); |
| 210 return ret; |
| 211 } |
| 212 |
| 207 static int SendData(MHD_Connection* connection, const SkData* data, const char*
type, | 213 static int SendData(MHD_Connection* connection, const SkData* data, const char*
type, |
| 208 bool setContentDisposition = false, const char* dispositionS
tring = nullptr) { | 214 bool setContentDisposition = false, const char* dispositionS
tring = nullptr) { |
| 209 MHD_Response* response = MHD_create_response_from_buffer(data->size(), | 215 MHD_Response* response = MHD_create_response_from_buffer(data->size(), |
| 210 const_cast<void*>(d
ata->data()), | 216 const_cast<void*>(d
ata->data()), |
| 211 MHD_RESPMEM_MUST_CO
PY); | 217 MHD_RESPMEM_MUST_CO
PY); |
| 212 MHD_add_response_header(response, "Content-Type", type); | 218 MHD_add_response_header(response, "Content-Type", type); |
| 213 | 219 |
| 214 if (setContentDisposition) { | 220 if (setContentDisposition) { |
| 215 MHD_add_response_header(response, "Content-Disposition", dispositionStri
ng); | 221 MHD_add_response_header(response, "Content-Disposition", dispositionStri
ng); |
| 216 } | 222 } |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 } | 457 } |
| 452 | 458 |
| 453 int alpha; | 459 int alpha; |
| 454 sscanf(commands[1].c_str(), "%d", &alpha); | 460 sscanf(commands[1].c_str(), "%d", &alpha); |
| 455 | 461 |
| 456 request->fDebugCanvas->setClipVizColor(SkColorSetARGB(alpha, 0, 0, 0)); | 462 request->fDebugCanvas->setClipVizColor(SkColorSetARGB(alpha, 0, 0, 0)); |
| 457 return SendOK(connection); | 463 return SendOK(connection); |
| 458 } | 464 } |
| 459 }; | 465 }; |
| 460 | 466 |
| 467 /** |
| 468 Controls whether GPU rendering is enabled. Posting to /enableGPU/1 turns GPU
on, /enableGPU/0 |
| 469 disables it. |
| 470 */ |
| 471 class EnableGPUHandler : public UrlHandler { |
| 472 public: |
| 473 bool canHandle(const char* method, const char* url) override { |
| 474 static const char* kBasePath = "/enableGPU/"; |
| 475 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
| 476 0 == strncmp(url, kBasePath, strlen(kBasePath)); |
| 477 } |
| 478 |
| 479 int handle(Request* request, MHD_Connection* connection, |
| 480 const char* url, const char* method, |
| 481 const char* upload_data, size_t* upload_data_size) override { |
| 482 SkTArray<SkString> commands; |
| 483 SkStrSplit(url, "/", &commands); |
| 484 |
| 485 if (commands.count() != 2) { |
| 486 return MHD_NO; |
| 487 } |
| 488 |
| 489 int enable; |
| 490 sscanf(commands[1].c_str(), "%d", &enable); |
| 491 |
| 492 if (enable) { |
| 493 SkSurface* surface = createGPUSurface(request); |
| 494 if (surface) { |
| 495 request->fSurface.reset(surface); |
| 496 return SendOK(connection); |
| 497 } |
| 498 return SendError(connection, "Unable to create GPU surface"); |
| 499 } |
| 500 request->fSurface.reset(createCPUSurface()); |
| 501 return SendOK(connection); |
| 502 } |
| 503 }; |
| 504 |
| 461 class PostHandler : public UrlHandler { | 505 class PostHandler : public UrlHandler { |
| 462 public: | 506 public: |
| 463 bool canHandle(const char* method, const char* url) override { | 507 bool canHandle(const char* method, const char* url) override { |
| 464 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && | 508 return 0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
| 465 0 == strcmp(url, "/new"); | 509 0 == strcmp(url, "/new"); |
| 466 } | 510 } |
| 467 | 511 |
| 468 int handle(Request* request, MHD_Connection* connection, | 512 int handle(Request* request, MHD_Connection* connection, |
| 469 const char* url, const char* method, | 513 const char* url, const char* method, |
| 470 const char* upload_data, size_t* upload_data_size) override { | 514 const char* upload_data, size_t* upload_data_size) override { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 496 uc->fPostProcessor = nullptr; | 540 uc->fPostProcessor = nullptr; |
| 497 | 541 |
| 498 // parse picture from stream | 542 // parse picture from stream |
| 499 request->fPicture.reset( | 543 request->fPicture.reset( |
| 500 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachA
sStream())); | 544 SkPicture::CreateFromStream(request->fUploadContext->fStream.detachA
sStream())); |
| 501 if (!request->fPicture.get()) { | 545 if (!request->fPicture.get()) { |
| 502 fprintf(stderr, "Could not create picture from stream.\n"); | 546 fprintf(stderr, "Could not create picture from stream.\n"); |
| 503 return MHD_NO; | 547 return MHD_NO; |
| 504 } | 548 } |
| 505 | 549 |
| 506 // create surface | |
| 507 GrContextOptions grContextOpts; | |
| 508 request->fContextFactory.reset(new GrContextFactory(grContextOpts)); | |
| 509 request->fSurface.reset(setupSurface(request->fContextFactory.get())); | |
| 510 | |
| 511 // pour picture into debug canvas | 550 // pour picture into debug canvas |
| 512 request->fDebugCanvas.reset(new SkDebugCanvas(kImageWidth, kImageHeight)
); | 551 request->fDebugCanvas.reset(new SkDebugCanvas(kImageWidth, kImageHeight)
); |
| 513 request->fDebugCanvas->drawPicture(request->fPicture); | 552 request->fDebugCanvas->drawPicture(request->fPicture); |
| 514 | 553 |
| 515 // clear upload context | 554 // clear upload context |
| 516 delete request->fUploadContext; | 555 delete request->fUploadContext; |
| 517 request->fUploadContext = nullptr; | 556 request->fUploadContext = nullptr; |
| 518 | 557 |
| 519 return SendTemplate(connection, true, "/"); | 558 return SendTemplate(connection, true, "/"); |
| 520 } | 559 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 const char* url, const char* method, | 607 const char* url, const char* method, |
| 569 const char* upload_data, size_t* upload_data_size) override { | 608 const char* upload_data, size_t* upload_data_size) override { |
| 570 SkTArray<SkString> commands; | 609 SkTArray<SkString> commands; |
| 571 SkStrSplit(url, "/", &commands); | 610 SkStrSplit(url, "/", &commands); |
| 572 | 611 |
| 573 if (!request->fPicture.get() || commands.count() > 2) { | 612 if (!request->fPicture.get() || commands.count() > 2) { |
| 574 return MHD_NO; | 613 return MHD_NO; |
| 575 } | 614 } |
| 576 | 615 |
| 577 // drawTo | 616 // drawTo |
| 578 SkAutoTUnref<SkSurface> surface(setupCpuSurface()); | 617 SkAutoTUnref<SkSurface> surface(createCPUSurface()); |
| 579 SkCanvas* canvas = surface->getCanvas(); | 618 SkCanvas* canvas = surface->getCanvas(); |
| 580 | 619 |
| 581 int n; | 620 int n; |
| 582 // /info or /info/N | 621 // /info or /info/N |
| 583 if (commands.count() == 1) { | 622 if (commands.count() == 1) { |
| 584 n = request->fDebugCanvas->getSize() - 1; | 623 n = request->fDebugCanvas->getSize() - 1; |
| 585 } else { | 624 } else { |
| 586 sscanf(commands[1].c_str(), "%d", &n); | 625 sscanf(commands[1].c_str(), "%d", &n); |
| 587 } | 626 } |
| 588 | 627 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 }; | 708 }; |
| 670 | 709 |
| 671 class UrlManager { | 710 class UrlManager { |
| 672 public: | 711 public: |
| 673 UrlManager() { | 712 UrlManager() { |
| 674 // Register handlers | 713 // Register handlers |
| 675 fHandlers.push_back(new RootHandler); | 714 fHandlers.push_back(new RootHandler); |
| 676 fHandlers.push_back(new PostHandler); | 715 fHandlers.push_back(new PostHandler); |
| 677 fHandlers.push_back(new ImgHandler); | 716 fHandlers.push_back(new ImgHandler); |
| 678 fHandlers.push_back(new ClipAlphaHandler); | 717 fHandlers.push_back(new ClipAlphaHandler); |
| 718 fHandlers.push_back(new EnableGPUHandler); |
| 679 fHandlers.push_back(new CmdHandler); | 719 fHandlers.push_back(new CmdHandler); |
| 680 fHandlers.push_back(new InfoHandler); | 720 fHandlers.push_back(new InfoHandler); |
| 681 fHandlers.push_back(new DownloadHandler); | 721 fHandlers.push_back(new DownloadHandler); |
| 682 fHandlers.push_back(new DataHandler); | 722 fHandlers.push_back(new DataHandler); |
| 683 fHandlers.push_back(new FaviconHandler); | 723 fHandlers.push_back(new FaviconHandler); |
| 684 fHandlers.push_back(new BreakHandler); | 724 fHandlers.push_back(new BreakHandler); |
| 685 } | 725 } |
| 686 | 726 |
| 687 ~UrlManager() { | 727 ~UrlManager() { |
| 688 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } | 728 for (int i = 0; i < fHandlers.count(); i++) { delete fHandlers[i]; } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 716 int result = kUrlManager.invoke(request, connection, url, method, upload_dat
a, | 756 int result = kUrlManager.invoke(request, connection, url, method, upload_dat
a, |
| 717 upload_data_size); | 757 upload_data_size); |
| 718 if (MHD_NO == result) { | 758 if (MHD_NO == result) { |
| 719 fprintf(stderr, "Invalid method and / or url: %s %s\n", method, url); | 759 fprintf(stderr, "Invalid method and / or url: %s %s\n", method, url); |
| 720 } | 760 } |
| 721 return result; | 761 return result; |
| 722 } | 762 } |
| 723 | 763 |
| 724 int skiaserve_main() { | 764 int skiaserve_main() { |
| 725 Request request(SkString("/data")); // This simple server has one request | 765 Request request(SkString("/data")); // This simple server has one request |
| 766 |
| 767 // create surface |
| 768 GrContextOptions grContextOpts; |
| 769 request.fContextFactory.reset(new GrContextFactory(grContextOpts)); |
| 770 request.fSurface.reset(createCPUSurface()); |
| 771 |
| 726 struct MHD_Daemon* daemon; | 772 struct MHD_Daemon* daemon; |
| 727 // TODO Add option to bind this strictly to an address, e.g. localhost, for
security. | 773 // TODO Add option to bind this strictly to an address, e.g. localhost, for
security. |
| 728 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, FLAGS_port, nullptr, nu
llptr, | 774 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, FLAGS_port, nullptr, nu
llptr, |
| 729 &answer_to_connection, &request, | 775 &answer_to_connection, &request, |
| 730 MHD_OPTION_END); | 776 MHD_OPTION_END); |
| 731 if (NULL == daemon) { | 777 if (NULL == daemon) { |
| 732 return 1; | 778 return 1; |
| 733 } | 779 } |
| 734 | 780 |
| 735 getchar(); | 781 getchar(); |
| 736 MHD_stop_daemon(daemon); | 782 MHD_stop_daemon(daemon); |
| 737 return 0; | 783 return 0; |
| 738 } | 784 } |
| 739 | 785 |
| 740 #if !defined SK_BUILD_FOR_IOS | 786 #if !defined SK_BUILD_FOR_IOS |
| 741 int main(int argc, char** argv) { | 787 int main(int argc, char** argv) { |
| 742 SkCommandLineFlags::Parse(argc, argv); | 788 SkCommandLineFlags::Parse(argc, argv); |
| 743 return skiaserve_main(); | 789 return skiaserve_main(); |
| 744 } | 790 } |
| 745 #endif | 791 #endif |
| OLD | NEW |