Index: tools/skiaserve/skiaserve.cpp |
diff --git a/tools/skiaserve/skiaserve.cpp b/tools/skiaserve/skiaserve.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..effd28973c226bd007a98b7e185b63aa04001d58 |
--- /dev/null |
+++ b/tools/skiaserve/skiaserve.cpp |
@@ -0,0 +1,183 @@ |
+/* |
+ * Copyright 2016 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "GrCaps.h" |
+#include "GrContextFactory.h" |
+#include "SkCanvas.h" |
+#include "SkCommandLineFlags.h" |
+#include "SkOSFile.h" |
+#include <SkPicture.h> |
+#include "SkStream.h" |
+#include "SkSurface.h" |
+ |
+// temporary junk |
+#include "SkGradientShader.h" |
+ |
+#include <stdio.h> |
+#include <sys/types.h> |
+#include <sys/select.h> |
+#include <sys/stat.h> |
+#include <sys/socket.h> |
+#include <fcntl.h> |
+#include <microhttpd.h> |
+ |
+// To get image decoders linked in we have to do the below magic |
+#include "SkForceLinking.h" |
+#include "SkImageDecoder.h" |
+__SK_FORCE_IMAGE_DECODER_LINKING; |
+ |
+// TODO make this configurable |
+#define PORT 8888 |
+ |
+DEFINE_string(dir, "skps", "Directory to read skp."); |
+DEFINE_string(name, "desk_carsvg", "skp to load."); |
+DEFINE_bool(useTemplate, true, "whether or not to use the skdebugger template string."); |
+ |
+// TODO probably want to make this configurable |
+static const int kImageWidth = 1920; |
+static const int kImageHeight = 1080; |
+ |
+// TODO factor this out into functions, also handle CPU path |
+SkData* setupAndDrawToCanvas(const char* path, SkString* error) { |
+ GrContextOptions grContextOpts; |
+ SkAutoTDelete<GrContextFactory> factory(new GrContextFactory(grContextOpts)); |
+ |
+ GrContext* context = factory->get(GrContextFactory::kNative_GLContextType, |
+ GrContextFactory::kNone_GLContextOptions); |
+ int maxRTSize = context->caps()->maxRenderTargetSize(); |
+ SkImageInfo info = SkImageInfo::Make(SkTMin(kImageWidth, maxRTSize), |
+ SkTMin(kImageHeight, maxRTSize), |
+ kN32_SkColorType, kPremul_SkAlphaType); |
+ uint32_t flags = 0; |
+ SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); |
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, |
+ SkSurface::kNo_Budgeted, info, |
+ 0, &props)); |
+ SkASSERT(surface.get()); |
+ |
+ SkGLContext* gl = factory->getContextInfo(GrContextFactory::kNative_GLContextType, |
+ GrContextFactory::kNone_GLContextOptions).fGLContext; |
+ gl->makeCurrent(); |
+ |
+ // draw |
+ SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path)); |
+ if (stream.get() == nullptr) { |
+ error->appendf("Could not read %s.\n", path); |
+ return nullptr; |
+ } |
+ |
+ SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get())); |
+ if (pic.get() == nullptr) { |
+ error->appendf("Could not read %s as an SkPicture.\n", path); |
+ return nullptr; |
+ } |
+ |
+ SkCanvas* canvas = surface->getCanvas(); |
+ canvas->drawPicture(pic); |
+ |
+ // capture pixels |
+ SkBitmap bmp; |
+ bmp.setInfo(canvas->imageInfo()); |
+ if (!canvas->readPixels(&bmp, 0, 0)) { |
+ error->appendf("Can't read canvas pixels.\n"); |
+ return nullptr; |
+ } |
+ |
+ // write to png |
+ SkData* data = SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 100); |
+ if (!data) { |
+ error->appendf("Can't encode a PNG.\n"); |
+ return nullptr; |
+ } |
+ return data; |
+} |
+ |
+// TODO move to template file |
+SkString generateTemplate(SkString source) { |
+ SkString debuggerTemplate; |
+ debuggerTemplate.appendf( |
+ "<!DOCTYPE html>\n" |
+ "<html>\n" |
+ "<head>\n" |
+ " <title>SkDebugger</title>\n" |
+ " <meta charset=\"utf-8\" />\n" |
+ " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\n" |
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" |
+ " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n" |
+ " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" |
+ "</head>\n" |
+ "<body class=\"fullbleed layout vertical\">\n" |
+ " <debugger-app-sk>This is the app." |
+ " </debugger-app-sk>\n" |
+ "</body>\n" |
+ "</html>", source.c_str(), source.c_str()); |
+ return debuggerTemplate; |
+ |
+} |
+ |
+int answer_to_connection(void* cls, struct MHD_Connection* connection, |
+ const char* url, const char* method, const char* version, |
+ const char* upload_data, size_t* upload_data_size, |
+ void** con_cls) { |
+ printf ("New %s request for %s using version %s\n", method, url, version); |
+ |
+ struct MHD_Response* response; |
+ |
+ // serve html to root |
+ // TODO better url handling |
+ int ret; |
+ if (0 == strcmp("/", url)) { |
+ SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org")); |
+ |
+ response = MHD_create_response_from_buffer(debuggerTemplate.size(), |
+ (void*)const_cast<char*>(debuggerTemplate.c_str()), |
+ MHD_RESPMEM_MUST_COPY); |
+ ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
+ MHD_destroy_response(response); |
+ return MHD_YES; |
+ } |
+ |
+ // otherwise serve an image |
+ // TODO take from post |
+ SkString resourceName; |
+ resourceName.appendf("%s/%s.skp", FLAGS_dir[0], FLAGS_name[0]); |
+ SkDebugf("Loading skp: %s\n", resourceName.c_str()); |
+ |
+ SkString error; |
+ SkAutoTUnref<SkData> data(setupAndDrawToCanvas(resourceName.c_str(), &error)); |
+ if (!data) { |
+ // TODO send error |
+ return MHD_YES; |
+ } |
+ |
+ response = MHD_create_response_from_buffer(data->size(), const_cast<void*>(data->data()), |
+ MHD_RESPMEM_MUST_COPY); |
+ MHD_add_response_header(response, "Content-Type", "image/png"); |
+ ret = MHD_queue_response(connection, MHD_HTTP_OK, response); |
+ MHD_destroy_response(response); |
+ return ret; |
+} |
+ |
+int skiaserve_main() { |
+ struct MHD_Daemon* daemon; |
+ daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, |
+ &answer_to_connection, NULL, MHD_OPTION_END); |
+ if (NULL == daemon) { |
+ return 1; |
+ } |
+ |
+ getchar(); |
+ MHD_stop_daemon(daemon); |
+ return 0; |
+} |
+ |
+#if !defined SK_BUILD_FOR_IOS |
+int main(int argc, char** argv) { |
+ SkCommandLineFlags::Parse(argc, argv); |
+ return skiaserve_main(); |
+} |
+#endif |