1 /*
2  * Copyright 2015 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 
10 #include "HelloWorld.h"
11 
12 #include "gl/GrGLInterface.h"
13 #include "SkApplication.h"
14 #include "SkCanvas.h"
15 #include "SkGradientShader.h"
16 #include "SkGraphics.h"
17 #include "SkGr.h"
18 
application_init()19 void application_init() {
20     SkGraphics::Init();
21     SkEvent::Init();
22 }
23 
application_term()24 void application_term() {
25     SkEvent::Term();
26     SkGraphics::Term();
27 }
28 
HelloWorldWindow(void * hwnd)29 HelloWorldWindow::HelloWorldWindow(void* hwnd)
30     : INHERITED(hwnd) {
31     fType = kGPU_DeviceType;
32     fRenderTarget = NULL;
33     fRotationAngle = 0;
34     this->setTitle();
35     this->setUpBackend();
36 }
37 
~HelloWorldWindow()38 HelloWorldWindow::~HelloWorldWindow() {
39     tearDownBackend();
40 }
41 
tearDownBackend()42 void HelloWorldWindow::tearDownBackend() {
43     SkSafeUnref(fContext);
44     fContext = NULL;
45 
46     SkSafeUnref(fInterface);
47     fInterface = NULL;
48 
49     SkSafeUnref(fRenderTarget);
50     fRenderTarget = NULL;
51 
52     INHERITED::detach();
53 }
54 
setTitle()55 void HelloWorldWindow::setTitle() {
56     SkString title("Hello World ");
57     title.appendf(fType == kRaster_DeviceType ? "raster" : "opengl");
58     INHERITED::setTitle(title.c_str());
59 }
60 
setUpBackend()61 bool HelloWorldWindow::setUpBackend() {
62     this->setColorType(kRGBA_8888_SkColorType);
63     this->setVisibleP(true);
64     this->setClipToBounds(false);
65 
66     bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
67     if (false == result) {
68         SkDebugf("Not possible to create backend.\n");
69         detach();
70         return false;
71     }
72 
73     fInterface = GrGLCreateNativeInterface();
74 
75     SkASSERT(NULL != fInterface);
76 
77     fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
78     SkASSERT(NULL != fContext);
79 
80     this->setUpRenderTarget();
81     return true;
82 }
83 
setUpRenderTarget()84 void HelloWorldWindow::setUpRenderTarget() {
85     SkSafeUnref(fRenderTarget);
86     fRenderTarget = this->renderTarget(fAttachmentInfo, fInterface, fContext);
87 }
88 
drawContents(SkCanvas * canvas)89 void HelloWorldWindow::drawContents(SkCanvas* canvas) {
90     // Clear background
91     canvas->drawColor(SK_ColorWHITE);
92 
93     SkPaint paint;
94     paint.setColor(SK_ColorRED);
95 
96     // Draw a rectangle with red paint
97     SkRect rect = {
98             10, 10,
99             128, 128
100     };
101     canvas->drawRect(rect, paint);
102 
103     // Set up a linear gradient and draw a circle
104     {
105         SkPoint linearPoints[] = {
106                 {0, 0},
107                 {300, 300}
108         };
109         SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
110 
111         SkShader* shader = SkGradientShader::CreateLinear(
112                 linearPoints, linearColors, NULL, 2,
113                 SkShader::kMirror_TileMode);
114         SkAutoUnref shader_deleter(shader);
115 
116         paint.setShader(shader);
117         paint.setFlags(SkPaint::kAntiAlias_Flag);
118 
119         canvas->drawCircle(200, 200, 64, paint);
120 
121         // Detach shader
122         paint.setShader(NULL);
123     }
124 
125     // Draw a message with a nice black paint.
126     paint.setFlags(
127             SkPaint::kAntiAlias_Flag |
128             SkPaint::kSubpixelText_Flag |  // ... avoid waggly text when rotating.
129             SkPaint::kUnderlineText_Flag);
130     paint.setColor(SK_ColorBLACK);
131     paint.setTextSize(20);
132 
133     canvas->save();
134 
135     static const char message[] = "Hello World";
136 
137     // Translate and rotate
138     canvas->translate(300, 300);
139     fRotationAngle += 0.2f;
140     if (fRotationAngle > 360) {
141         fRotationAngle -= 360;
142     }
143     canvas->rotate(fRotationAngle);
144 
145     // Draw the text:
146     canvas->drawText(message, strlen(message), 0, 0, paint);
147 
148     canvas->restore();
149 }
150 
draw(SkCanvas * canvas)151 void HelloWorldWindow::draw(SkCanvas* canvas) {
152     drawContents(canvas);
153     // in case we have queued drawing calls
154     fContext->flush();
155     // Invalidate the window to force a redraw. Poor man's animation mechanism.
156     this->inval(NULL);
157 
158     if (kRaster_DeviceType == fType) {
159         // need to send the raster bits to the (gpu) window
160         SkImage* snap = fSurface->newImageSnapshot();
161         size_t rowBytes;
162         SkImageInfo info;
163         const void* pixels = snap->peekPixels(&info, &rowBytes);
164         fRenderTarget->writePixels(0, 0, snap->width(), snap->height(),
165                                         SkImageInfo2GrPixelConfig(info.colorType(),
166                                                                 info.alphaType(),
167                                                                 info.profileType()),
168                                         pixels,
169                                         rowBytes,
170                                         GrContext::kFlushWrites_PixelOp);
171         SkSafeUnref(snap);
172     }
173     INHERITED::present();
174 }
175 
onSizeChange()176 void HelloWorldWindow::onSizeChange() {
177     setUpRenderTarget();
178 }
179 
onHandleChar(SkUnichar unichar)180 bool HelloWorldWindow::onHandleChar(SkUnichar unichar) {
181     if (' ' == unichar) {
182         fType = fType == kRaster_DeviceType ? kGPU_DeviceType: kRaster_DeviceType;
183         tearDownBackend();
184         setUpBackend();
185         this->setTitle();
186         this->inval(NULL);
187     }
188     return true;
189 }
190 
create_sk_window(void * hwnd,int,char **)191 SkOSWindow* create_sk_window(void* hwnd, int , char** ) {
192     return new HelloWorldWindow(hwnd);
193 }
194