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"
13f276ac5c16d39a2b877300d760041f0291bb5ec9bsalomon#include "GrContext.h"
1452edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkApplication.h"
1552edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkCanvas.h"
1652edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkGradientShader.h"
1752edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkGraphics.h"
1852edc4d05380c88de5b334479ad8e537ef2b4925caryclark#include "SkGr.h"
1952edc4d05380c88de5b334479ad8e537ef2b4925caryclark
2052edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid application_init() {
2152edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkGraphics::Init();
2252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkEvent::Init();
2352edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
2452edc4d05380c88de5b334479ad8e537ef2b4925caryclark
2552edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid application_term() {
2652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkEvent::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->setVisibleP(true);
6352edc4d05380c88de5b334479ad8e537ef2b4925caryclark    this->setClipToBounds(false);
6452edc4d05380c88de5b334479ad8e537ef2b4925caryclark
6552edc4d05380c88de5b334479ad8e537ef2b4925caryclark    bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
6652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    if (false == result) {
6752edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkDebugf("Not possible to create backend.\n");
6852edc4d05380c88de5b334479ad8e537ef2b4925caryclark        detach();
6952edc4d05380c88de5b334479ad8e537ef2b4925caryclark        return false;
7052edc4d05380c88de5b334479ad8e537ef2b4925caryclark    }
7152edc4d05380c88de5b334479ad8e537ef2b4925caryclark
7252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    fInterface = GrGLCreateNativeInterface();
7352edc4d05380c88de5b334479ad8e537ef2b4925caryclark
7452edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkASSERT(NULL != fInterface);
7552edc4d05380c88de5b334479ad8e537ef2b4925caryclark
7652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
7752edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkASSERT(NULL != fContext);
7852edc4d05380c88de5b334479ad8e537ef2b4925caryclark
7952edc4d05380c88de5b334479ad8e537ef2b4925caryclark    this->setUpRenderTarget();
8052edc4d05380c88de5b334479ad8e537ef2b4925caryclark    return true;
8152edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
8252edc4d05380c88de5b334479ad8e537ef2b4925caryclark
8352edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::setUpRenderTarget() {
8452edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkSafeUnref(fRenderTarget);
8552edc4d05380c88de5b334479ad8e537ef2b4925caryclark    fRenderTarget = this->renderTarget(fAttachmentInfo, fInterface, fContext);
8652edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
8752edc4d05380c88de5b334479ad8e537ef2b4925caryclark
8852edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::drawContents(SkCanvas* canvas) {
8952edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Clear background
9052edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->drawColor(SK_ColorWHITE);
9152edc4d05380c88de5b334479ad8e537ef2b4925caryclark
9252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkPaint paint;
9352edc4d05380c88de5b334479ad8e537ef2b4925caryclark    paint.setColor(SK_ColorRED);
9452edc4d05380c88de5b334479ad8e537ef2b4925caryclark
9552edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Draw a rectangle with red paint
9652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    SkRect rect = {
9752edc4d05380c88de5b334479ad8e537ef2b4925caryclark            10, 10,
9852edc4d05380c88de5b334479ad8e537ef2b4925caryclark            128, 128
9952edc4d05380c88de5b334479ad8e537ef2b4925caryclark    };
10052edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->drawRect(rect, paint);
10152edc4d05380c88de5b334479ad8e537ef2b4925caryclark
10252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Set up a linear gradient and draw a circle
10352edc4d05380c88de5b334479ad8e537ef2b4925caryclark    {
10452edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkPoint linearPoints[] = {
10552edc4d05380c88de5b334479ad8e537ef2b4925caryclark                {0, 0},
10652edc4d05380c88de5b334479ad8e537ef2b4925caryclark                {300, 300}
10752edc4d05380c88de5b334479ad8e537ef2b4925caryclark        };
10852edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
10952edc4d05380c88de5b334479ad8e537ef2b4925caryclark
11052edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkShader* shader = SkGradientShader::CreateLinear(
11152edc4d05380c88de5b334479ad8e537ef2b4925caryclark                linearPoints, linearColors, NULL, 2,
11252edc4d05380c88de5b334479ad8e537ef2b4925caryclark                SkShader::kMirror_TileMode);
11352edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkAutoUnref shader_deleter(shader);
11452edc4d05380c88de5b334479ad8e537ef2b4925caryclark
11552edc4d05380c88de5b334479ad8e537ef2b4925caryclark        paint.setShader(shader);
11652edc4d05380c88de5b334479ad8e537ef2b4925caryclark        paint.setFlags(SkPaint::kAntiAlias_Flag);
11752edc4d05380c88de5b334479ad8e537ef2b4925caryclark
11852edc4d05380c88de5b334479ad8e537ef2b4925caryclark        canvas->drawCircle(200, 200, 64, paint);
11952edc4d05380c88de5b334479ad8e537ef2b4925caryclark
12052edc4d05380c88de5b334479ad8e537ef2b4925caryclark        // Detach shader
12152edc4d05380c88de5b334479ad8e537ef2b4925caryclark        paint.setShader(NULL);
12252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    }
12352edc4d05380c88de5b334479ad8e537ef2b4925caryclark
12452edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Draw a message with a nice black paint.
12552edc4d05380c88de5b334479ad8e537ef2b4925caryclark    paint.setFlags(
12652edc4d05380c88de5b334479ad8e537ef2b4925caryclark            SkPaint::kAntiAlias_Flag |
12752edc4d05380c88de5b334479ad8e537ef2b4925caryclark            SkPaint::kSubpixelText_Flag |  // ... avoid waggly text when rotating.
12852edc4d05380c88de5b334479ad8e537ef2b4925caryclark            SkPaint::kUnderlineText_Flag);
12952edc4d05380c88de5b334479ad8e537ef2b4925caryclark    paint.setColor(SK_ColorBLACK);
13052edc4d05380c88de5b334479ad8e537ef2b4925caryclark    paint.setTextSize(20);
13152edc4d05380c88de5b334479ad8e537ef2b4925caryclark
13252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->save();
13352edc4d05380c88de5b334479ad8e537ef2b4925caryclark
13452edc4d05380c88de5b334479ad8e537ef2b4925caryclark    static const char message[] = "Hello World";
13552edc4d05380c88de5b334479ad8e537ef2b4925caryclark
13652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Translate and rotate
13752edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->translate(300, 300);
13852edc4d05380c88de5b334479ad8e537ef2b4925caryclark    fRotationAngle += 0.2f;
13952edc4d05380c88de5b334479ad8e537ef2b4925caryclark    if (fRotationAngle > 360) {
14052edc4d05380c88de5b334479ad8e537ef2b4925caryclark        fRotationAngle -= 360;
14152edc4d05380c88de5b334479ad8e537ef2b4925caryclark    }
14252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->rotate(fRotationAngle);
14352edc4d05380c88de5b334479ad8e537ef2b4925caryclark
14452edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Draw the text:
14552edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->drawText(message, strlen(message), 0, 0, paint);
14652edc4d05380c88de5b334479ad8e537ef2b4925caryclark
14752edc4d05380c88de5b334479ad8e537ef2b4925caryclark    canvas->restore();
14852edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
14952edc4d05380c88de5b334479ad8e537ef2b4925caryclark
15052edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::draw(SkCanvas* canvas) {
15152edc4d05380c88de5b334479ad8e537ef2b4925caryclark    drawContents(canvas);
15252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // in case we have queued drawing calls
15352edc4d05380c88de5b334479ad8e537ef2b4925caryclark    fContext->flush();
15452edc4d05380c88de5b334479ad8e537ef2b4925caryclark    // Invalidate the window to force a redraw. Poor man's animation mechanism.
15552edc4d05380c88de5b334479ad8e537ef2b4925caryclark    this->inval(NULL);
15652edc4d05380c88de5b334479ad8e537ef2b4925caryclark
15752edc4d05380c88de5b334479ad8e537ef2b4925caryclark    if (kRaster_DeviceType == fType) {
15852edc4d05380c88de5b334479ad8e537ef2b4925caryclark        // need to send the raster bits to the (gpu) window
15952edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkImage* snap = fSurface->newImageSnapshot();
160ed828001da75f4a3a5d31d9f1c1935e3595ce920cblume        size_t rowBytes = 0;
16152edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkImageInfo info;
16252edc4d05380c88de5b334479ad8e537ef2b4925caryclark        const void* pixels = snap->peekPixels(&info, &rowBytes);
16352edc4d05380c88de5b334479ad8e537ef2b4925caryclark        fRenderTarget->writePixels(0, 0, snap->width(), snap->height(),
16452edc4d05380c88de5b334479ad8e537ef2b4925caryclark                                        SkImageInfo2GrPixelConfig(info.colorType(),
16552edc4d05380c88de5b334479ad8e537ef2b4925caryclark                                                                info.alphaType(),
16652edc4d05380c88de5b334479ad8e537ef2b4925caryclark                                                                info.profileType()),
16752edc4d05380c88de5b334479ad8e537ef2b4925caryclark                                        pixels,
16852edc4d05380c88de5b334479ad8e537ef2b4925caryclark                                        rowBytes,
16952edc4d05380c88de5b334479ad8e537ef2b4925caryclark                                        GrContext::kFlushWrites_PixelOp);
17052edc4d05380c88de5b334479ad8e537ef2b4925caryclark        SkSafeUnref(snap);
17152edc4d05380c88de5b334479ad8e537ef2b4925caryclark    }
17252edc4d05380c88de5b334479ad8e537ef2b4925caryclark    INHERITED::present();
17352edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
17452edc4d05380c88de5b334479ad8e537ef2b4925caryclark
17552edc4d05380c88de5b334479ad8e537ef2b4925caryclarkvoid HelloWorldWindow::onSizeChange() {
17652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    setUpRenderTarget();
17752edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
17852edc4d05380c88de5b334479ad8e537ef2b4925caryclark
17952edc4d05380c88de5b334479ad8e537ef2b4925caryclarkbool HelloWorldWindow::onHandleChar(SkUnichar unichar) {
18052edc4d05380c88de5b334479ad8e537ef2b4925caryclark    if (' ' == unichar) {
18152edc4d05380c88de5b334479ad8e537ef2b4925caryclark        fType = fType == kRaster_DeviceType ? kGPU_DeviceType: kRaster_DeviceType;
18252edc4d05380c88de5b334479ad8e537ef2b4925caryclark        tearDownBackend();
18352edc4d05380c88de5b334479ad8e537ef2b4925caryclark        setUpBackend();
18452edc4d05380c88de5b334479ad8e537ef2b4925caryclark        this->setTitle();
18552edc4d05380c88de5b334479ad8e537ef2b4925caryclark        this->inval(NULL);
18652edc4d05380c88de5b334479ad8e537ef2b4925caryclark    }
18752edc4d05380c88de5b334479ad8e537ef2b4925caryclark    return true;
18852edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
18952edc4d05380c88de5b334479ad8e537ef2b4925caryclark
19052edc4d05380c88de5b334479ad8e537ef2b4925caryclarkSkOSWindow* create_sk_window(void* hwnd, int , char** ) {
19152edc4d05380c88de5b334479ad8e537ef2b4925caryclark    return new HelloWorldWindow(hwnd);
19252edc4d05380c88de5b334479ad8e537ef2b4925caryclark}
193