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 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 // 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 53void 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 68bool 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 94void 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 112SkCanvas* 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 124void 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 145void SkExampleWindow::onSizeChange() { 146 setupRenderTarget(); 147} 148 149#ifdef SK_BUILD_FOR_WIN 150void 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 160bool 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 181bool 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 191SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { 192 SkCommandLineFlags::Parse(argc, argv); 193 return new SkExampleWindow(hwnd); 194} 195