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