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 |