Home | History | Annotate | Download | only in SkiaExamples
      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 
     29 void application_init() {
     30     SkGraphics::Init();
     31     SkEvent::Init();
     32 }
     33 
     34 void application_term() {
     35     SkEvent::Term();
     36     SkGraphics::Term();
     37 }
     38 
     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 
     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 
     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 
     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 
    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 
    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 
    145 void SkExampleWindow::onSizeChange() {
    146     setupRenderTarget();
    147 }
    148 
    149 #ifdef SK_BUILD_FOR_WIN
    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 
    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 
    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 
    191 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
    192     SkCommandLineFlags::Parse(argc, argv);
    193     return new SkExampleWindow(hwnd);
    194 }
    195