152edc4d05380c88de5b334479ad8e537ef2b4925caryclark/* 252edc4d05380c88de5b334479ad8e537ef2b4925caryclark * Copyright 2015 Google Inc. 352edc4d05380c88de5b334479ad8e537ef2b4925caryclark * 452edc4d05380c88de5b334479ad8e537ef2b4925caryclark * 552edc4d05380c88de5b334479ad8e537ef2b4925caryclark * Use of this source code is governed by a BSD-style license that can be 652edc4d05380c88de5b334479ad8e537ef2b4925caryclark * found in the LICENSE file. 752edc4d05380c88de5b334479ad8e537ef2b4925caryclark * 852edc4d05380c88de5b334479ad8e537ef2b4925caryclark */ 952edc4d05380c88de5b334479ad8e537ef2b4925caryclark 1052edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "HelloWorld.h" 1152edc4d05380c88de5b334479ad8e537ef2b4925caryclark 1252edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "gl/GrGLInterface.h" 1352edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkApplication.h" 1452edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkCanvas.h" 1552edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkGradientShader.h" 1652edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkGraphics.h" 1752edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkGr.h" 1852edc4d05380c88de5b334479ad8e537ef2b4925caryclark 1952edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid application_init() { 2052edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkGraphics::Init(); 2152edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkEvent::Init(); 2252edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 2352edc4d05380c88de5b334479ad8e537ef2b4925caryclark 2452edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid application_term() { 2552edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkEvent::Term(); 2652edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkGraphics::Term(); 2752edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 2852edc4d05380c88de5b334479ad8e537ef2b4925caryclark 2952edc4d05380c88de5b334479ad8e537ef2b4925caryclarkHelloWorldWindow::HelloWorldWindow(void* hwnd) 3052edc4d05380c88de5b334479ad8e537ef2b4925caryclark : INHERITED(hwnd) { 3152edc4d05380c88de5b334479ad8e537ef2b4925caryclark fType = kGPU_DeviceType; 3252edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRenderTarget = NULL; 3352edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRotationAngle = 0; 3452edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setTitle(); 3552edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setUpBackend(); 3652edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 3752edc4d05380c88de5b334479ad8e537ef2b4925caryclark 3852edc4d05380c88de5b334479ad8e537ef2b4925caryclarkHelloWorldWindow::~HelloWorldWindow() { 3952edc4d05380c88de5b334479ad8e537ef2b4925caryclark tearDownBackend(); 4052edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 4152edc4d05380c88de5b334479ad8e537ef2b4925caryclark 4252edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::tearDownBackend() { 4352edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkSafeUnref(fContext); 4452edc4d05380c88de5b334479ad8e537ef2b4925caryclark fContext = NULL; 4552edc4d05380c88de5b334479ad8e537ef2b4925caryclark 4652edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkSafeUnref(fInterface); 4752edc4d05380c88de5b334479ad8e537ef2b4925caryclark fInterface = NULL; 4852edc4d05380c88de5b334479ad8e537ef2b4925caryclark 4952edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkSafeUnref(fRenderTarget); 5052edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRenderTarget = NULL; 5152edc4d05380c88de5b334479ad8e537ef2b4925caryclark 5252edc4d05380c88de5b334479ad8e537ef2b4925caryclark INHERITED::detach(); 5352edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 5452edc4d05380c88de5b334479ad8e537ef2b4925caryclark 5552edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::setTitle() { 5652edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkString title("Hello World "); 5752edc4d05380c88de5b334479ad8e537ef2b4925caryclark title.appendf(fType == kRaster_DeviceType ? "raster" : "opengl"); 5852edc4d05380c88de5b334479ad8e537ef2b4925caryclark INHERITED::setTitle(title.c_str()); 5952edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 6052edc4d05380c88de5b334479ad8e537ef2b4925caryclark 6152edc4d05380c88de5b334479ad8e537ef2b4925caryclarkbool HelloWorldWindow::setUpBackend() { 6252edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setColorType(kRGBA_8888_SkColorType); 6352edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setVisibleP(true); 6452edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setClipToBounds(false); 6552edc4d05380c88de5b334479ad8e537ef2b4925caryclark 6652edc4d05380c88de5b334479ad8e537ef2b4925caryclark bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo); 6752edc4d05380c88de5b334479ad8e537ef2b4925caryclark if (false == result) { 6852edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkDebugf("Not possible to create backend.\n"); 6952edc4d05380c88de5b334479ad8e537ef2b4925caryclark detach(); 7052edc4d05380c88de5b334479ad8e537ef2b4925caryclark return false; 7152edc4d05380c88de5b334479ad8e537ef2b4925caryclark } 7252edc4d05380c88de5b334479ad8e537ef2b4925caryclark 7352edc4d05380c88de5b334479ad8e537ef2b4925caryclark fInterface = GrGLCreateNativeInterface(); 7452edc4d05380c88de5b334479ad8e537ef2b4925caryclark 7552edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkASSERT(NULL != fInterface); 7652edc4d05380c88de5b334479ad8e537ef2b4925caryclark 7752edc4d05380c88de5b334479ad8e537ef2b4925caryclark fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface); 7852edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkASSERT(NULL != fContext); 7952edc4d05380c88de5b334479ad8e537ef2b4925caryclark 8052edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setUpRenderTarget(); 8152edc4d05380c88de5b334479ad8e537ef2b4925caryclark return true; 8252edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 8352edc4d05380c88de5b334479ad8e537ef2b4925caryclark 8452edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::setUpRenderTarget() { 8552edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkSafeUnref(fRenderTarget); 8652edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRenderTarget = this->renderTarget(fAttachmentInfo, fInterface, fContext); 8752edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 8852edc4d05380c88de5b334479ad8e537ef2b4925caryclark 8952edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::drawContents(SkCanvas* canvas) { 9052edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Clear background 9152edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->drawColor(SK_ColorWHITE); 9252edc4d05380c88de5b334479ad8e537ef2b4925caryclark 9352edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkPaint paint; 9452edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setColor(SK_ColorRED); 9552edc4d05380c88de5b334479ad8e537ef2b4925caryclark 9652edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Draw a rectangle with red paint 9752edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkRect rect = { 9852edc4d05380c88de5b334479ad8e537ef2b4925caryclark 10, 10, 9952edc4d05380c88de5b334479ad8e537ef2b4925caryclark 128, 128 10052edc4d05380c88de5b334479ad8e537ef2b4925caryclark }; 10152edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->drawRect(rect, paint); 10252edc4d05380c88de5b334479ad8e537ef2b4925caryclark 10352edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Set up a linear gradient and draw a circle 10452edc4d05380c88de5b334479ad8e537ef2b4925caryclark { 10552edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkPoint linearPoints[] = { 10652edc4d05380c88de5b334479ad8e537ef2b4925caryclark {0, 0}, 10752edc4d05380c88de5b334479ad8e537ef2b4925caryclark {300, 300} 10852edc4d05380c88de5b334479ad8e537ef2b4925caryclark }; 10952edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK}; 11052edc4d05380c88de5b334479ad8e537ef2b4925caryclark 11152edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkShader* shader = SkGradientShader::CreateLinear( 11252edc4d05380c88de5b334479ad8e537ef2b4925caryclark linearPoints, linearColors, NULL, 2, 11352edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkShader::kMirror_TileMode); 11452edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkAutoUnref shader_deleter(shader); 11552edc4d05380c88de5b334479ad8e537ef2b4925caryclark 11652edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setShader(shader); 11752edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setFlags(SkPaint::kAntiAlias_Flag); 11852edc4d05380c88de5b334479ad8e537ef2b4925caryclark 11952edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->drawCircle(200, 200, 64, paint); 12052edc4d05380c88de5b334479ad8e537ef2b4925caryclark 12152edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Detach shader 12252edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setShader(NULL); 12352edc4d05380c88de5b334479ad8e537ef2b4925caryclark } 12452edc4d05380c88de5b334479ad8e537ef2b4925caryclark 12552edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Draw a message with a nice black paint. 12652edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setFlags( 12752edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkPaint::kAntiAlias_Flag | 12852edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkPaint::kSubpixelText_Flag | // ... avoid waggly text when rotating. 12952edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkPaint::kUnderlineText_Flag); 13052edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setColor(SK_ColorBLACK); 13152edc4d05380c88de5b334479ad8e537ef2b4925caryclark paint.setTextSize(20); 13252edc4d05380c88de5b334479ad8e537ef2b4925caryclark 13352edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->save(); 13452edc4d05380c88de5b334479ad8e537ef2b4925caryclark 13552edc4d05380c88de5b334479ad8e537ef2b4925caryclark static const char message[] = "Hello World"; 13652edc4d05380c88de5b334479ad8e537ef2b4925caryclark 13752edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Translate and rotate 13852edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->translate(300, 300); 13952edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRotationAngle += 0.2f; 14052edc4d05380c88de5b334479ad8e537ef2b4925caryclark if (fRotationAngle > 360) { 14152edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRotationAngle -= 360; 14252edc4d05380c88de5b334479ad8e537ef2b4925caryclark } 14352edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->rotate(fRotationAngle); 14452edc4d05380c88de5b334479ad8e537ef2b4925caryclark 14552edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Draw the text: 14652edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->drawText(message, strlen(message), 0, 0, paint); 14752edc4d05380c88de5b334479ad8e537ef2b4925caryclark 14852edc4d05380c88de5b334479ad8e537ef2b4925caryclark canvas->restore(); 14952edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 15052edc4d05380c88de5b334479ad8e537ef2b4925caryclark 15152edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::draw(SkCanvas* canvas) { 15252edc4d05380c88de5b334479ad8e537ef2b4925caryclark drawContents(canvas); 15352edc4d05380c88de5b334479ad8e537ef2b4925caryclark // in case we have queued drawing calls 15452edc4d05380c88de5b334479ad8e537ef2b4925caryclark fContext->flush(); 15552edc4d05380c88de5b334479ad8e537ef2b4925caryclark // Invalidate the window to force a redraw. Poor man's animation mechanism. 15652edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->inval(NULL); 15752edc4d05380c88de5b334479ad8e537ef2b4925caryclark 15852edc4d05380c88de5b334479ad8e537ef2b4925caryclark if (kRaster_DeviceType == fType) { 15952edc4d05380c88de5b334479ad8e537ef2b4925caryclark // need to send the raster bits to the (gpu) window 16052edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkImage* snap = fSurface->newImageSnapshot(); 16152edc4d05380c88de5b334479ad8e537ef2b4925caryclark size_t rowBytes; 16252edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkImageInfo info; 16352edc4d05380c88de5b334479ad8e537ef2b4925caryclark const void* pixels = snap->peekPixels(&info, &rowBytes); 16452edc4d05380c88de5b334479ad8e537ef2b4925caryclark fRenderTarget->writePixels(0, 0, snap->width(), snap->height(), 16552edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkImageInfo2GrPixelConfig(info.colorType(), 16652edc4d05380c88de5b334479ad8e537ef2b4925caryclark info.alphaType(), 16752edc4d05380c88de5b334479ad8e537ef2b4925caryclark info.profileType()), 16852edc4d05380c88de5b334479ad8e537ef2b4925caryclark pixels, 16952edc4d05380c88de5b334479ad8e537ef2b4925caryclark rowBytes, 17052edc4d05380c88de5b334479ad8e537ef2b4925caryclark GrContext::kFlushWrites_PixelOp); 17152edc4d05380c88de5b334479ad8e537ef2b4925caryclark SkSafeUnref(snap); 17252edc4d05380c88de5b334479ad8e537ef2b4925caryclark } 17352edc4d05380c88de5b334479ad8e537ef2b4925caryclark INHERITED::present(); 17452edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 17552edc4d05380c88de5b334479ad8e537ef2b4925caryclark 17652edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::onSizeChange() { 17752edc4d05380c88de5b334479ad8e537ef2b4925caryclark setUpRenderTarget(); 17852edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 17952edc4d05380c88de5b334479ad8e537ef2b4925caryclark 18052edc4d05380c88de5b334479ad8e537ef2b4925caryclarkbool HelloWorldWindow::onHandleChar(SkUnichar unichar) { 18152edc4d05380c88de5b334479ad8e537ef2b4925caryclark if (' ' == unichar) { 18252edc4d05380c88de5b334479ad8e537ef2b4925caryclark fType = fType == kRaster_DeviceType ? kGPU_DeviceType: kRaster_DeviceType; 18352edc4d05380c88de5b334479ad8e537ef2b4925caryclark tearDownBackend(); 18452edc4d05380c88de5b334479ad8e537ef2b4925caryclark setUpBackend(); 18552edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->setTitle(); 18652edc4d05380c88de5b334479ad8e537ef2b4925caryclark this->inval(NULL); 18752edc4d05380c88de5b334479ad8e537ef2b4925caryclark } 18852edc4d05380c88de5b334479ad8e537ef2b4925caryclark return true; 18952edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 19052edc4d05380c88de5b334479ad8e537ef2b4925caryclark 19152edc4d05380c88de5b334479ad8e537ef2b4925caryclarkSkOSWindow* create_sk_window(void* hwnd, int , char** ) { 19252edc4d05380c88de5b334479ad8e537ef2b4925caryclark return new HelloWorldWindow(hwnd); 19352edc4d05380c88de5b334479ad8e537ef2b4925caryclark} 194