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