| /* |
| * Copyright 2013 Google Inc. |
| * |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| * |
| */ |
| |
| #include "SkExample.h" |
| |
| #include "gl/GrGLUtil.h" |
| #include "gl/GrGLDefines.h" |
| #include "gl/GrGLInterface.h" |
| #include "SkApplication.h" |
| #include "SkCommandLineFlags.h" |
| #include "SkGpuDevice.h" |
| #include "SkGraphics.h" |
| |
| DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \ |
| "Multiple matches may be separated by spaces.\n" \ |
| "~ causes a matching test to always be skipped\n" \ |
| "^ requires the start of the test to match\n" \ |
| "$ requires the end of the test to match\n" \ |
| "^ and $ requires an exact match\n" \ |
| "If a test does not match any list entry,\n" \ |
| "it is skipped unless some list entry starts with ~"); |
| |
| void application_init() { |
| SkGraphics::Init(); |
| SkEvent::Init(); |
| } |
| |
| void application_term() { |
| SkEvent::Term(); |
| SkGraphics::Term(); |
| } |
| |
| SkExampleWindow::SkExampleWindow(void* hwnd) |
| : INHERITED(hwnd) { |
| fRegistry = SkExample::Registry::Head(); |
| fCurrExample = fRegistry->factory()(this); |
| |
| if (FLAGS_match.count()) { |
| // Start with the a matching sample if possible. |
| bool found = this->findNextMatch(); |
| if (!found) { |
| SkDebugf("No matching SkExample found.\n"); |
| } |
| } |
| } |
| |
| void SkExampleWindow::tearDownBackend() { |
| if (kGPU_DeviceType == fType) { |
| SkSafeUnref(fContext); |
| fContext = NULL; |
| |
| SkSafeUnref(fInterface); |
| fInterface = NULL; |
| |
| SkSafeUnref(fRenderTarget); |
| fRenderTarget = NULL; |
| |
| detach(); |
| } |
| } |
| |
| bool SkExampleWindow::setupBackend(DeviceType type) { |
| fType = type; |
| |
| this->setConfig(SkBitmap::kARGB_8888_Config); |
| this->setVisibleP(true); |
| this->setClipToBounds(false); |
| |
| bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo); |
| if (false == result) { |
| SkDebugf("Not possible to create backend.\n"); |
| detach(); |
| return false; |
| } |
| |
| fInterface = GrGLCreateNativeInterface(); |
| |
| SkASSERT(NULL != fInterface); |
| |
| fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface); |
| SkASSERT(NULL != fContext); |
| |
| setupRenderTarget(); |
| |
| return true; |
| } |
| |
| void SkExampleWindow::setupRenderTarget() { |
| GrBackendRenderTargetDesc desc; |
| desc.fWidth = SkScalarRoundToInt(width()); |
| desc.fHeight = SkScalarRoundToInt(height()); |
| desc.fConfig = kSkia8888_GrPixelConfig; |
| desc.fOrigin = kBottomLeft_GrSurfaceOrigin; |
| desc.fSampleCnt = fAttachmentInfo.fSampleCount; |
| desc.fStencilBits = fAttachmentInfo.fStencilBits; |
| |
| GrGLint buffer; |
| GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer); |
| desc.fRenderTargetHandle = buffer; |
| |
| fRenderTarget = fContext->wrapBackendRenderTarget(desc); |
| |
| fContext->setRenderTarget(fRenderTarget); |
| } |
| |
| SkCanvas* SkExampleWindow::createCanvas() { |
| if (fType == kGPU_DeviceType) { |
| if (NULL != fContext && NULL != fRenderTarget) { |
| SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(fContext, fRenderTarget)); |
| return new SkCanvas(device); |
| } |
| tearDownBackend(); |
| setupBackend(kRaster_DeviceType); |
| } |
| return INHERITED::createCanvas(); |
| } |
| |
| void SkExampleWindow::draw(SkCanvas* canvas) { |
| if (NULL != fCurrExample) { |
| fCurrExample->draw(canvas); |
| } |
| if (fType == kGPU_DeviceType) { |
| |
| SkASSERT(NULL != fContext); |
| fContext->flush(); |
| } |
| if (fType == kRaster_DeviceType) { |
| // need to send the raster bits to the (gpu) window |
| fContext->setRenderTarget(fRenderTarget); |
| const SkBitmap& bm = getBitmap(); |
| fRenderTarget->writePixels(0, 0, bm.width(), bm.height(), |
| kSkia8888_GrPixelConfig, |
| bm.getPixels(), |
| bm.rowBytes()); |
| } |
| INHERITED::present(); |
| } |
| |
| void SkExampleWindow::onSizeChange() { |
| setupRenderTarget(); |
| } |
| |
| #ifdef SK_BUILD_FOR_WIN |
| void SkExampleWindow::onHandleInval(const SkIRect& rect) { |
| RECT winRect; |
| winRect.top = rect.top(); |
| winRect.bottom = rect.bottom(); |
| winRect.right = rect.right(); |
| winRect.left = rect.left(); |
| InvalidateRect((HWND)this->getHWND(), &winRect, false); |
| } |
| #endif |
| |
| bool SkExampleWindow::findNextMatch() { |
| bool found = false; |
| // Avoid infinite loop by knowing where we started. |
| const SkExample::Registry* begin = fRegistry; |
| while (!found) { |
| fRegistry = fRegistry->next(); |
| if (NULL == fRegistry) { // Reached the end of the registered samples. GOTO head. |
| fRegistry = SkExample::Registry::Head(); |
| } |
| SkExample* next = fRegistry->factory()(this); |
| if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, next->getName().c_str())) { |
| fCurrExample = next; |
| found = true; |
| } |
| if (begin == fRegistry) { // We looped through every sample without finding anything. |
| break; |
| } |
| } |
| return found; |
| } |
| |
| bool SkExampleWindow::onHandleChar(SkUnichar unichar) { |
| if ('n' == unichar) { |
| bool found = findNextMatch(); |
| if (!found) { |
| SkDebugf("No SkExample that matches your query\n"); |
| } |
| } |
| return true; |
| } |
| |
| SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) { |
| SkCommandLineFlags::Parse(argc, argv); |
| return new SkExampleWindow(hwnd); |
| } |