1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 * 8 */ 9 #include <v8.h> 10 #include <include/libplatform/libplatform.h> 11 12 #include "SkV8Example.h" 13 #include "Global.h" 14 #include "JsContext.h" 15 #include "Path2D.h" 16 #include "Path2DBuilder.h" 17 18 #include "gl/GrGLUtil.h" 19 #include "gl/GrGLDefines.h" 20 #include "gl/GrGLInterface.h" 21 #include "GrContext.h" 22 #include "SkApplication.h" 23 #include "SkCommandLineFlags.h" 24 #include "SkData.h" 25 #include "SkDraw.h" 26 #include "SkGpuDevice.h" 27 #include "SkGraphics.h" 28 #include "SkScalar.h" 29 #include "SkSurface.h" 30 31 32 DEFINE_string2(infile, i, NULL, "Name of file to load JS from.\n"); 33 DEFINE_bool(gpu, true, "Use the GPU for rendering."); 34 35 void application_init() { 36 SkGraphics::Init(); 37 SkEvent::Init(); 38 } 39 40 void application_term() { 41 SkEvent::Term(); 42 } 43 44 SkV8ExampleWindow::SkV8ExampleWindow(void* hwnd, JsContext* context) 45 : INHERITED(hwnd) 46 , fJsContext(context) 47 #if SK_SUPPORT_GPU 48 , fCurContext(NULL) 49 , fCurIntf(NULL) 50 , fCurSurface(NULL) 51 #endif 52 { 53 this->setVisibleP(true); 54 this->setClipToBounds(false); 55 56 #if SK_SUPPORT_GPU 57 this->windowSizeChanged(); 58 #endif 59 } 60 61 SkV8ExampleWindow::~SkV8ExampleWindow() { 62 #if SK_SUPPORT_GPU 63 SkSafeUnref(fCurContext); 64 SkSafeUnref(fCurIntf); 65 SkSafeUnref(fCurSurface); 66 #endif 67 } 68 69 #if SK_SUPPORT_GPU 70 void SkV8ExampleWindow::windowSizeChanged() { 71 if (FLAGS_gpu) { 72 SkOSWindow::AttachmentInfo attachmentInfo; 73 bool result = this->attach( 74 SkOSWindow::kNativeGL_BackEndType, 0, false, &attachmentInfo); 75 if (!result) { 76 printf("Failed to attach."); 77 exit(1); 78 } 79 80 fCurIntf = GrGLCreateNativeInterface(); 81 fCurContext = GrContext::Create( 82 kOpenGL_GrBackend, (GrBackendContext) fCurIntf); 83 if (NULL == fCurIntf || NULL == fCurContext) { 84 printf("Failed to initialize GL."); 85 exit(1); 86 } 87 88 GrBackendRenderTargetDesc desc; 89 desc.fWidth = SkScalarRoundToInt(this->width()); 90 desc.fHeight = SkScalarRoundToInt(this->height()); 91 desc.fConfig = kSkia8888_GrPixelConfig; 92 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 93 desc.fSampleCnt = attachmentInfo.fSampleCount; 94 desc.fStencilBits = attachmentInfo.fStencilBits; 95 GrGLint buffer; 96 GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer); 97 desc.fRenderTargetHandle = buffer; 98 99 SkSafeUnref(fCurSurface); 100 fCurSurface = SkSurface::MakeFromBackendRenderTarget(fCurContext, desc, 101 nullptr, nullptr).release(); 102 } 103 } 104 #endif 105 106 #if SK_SUPPORT_GPU 107 SkSurface* SkV8ExampleWindow::createSurface() { 108 if (FLAGS_gpu) { 109 // Increase the ref count since callers of createSurface put the 110 // results in a sk_sp. 111 fCurSurface->ref(); 112 return fCurSurface; 113 } else { 114 return this->INHERITED::createSurface(); 115 } 116 } 117 #endif 118 119 void SkV8ExampleWindow::onSizeChange() { 120 this->INHERITED::onSizeChange(); 121 122 #if SK_SUPPORT_GPU 123 this->windowSizeChanged(); 124 #endif 125 } 126 127 Global* global = NULL; 128 129 void SkV8ExampleWindow::onDraw(SkCanvas* canvas) { 130 131 canvas->save(); 132 canvas->drawColor(SK_ColorWHITE); 133 134 // Now jump into JS and call the onDraw(canvas) method defined there. 135 fJsContext->onDraw(canvas); 136 137 canvas->restore(); 138 139 this->INHERITED::onDraw(canvas); 140 141 #if SK_SUPPORT_GPU 142 if (FLAGS_gpu) { 143 fCurContext->flush(); 144 this->present(); 145 } 146 #endif 147 } 148 149 #ifdef SK_BUILD_FOR_WIN 150 void SkV8ExampleWindow::onHandleInval(const SkIRect& rect) { 151 RECT winRect; 152 winRect.top = rect.top(); 153 winRect.bottom = rect.bottom(); 154 winRect.right = rect.right(); 155 winRect.left = rect.left(); 156 InvalidateRect((HWND)this->getHWND(), &winRect, false); 157 } 158 #endif 159 160 161 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 162 printf("Started\n"); 163 164 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); 165 SkCommandLineFlags::Parse(argc, argv); 166 167 v8::V8::InitializeICU(); 168 v8::Platform* platform = v8::platform::CreateDefaultPlatform(); 169 v8::V8::InitializePlatform(platform); 170 v8::V8::Initialize(); 171 172 v8::Isolate* isolate = v8::Isolate::New(); 173 v8::Isolate::Scope isolate_scope(isolate); 174 v8::HandleScope handle_scope(isolate); 175 isolate->Enter(); 176 177 global = new Global(isolate); 178 179 180 // Set up things to look like a browser by creating 181 // a console object that invokes our print function. 182 const char* startupScript = 183 "function Console() {}; \n" 184 "Console.prototype.log = function() { \n" 185 " var args = Array.prototype.slice.call(arguments).join(' '); \n" 186 " print(args); \n" 187 "}; \n" 188 "console = new Console(); \n"; 189 190 if (!global->parseScript(startupScript)) { 191 printf("Failed to parse startup script: %s.\n", FLAGS_infile[0]); 192 exit(1); 193 } 194 195 const char* script = 196 "function onDraw(canvas) { \n" 197 " canvas.fillStyle = '#00FF00'; \n" 198 " canvas.fillRect(20, 20, 100, 100); \n" 199 " canvas.inval(); \n" 200 "} \n"; 201 202 sk_sp<SkData> data; 203 if (FLAGS_infile.count()) { 204 data = SkData::MakeFromFileName(FLAGS_infile[0]); 205 script = static_cast<const char*>(data->data()); 206 } 207 if (NULL == script) { 208 printf("Could not load file: %s.\n", FLAGS_infile[0]); 209 exit(1); 210 } 211 Path2DBuilder::AddToGlobal(global); 212 Path2D::AddToGlobal(global); 213 214 if (!global->parseScript(script)) { 215 printf("Failed to parse file: %s.\n", FLAGS_infile[0]); 216 exit(1); 217 } 218 219 220 JsContext* jsContext = new JsContext(global); 221 222 if (!jsContext->initialize()) { 223 printf("Failed to initialize.\n"); 224 exit(1); 225 } 226 SkV8ExampleWindow* win = new SkV8ExampleWindow(hwnd, jsContext); 227 global->setWindow(win); 228 229 return win; 230 } 231