skia2/experimental/SkiaExamples/SkExample.cpp
sglez@google.com 43f2b2c833 SkiaExamples improvements.
Make it possible for a client to write a Hello World in less than 50 lines.

R=caryclark@google.com

Review URL: https://codereview.chromium.org/18574002

git-svn-id: http://skia.googlecode.com/svn/trunk@10319 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-07-24 17:48:03 +00:00

198 lines
5.6 KiB
C++

/*
* 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()) {
for(int i = 0; i < FLAGS_match.count(); ++i) {
fMatchStrs.push(FLAGS_match[i]);
}
// 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 = SkScalarRound(width());
desc.fHeight = SkScalarRound(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<SkDevice> 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(fMatchStrs, 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);
}