blob: 387276ad1bc5862601cc8bbb89fbd1afe4c088e4 [file] [log] [blame]
sglez@google.com43f2b2c2013-07-24 17:48:03 +00001/*
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
10#include "SkExample.h"
11
12#include "gl/GrGLUtil.h"
13#include "gl/GrGLDefines.h"
14#include "gl/GrGLInterface.h"
15#include "SkApplication.h"
16#include "SkCommandLineFlags.h"
17#include "SkGpuDevice.h"
18#include "SkGraphics.h"
19
20DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \
21 "Multiple matches may be separated by spaces.\n" \
22 "~ causes a matching test to always be skipped\n" \
23 "^ requires the start of the test to match\n" \
24 "$ requires the end of the test to match\n" \
25 "^ and $ requires an exact match\n" \
26 "If a test does not match any list entry,\n" \
27 "it is skipped unless some list entry starts with ~");
28
29void application_init() {
30 SkGraphics::Init();
31 SkEvent::Init();
32}
33
34void application_term() {
35 SkEvent::Term();
36 SkGraphics::Term();
37}
38
39SkExampleWindow::SkExampleWindow(void* hwnd)
40 : INHERITED(hwnd) {
41 fRegistry = SkExample::Registry::Head();
42 fCurrExample = fRegistry->factory()(this);
43
44 if (FLAGS_match.count()) {
45 for(int i = 0; i < FLAGS_match.count(); ++i) {
46 fMatchStrs.push(FLAGS_match[i]);
47 }
48 // Start with the a matching sample if possible.
49 bool found = this->findNextMatch();
50 if (!found) {
51 SkDebugf("No matching SkExample found.\n");
52 }
53 }
54}
55
56void SkExampleWindow::tearDownBackend() {
57 if (kGPU_DeviceType == fType) {
58 SkSafeUnref(fContext);
59 fContext = NULL;
60
61 SkSafeUnref(fInterface);
62 fInterface = NULL;
63
64 SkSafeUnref(fRenderTarget);
65 fRenderTarget = NULL;
66
67 detach();
68 }
69}
70
71bool SkExampleWindow::setupBackend(DeviceType type) {
72 fType = type;
73
74 this->setConfig(SkBitmap::kARGB_8888_Config);
75 this->setVisibleP(true);
76 this->setClipToBounds(false);
77
78 bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
79 if (false == result) {
80 SkDebugf("Not possible to create backend.\n");
81 detach();
82 return false;
83 }
84
85 fInterface = GrGLCreateNativeInterface();
86
87 SkASSERT(NULL != fInterface);
88
89 fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
90 SkASSERT(NULL != fContext);
91
92 setupRenderTarget();
93
94 return true;
95}
96
97void SkExampleWindow::setupRenderTarget() {
98 GrBackendRenderTargetDesc desc;
99 desc.fWidth = SkScalarRound(width());
100 desc.fHeight = SkScalarRound(height());
101 desc.fConfig = kSkia8888_GrPixelConfig;
102 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
103 desc.fSampleCnt = fAttachmentInfo.fSampleCount;
104 desc.fStencilBits = fAttachmentInfo.fStencilBits;
105
106 GrGLint buffer;
107 GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
108 desc.fRenderTargetHandle = buffer;
109
110 fRenderTarget = fContext->wrapBackendRenderTarget(desc);
111
112 fContext->setRenderTarget(fRenderTarget);
113}
114
115SkCanvas* SkExampleWindow::createCanvas() {
116 if (fType == kGPU_DeviceType) {
117 if (NULL != fContext && NULL != fRenderTarget) {
robertphillips@google.com9b051a32013-08-20 20:06:40 +0000118 SkAutoTUnref<SkDevice> device(new SkGpuDevice(fContext, fRenderTarget));
sglez@google.com43f2b2c2013-07-24 17:48:03 +0000119 return new SkCanvas(device);
120 }
121 tearDownBackend();
122 setupBackend(kRaster_DeviceType);
123 }
124 return INHERITED::createCanvas();
125}
126
127void SkExampleWindow::draw(SkCanvas* canvas) {
128 if (NULL != fCurrExample) {
129 fCurrExample->draw(canvas);
130 }
131 if (fType == kGPU_DeviceType) {
132
133 SkASSERT(NULL != fContext);
134 fContext->flush();
135 }
136 if (fType == kRaster_DeviceType) {
137 // need to send the raster bits to the (gpu) window
138 fContext->setRenderTarget(fRenderTarget);
139 const SkBitmap& bm = getBitmap();
140 fRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
141 kSkia8888_GrPixelConfig,
142 bm.getPixels(),
143 bm.rowBytes());
144 }
145 INHERITED::present();
146}
147
148void SkExampleWindow::onSizeChange() {
149 setupRenderTarget();
150}
151
152#ifdef SK_BUILD_FOR_WIN
153void SkExampleWindow::onHandleInval(const SkIRect& rect) {
154 RECT winRect;
155 winRect.top = rect.top();
156 winRect.bottom = rect.bottom();
157 winRect.right = rect.right();
158 winRect.left = rect.left();
159 InvalidateRect((HWND)this->getHWND(), &winRect, false);
160}
161#endif
162
163bool SkExampleWindow::findNextMatch() {
164 bool found = false;
165 // Avoid infinite loop by knowing where we started.
166 const SkExample::Registry* begin = fRegistry;
167 while (!found) {
168 fRegistry = fRegistry->next();
169 if (NULL == fRegistry) { // Reached the end of the registered samples. GOTO head.
170 fRegistry = SkExample::Registry::Head();
171 }
172 SkExample* next = fRegistry->factory()(this);
173 if (!SkCommandLineFlags::ShouldSkip(fMatchStrs, next->getName().c_str())) {
174 fCurrExample = next;
175 found = true;
176 }
177 if (begin == fRegistry) { // We looped through every sample without finding anything.
178 break;
179 }
180 }
181 return found;
182}
183
184bool SkExampleWindow::onHandleChar(SkUnichar unichar) {
185 if ('n' == unichar) {
186 bool found = findNextMatch();
187 if (!found) {
188 SkDebugf("No SkExample that matches your query\n");
189 }
190 }
191 return true;
192}
193
194SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
195 SkCommandLineFlags::Parse(argc, argv);
196 return new SkExampleWindow(hwnd);
197}