1 /*
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
20 DEFINE_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
application_init()29 void application_init() {
30 SkGraphics::Init();
31 SkEvent::Init();
32 }
33
application_term()34 void application_term() {
35 SkEvent::Term();
36 SkGraphics::Term();
37 }
38
SkExampleWindow(void * hwnd)39 SkExampleWindow::SkExampleWindow(void* hwnd)
40 : INHERITED(hwnd) {
41 fRegistry = SkExample::Registry::Head();
42 fCurrExample = fRegistry->factory()(this);
43
44 if (FLAGS_match.count()) {
45 // Start with the a matching sample if possible.
46 bool found = this->findNextMatch();
47 if (!found) {
48 SkDebugf("No matching SkExample found.\n");
49 }
50 }
51 }
52
tearDownBackend()53 void SkExampleWindow::tearDownBackend() {
54 if (kGPU_DeviceType == fType) {
55 SkSafeUnref(fContext);
56 fContext = NULL;
57
58 SkSafeUnref(fInterface);
59 fInterface = NULL;
60
61 SkSafeUnref(fRenderTarget);
62 fRenderTarget = NULL;
63
64 detach();
65 }
66 }
67
setupBackend(DeviceType type)68 bool SkExampleWindow::setupBackend(DeviceType type) {
69 fType = type;
70
71 this->setColorType(kRGBA_8888_SkColorType);
72 this->setVisibleP(true);
73 this->setClipToBounds(false);
74
75 bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
76 if (false == result) {
77 SkDebugf("Not possible to create backend.\n");
78 detach();
79 return false;
80 }
81
82 fInterface = GrGLCreateNativeInterface();
83
84 SkASSERT(NULL != fInterface);
85
86 fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
87 SkASSERT(NULL != fContext);
88
89 setupRenderTarget();
90
91 return true;
92 }
93
setupRenderTarget()94 void SkExampleWindow::setupRenderTarget() {
95 GrBackendRenderTargetDesc desc;
96 desc.fWidth = SkScalarRoundToInt(width());
97 desc.fHeight = SkScalarRoundToInt(height());
98 desc.fConfig = kSkia8888_GrPixelConfig;
99 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
100 desc.fSampleCnt = fAttachmentInfo.fSampleCount;
101 desc.fStencilBits = fAttachmentInfo.fStencilBits;
102
103 GrGLint buffer;
104 GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
105 desc.fRenderTargetHandle = buffer;
106
107 fRenderTarget = fContext->wrapBackendRenderTarget(desc);
108
109 fContext->setRenderTarget(fRenderTarget);
110 }
111
createCanvas()112 SkCanvas* SkExampleWindow::createCanvas() {
113 if (fType == kGPU_DeviceType) {
114 if (NULL != fContext && NULL != fRenderTarget) {
115 SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(fContext, fRenderTarget));
116 return new SkCanvas(device);
117 }
118 tearDownBackend();
119 setupBackend(kRaster_DeviceType);
120 }
121 return INHERITED::createCanvas();
122 }
123
draw(SkCanvas * canvas)124 void SkExampleWindow::draw(SkCanvas* canvas) {
125 if (NULL != fCurrExample) {
126 fCurrExample->draw(canvas);
127 }
128 if (fType == kGPU_DeviceType) {
129
130 SkASSERT(NULL != fContext);
131 fContext->flush();
132 }
133 if (fType == kRaster_DeviceType) {
134 // need to send the raster bits to the (gpu) window
135 fContext->setRenderTarget(fRenderTarget);
136 const SkBitmap& bm = getBitmap();
137 fRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
138 kSkia8888_GrPixelConfig,
139 bm.getPixels(),
140 bm.rowBytes());
141 }
142 INHERITED::present();
143 }
144
onSizeChange()145 void SkExampleWindow::onSizeChange() {
146 setupRenderTarget();
147 }
148
149 #ifdef SK_BUILD_FOR_WIN
onHandleInval(const SkIRect & rect)150 void SkExampleWindow::onHandleInval(const SkIRect& rect) {
151 RECT winRect;
152 winRect.top = rect.top();
153 winRect.bottom = rect.bottom();
154 winRect.right = rect.right();
155 winRect.left = rect.left();
156 InvalidateRect((HWND)this->getHWND(), &winRect, false);
157 }
158 #endif
159
findNextMatch()160 bool SkExampleWindow::findNextMatch() {
161 bool found = false;
162 // Avoid infinite loop by knowing where we started.
163 const SkExample::Registry* begin = fRegistry;
164 while (!found) {
165 fRegistry = fRegistry->next();
166 if (NULL == fRegistry) { // Reached the end of the registered samples. GOTO head.
167 fRegistry = SkExample::Registry::Head();
168 }
169 SkExample* next = fRegistry->factory()(this);
170 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, next->getName().c_str())) {
171 fCurrExample = next;
172 found = true;
173 }
174 if (begin == fRegistry) { // We looped through every sample without finding anything.
175 break;
176 }
177 }
178 return found;
179 }
180
onHandleChar(SkUnichar unichar)181 bool SkExampleWindow::onHandleChar(SkUnichar unichar) {
182 if ('n' == unichar) {
183 bool found = findNextMatch();
184 if (!found) {
185 SkDebugf("No SkExample that matches your query\n");
186 }
187 }
188 return true;
189 }
190
create_sk_window(void * hwnd,int argc,char ** argv)191 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
192 SkCommandLineFlags::Parse(argc, argv);
193 return new SkExampleWindow(hwnd);
194 }
195