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