| 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" |
| 11 #include "SkCommandLineFlags.h" | 11 #include "SkCommandLineFlags.h" |
| 12 #include "SkOSFile.h" | 12 #include "SkPicture.h" |
| 13 #include <SkPicture.h> | |
| 14 #include "SkStream.h" | 13 #include "SkStream.h" |
| 15 #include "SkSurface.h" | 14 #include "SkSurface.h" |
| 16 | 15 |
| 17 // temporary junk | |
| 18 #include "SkGradientShader.h" | |
| 19 | |
| 20 #include <stdio.h> | |
| 21 #include <sys/types.h> | |
| 22 #include <sys/select.h> | |
| 23 #include <sys/stat.h> | |
| 24 #include <sys/socket.h> | 16 #include <sys/socket.h> |
| 25 #include <fcntl.h> | |
| 26 #include <microhttpd.h> | 17 #include <microhttpd.h> |
| 27 | 18 |
| 28 // To get image decoders linked in we have to do the below magic | 19 // To get image decoders linked in we have to do the below magic |
| 29 #include "SkForceLinking.h" | 20 #include "SkForceLinking.h" |
| 30 #include "SkImageDecoder.h" | 21 #include "SkImageDecoder.h" |
| 31 __SK_FORCE_IMAGE_DECODER_LINKING; | 22 __SK_FORCE_IMAGE_DECODER_LINKING; |
| 32 | 23 |
| 33 // TODO make this configurable | 24 // TODO make this configurable |
| 34 #define PORT 8888 | 25 #define PORT 8888 |
| 35 | 26 |
| 36 DEFINE_string(dir, "skps", "Directory to read skp."); | 27 DEFINE_string(dir, "skps", "Directory to read skp."); |
| 37 DEFINE_string(name, "desk_carsvg", "skp to load."); | 28 DEFINE_string(name, "desk_carsvg", "skp to load."); |
| 38 DEFINE_bool(useTemplate, true, "whether or not to use the skdebugger template st
ring."); | 29 DEFINE_bool(useTemplate, true, "whether or not to use the skdebugger template st
ring."); |
| 39 | 30 |
| 40 // TODO probably want to make this configurable | 31 // TODO probably want to make this configurable |
| 41 static const int kImageWidth = 1920; | 32 static const int kImageWidth = 1920; |
| 42 static const int kImageHeight = 1080; | 33 static const int kImageHeight = 1080; |
| 43 | 34 |
| 44 // TODO factor this out into functions, also handle CPU path | 35 // TODO factor this out into functions, also handle CPU path |
| 45 SkData* setupAndDrawToCanvas(const char* path, SkString* error) { | 36 SkData* setupAndDrawToCanvas(SkStream* stream, SkString* error) { |
| 46 GrContextOptions grContextOpts; | 37 GrContextOptions grContextOpts; |
| 47 SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts))
; | 38 SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts))
; |
| 48 | 39 |
| 49 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, | 40 GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, |
| 50 GrContextFactory::kNone_GLContextOptions); | 41 GrContextFactory::kNone_GLContextOptions); |
| 51 int maxRTSize = context->caps()->maxRenderTargetSize(); | 42 int maxRTSize = context->caps()->maxRenderTargetSize(); |
| 52 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), | 43 SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), |
| 53 SkTMin(kImageHeight, maxRTSize), | 44 SkTMin(kImageHeight, maxRTSize), |
| 54 kN32_SkColorType, kPremul_SkAlphaType); | 45 kN32_SkColorType, kPremul_SkAlphaType); |
| 55 uint32_t flags = 0; | 46 uint32_t flags = 0; |
| 56 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); | 47 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
| 57 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, | 48 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, |
| 58 SkSurface::kNo_Bu
dgeted, info, | 49 SkSurface::kNo_Bu
dgeted, info, |
| 59 0, &props)); | 50 0, &props)); |
| 60 SkASSERT(surface.get()); | 51 SkASSERT(surface.get()); |
| 61 | 52 |
| 62 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex
tType, | 53 SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContex
tType, |
| 63 GrContextFactory::kNone_GLContextO
ptions).fGLContext; | 54 GrContextFactory::kNone_GLContextO
ptions).fGLContext; |
| 64 gl->makeCurrent(); | 55 gl->makeCurrent(); |
| 65 | 56 |
| 66 // draw | 57 // draw |
| 67 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path)); | 58 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream)); |
| 68 if (stream.get() == nullptr) { | 59 if (pic.get() == nullptr) { |
| 69 error->appendf("Could not read %s.\n", path); | 60 error->appendf("Could not create picture from stream.\n"); |
| 70 return nullptr; | 61 return nullptr; |
| 71 } | 62 } |
| 72 | 63 |
| 73 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get())); | |
| 74 if (pic.get() == nullptr) { | |
| 75 error->appendf("Could not read %s as an SkPicture.\n", path); | |
| 76 return nullptr; | |
| 77 } | |
| 78 | |
| 79 SkCanvas* canvas = surface->getCanvas(); | 64 SkCanvas* canvas = surface->getCanvas(); |
| 80 canvas->drawPicture(pic); | 65 canvas->drawPicture(pic); |
| 81 | 66 |
| 82 // capture pixels | 67 // capture pixels |
| 83 SkBitmap bmp; | 68 SkBitmap bmp; |
| 84 bmp.setInfo(canvas->imageInfo()); | 69 bmp.setInfo(canvas->imageInfo()); |
| 85 if (!canvas->readPixels(&bmp, 0, 0)) { | 70 if (!canvas->readPixels(&bmp, 0, 0)) { |
| 86 error->appendf("Can't read canvas pixels.\n"); | 71 error->appendf("Can't read canvas pixels.\n"); |
| 87 return nullptr; | 72 return nullptr; |
| 88 } | 73 } |
| 89 | 74 |
| 90 // write to png | 75 // write to png |
| 91 SkData* data = SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 10
0); | 76 SkData* data = SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 10
0); |
| 92 if (!data) { | 77 if (!data) { |
| 93 error->appendf("Can't encode a PNG.\n"); | 78 error->appendf("Can't encode a PNG.\n"); |
| 94 return nullptr; | 79 return nullptr; |
| 95 } | 80 } |
| 96 return data; | 81 return data; |
| 97 } | 82 } |
| 98 | |
| 99 // TODO move to template file | 83 // TODO move to template file |
| 100 SkString generateTemplate(SkString source) { | 84 SkString generateTemplate(SkString source) { |
| 101 SkString debuggerTemplate; | 85 SkString debuggerTemplate; |
| 102 debuggerTemplate.appendf( | 86 debuggerTemplate.appendf( |
| 103 "<!DOCTYPE html>\n" | 87 "<!DOCTYPE html>\n" |
| 104 "<html>\n" | 88 "<html>\n" |
| 105 "<head>\n" | 89 "<head>\n" |
| 106 " <title>SkDebugger</title>\n" | 90 " <title>SkDebugger</title>\n" |
| 107 " <meta charset=\"utf-8\" />\n" | 91 " <meta charset=\"utf-8\" />\n" |
| 108 " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\
n" | 92 " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\
n" |
| 109 " <meta name=\"viewport\" content=\"width=device-width, initial-scale
=1.0\">\n" | 93 " <meta name=\"viewport\" content=\"width=device-width, initial-scale
=1.0\">\n" |
| 110 " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=
\"utf-8\"></script>\n" | 94 " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=
\"utf-8\"></script>\n" |
| 111 " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" | 95 " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" |
| 112 "</head>\n" | 96 "</head>\n" |
| 113 "<body class=\"fullbleed layout vertical\">\n" | 97 "<body class=\"fullbleed layout vertical\">\n" |
| 114 " <debugger-app-sk>This is the app." | 98 " <debugger-app-sk>This is the app." |
| 115 " </debugger-app-sk>\n" | 99 " </debugger-app-sk>\n" |
| 116 "</body>\n" | 100 "</body>\n" |
| 117 "</html>", source.c_str(), source.c_str()); | 101 "</html>", source.c_str(), source.c_str()); |
| 118 return debuggerTemplate; | 102 return debuggerTemplate; |
| 119 | 103 |
| 120 } | 104 } |
| 121 | 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 |
| 118 static const size_t kBufferSize = 1024; |
| 119 |
| 120 static int process_upload_data(void* cls, enum MHD_ValueKind kind, |
| 121 const char* key, const char* filename, |
| 122 const char* content_type, const char* transfer_en
coding, |
| 123 const char* data, uint64_t off, size_t size) { |
| 124 struct UploadContext* uc = reinterpret_cast<UploadContext*>(cls); |
| 125 |
| 126 if (0 != size) { |
| 127 uc->stream.write(data, size); |
| 128 } |
| 129 return MHD_YES; |
| 130 } |
| 131 |
| 122 int answer_to_connection(void* cls, struct MHD_Connection* connection, | 132 int answer_to_connection(void* cls, struct MHD_Connection* connection, |
| 123 const char* url, const char* method, const char* versio
n, | 133 const char* url, const char* method, const char* versio
n, |
| 124 const char* upload_data, size_t* upload_data_size, | 134 const char* upload_data, size_t* upload_data_size, |
| 125 void** con_cls) { | 135 void** con_cls) { |
| 126 printf ("New %s request for %s using version %s\n", method, url, version); | 136 SkDebugf("New %s request for %s using version %s\n", method, url, version); |
| 127 | 137 |
| 128 struct MHD_Response* response; | 138 Request* request = reinterpret_cast<Request*>(cls); |
| 129 | 139 |
| 130 // serve html to root | 140 MHD_Response* response; |
| 131 // TODO better url handling | 141 int ret = MHD_NO; |
| 132 int ret; | 142 |
| 133 if (0 == strcmp("/", url)) { | 143 // TODO url handlers |
| 144 // handle uploads |
| 145 if (0 == strcmp(method, MHD_HTTP_METHOD_POST) && |
| 146 0 == strcmp(url, "/new")) { |
| 147 UploadContext* uc = request->fUploadContext; |
| 148 |
| 149 // New connection |
| 150 if (!uc) { |
| 151 // TODO make this a method on request |
| 152 uc = new UploadContext; |
| 153 uc->connection = connection; |
| 154 uc->pp = MHD_create_post_processor(connection, kBufferSize, &process
_upload_data, uc); |
| 155 SkASSERT(uc->pp); |
| 156 |
| 157 request->fUploadContext = uc; |
| 158 return MHD_YES; |
| 159 } |
| 160 |
| 161 // in process upload |
| 162 if (0 != *upload_data_size) { |
| 163 SkASSERT(uc->pp); |
| 164 MHD_post_process(uc->pp, upload_data, *upload_data_size); |
| 165 *upload_data_size = 0; |
| 166 return MHD_YES; |
| 167 } |
| 168 |
| 169 // end of upload |
| 170 MHD_destroy_post_processor(uc->pp); |
| 171 uc->pp = nullptr; |
| 172 |
| 173 // TODO response |
| 174 SkString error; |
| 175 SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error)
; |
| 176 if (!data) { |
| 177 // TODO send error |
| 178 return MHD_YES; |
| 179 } |
| 180 |
| 181 request->fPNG.reset(data); |
| 182 // TODO Hack |
| 134 SkString debuggerTemplate = generateTemplate(SkString("http://debugger.s
kia.org")); | 183 SkString debuggerTemplate = generateTemplate(SkString("http://debugger.s
kia.org")); |
| 135 | 184 |
| 136 response = MHD_create_response_from_buffer(debuggerTemplate.size(), | 185 response = MHD_create_response_from_buffer(debuggerTemplate.size(), |
| 137 (void*)const_cast<char*>(debu
ggerTemplate.c_str()), | 186 (void*) const_cast<char*>(deb
uggerTemplate.c_str()), |
| 138 MHD_RESPMEM_MUST_COPY); | 187 MHD_RESPMEM_MUST_COPY); |
| 188 |
| 139 ret = MHD_queue_response(connection, MHD_HTTP_OK, response); | 189 ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
| 140 MHD_destroy_response(response); | 190 MHD_destroy_response(response); |
| 141 return MHD_YES; | 191 } else if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) { |
| 192 if (0 == strcmp(url, "/")) { |
| 193 SkString debuggerTemplate = generateTemplate(SkString("http://debugg
er.skia.org")); |
| 194 |
| 195 response = MHD_create_response_from_buffer(debuggerTemplate.size(), |
| 196 (void*) const_cast<char*>
(debuggerTemplate.c_str()), |
| 197 MHD_RESPMEM_MUST_COPY); |
| 198 |
| 199 ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
| 200 MHD_destroy_response(response); |
| 201 } else if (0 == strcmp(url, "/img")) { |
| 202 if (request->fPNG.get()) { |
| 203 SkData* data = request->fPNG.get(); |
| 204 response = MHD_create_response_from_buffer(data->size(), |
| 205 const_cast<void*>(dat
a->data()), |
| 206 MHD_RESPMEM_MUST_COPY
); |
| 207 MHD_add_response_header(response, "Content-Type", "image/png"); |
| 208 |
| 209 ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
| 210 MHD_destroy_response(response); |
| 211 } |
| 212 } |
| 213 } else { |
| 214 SkFAIL("whoops, need proper error handling"); |
| 215 return MHD_NO; |
| 142 } | 216 } |
| 143 | 217 |
| 144 // otherwise serve an image | |
| 145 // TODO take from post | |
| 146 SkString resourceName; | |
| 147 resourceName.appendf("%s/%s.skp", FLAGS_dir[0], FLAGS_name[0]); | |
| 148 SkDebugf("Loading skp: %s\n", resourceName.c_str()); | |
| 149 | |
| 150 SkString error; | |
| 151 SkAutoTUnref<SkData> data(setupAndDrawToCanvas(resourceName.c_str(), &error)
); | |
| 152 if (!data) { | |
| 153 // TODO send error | |
| 154 return MHD_YES; | |
| 155 } | |
| 156 | |
| 157 response = MHD_create_response_from_buffer(data->size(), const_cast<void*>(d
ata->data()), | |
| 158 MHD_RESPMEM_MUST_COPY); | |
| 159 MHD_add_response_header(response, "Content-Type", "image/png"); | |
| 160 ret = MHD_queue_response(connection, MHD_HTTP_OK, response); | |
| 161 MHD_destroy_response(response); | |
| 162 return ret; | 218 return ret; |
| 163 } | 219 } |
| 164 | 220 |
| 165 int skiaserve_main() { | 221 int skiaserve_main() { |
| 222 Request request; // This simple server has one request |
| 166 struct MHD_Daemon* daemon; | 223 struct MHD_Daemon* daemon; |
| 167 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, | 224 daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, nullptr, nullptr, |
| 168 &answer_to_connection, NULL, MHD_OPTION_END); | 225 &answer_to_connection, &request, |
| 226 MHD_OPTION_END); |
| 169 if (NULL == daemon) { | 227 if (NULL == daemon) { |
| 170 return 1; | 228 return 1; |
| 171 } | 229 } |
| 172 | 230 |
| 173 getchar(); | 231 getchar(); |
| 174 MHD_stop_daemon(daemon); | 232 MHD_stop_daemon(daemon); |
| 175 return 0; | 233 return 0; |
| 176 } | 234 } |
| 177 | 235 |
| 178 #if !defined SK_BUILD_FOR_IOS | 236 #if !defined SK_BUILD_FOR_IOS |
| 179 int main(int argc, char** argv) { | 237 int main(int argc, char** argv) { |
| 180 SkCommandLineFlags::Parse(argc, argv); | 238 SkCommandLineFlags::Parse(argc, argv); |
| 181 return skiaserve_main(); | 239 return skiaserve_main(); |
| 182 } | 240 } |
| 183 #endif | 241 #endif |
| OLD | NEW |