Add DeviceManager to SampleWindow
Review URL: http://codereview.appspot.com/4715045/


git-svn-id: http://skia.googlecode.com/svn/trunk@1857 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 258da06..5251604 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -53,6 +53,104 @@
 static SampleWindow* gSampleWindow;
 
 ///////////////
+class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
+public:
+
+    DefaultDeviceManager() {
+        fGrRenderTarget = NULL;
+        fGrContext = NULL;
+    }
+
+    virtual ~DefaultDeviceManager() {
+        SkSafeUnref(fGrRenderTarget);
+        SkSafeUnref(fGrContext);
+    }
+
+    virtual void init(SampleWindow* win) {
+        win->attachGL();
+        if (NULL == fGrContext) {
+            fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
+        }
+        if (NULL == fGrContext) {
+            SkDebugf("Failed to setup 3D");
+            win->detachGL();
+        }
+    }
+
+    virtual bool supportsDeviceType(SampleWindow::DeviceType dType) {
+        switch (dType) {
+            case kRaster_DeviceType:
+            case kPicture_DeviceType: // fallthru
+                return true;
+            case kGPU_DeviceType:
+                return NULL != fGrContext && NULL != fGrRenderTarget;
+            default:
+                return false;
+        }
+    }
+
+    virtual bool prepareCanvas(SampleWindow::DeviceType dType,
+                               SkCanvas* canvas,
+                               SampleWindow* win) {
+        if (kGPU_DeviceType == dType) {
+            if (fGrContext) {
+                canvas->setDevice(new SkGpuDevice(fGrContext,
+                                                fGrRenderTarget))->unref();
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    virtual void publishCanvas(SampleWindow::DeviceType dType,
+                               SkCanvas* canvas,
+                               SampleWindow* win) {
+        if (fGrContext) {
+            // in case we have queued drawing calls
+            fGrContext->flush();
+            if (dType != kGPU_DeviceType) {
+                // need to send the raster bits to the (gpu) window
+                fGrContext->setRenderTarget(fGrRenderTarget);
+                const SkBitmap& bm = win->getBitmap();
+                fGrContext->writePixels(0, 0, bm.width(), bm.height(),
+                                        kRGBA_8888_GrPixelConfig, bm.getPixels(),
+                                        bm.rowBytes());
+            }
+        }
+        win->presentGL();
+    }
+
+    virtual void windowSizeChanged(SampleWindow* win) {
+        if (fGrContext) {
+            win->attachGL();
+
+            GrPlatformSurfaceDesc desc;
+            desc.reset();
+            desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
+            desc.fWidth = SkScalarRound(win->width());
+            desc.fHeight = SkScalarRound(win->height());
+            desc.fConfig = kRGBA_8888_GrPixelConfig;
+            desc.fStencilBits = 8;
+            GrGLint buffer;
+            GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
+            desc.fPlatformRenderTarget = buffer;
+
+            SkSafeUnref(fGrRenderTarget);
+            fGrRenderTarget = static_cast<GrRenderTarget*>(
+                                            fGrContext->createPlatformSurface(desc));
+        }
+    }
+
+    virtual GrContext* getGrContext() {
+        return fGrContext;
+    }
+private:
+    GrContext* fGrContext;
+    GrRenderTarget* fGrRenderTarget;
+};
+
+///////////////
 static const char view_inval_msg[] = "view-inval-msg";
 
 void SampleWindow::postInvalDelay() {
@@ -258,21 +356,6 @@
     fZoomCenterY = SkFloatToScalar(y);
 }
 
-bool SampleWindow::setGrContext(GrContext* context)
-{
-    if (fGrContext) {
-        fGrContext->unref();
-    }
-    fGrContext = context;
-    fGrContext->ref();
-    return true;
-}
-
-GrContext* SampleWindow::getGrContext()
-{
-    return fGrContext;
-}
-
 bool SampleWindow::zoomIn()
 {
     // Arbitrarily decided
@@ -305,54 +388,16 @@
     }
 }
 
-bool SampleWindow::make3DReady() {
-
-#if defined(SK_SUPPORT_GL)
-    if (attachGL()) {
-        if (NULL != fGrContext) {
-        // various gr lifecycle tests
-        #if   0
-            fGrContext->freeGpuResources();
-        #elif 0
-            // this will leak resources.
-            fGrContext->contextLost();
-        #elif 0
-            GrAssert(1 == fGrContext->refcnt());
-            fGrContext->unref();
-            fGrContext = NULL;
-        #endif
-        }
-
-        if (NULL == fGrContext) {
-        #if defined(SK_USE_SHADERS)
-            fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
-        #else
-            fGrContext = GrContext::Create(kOpenGL_Fixed_GrEngine, NULL);
-        #endif
-            SkDebugf("---- constructor\n");
-        }
-
-        if (NULL != fGrContext) {
-            return true;
-        } else {
-            detachGL();
-        }
-    }
-#endif
-    SkDebugf("Failed to setup 3D");
-    return false;
-}
-
-SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
-    static const CanvasType gCT[] = {
-        kPicture_CanvasType,
-        kGPU_CanvasType,
-        kRaster_CanvasType
+static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType ct) {
+    static const SampleWindow::DeviceType gCT[] = {
+        SampleWindow::kPicture_DeviceType,
+        SampleWindow::kGPU_DeviceType,
+        SampleWindow::kRaster_DeviceType
     };
     return gCT[ct];
 }
 
-SampleWindow::SampleWindow(void* hwnd, int argc, char** argv) : INHERITED(hwnd) {
+SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager) : INHERITED(hwnd) {
     gSampleWindow = this;
 
 #ifdef  PIPE_FILE
@@ -362,14 +407,11 @@
 #endif
      
     fPicture = NULL;
-
-    fGrContext = NULL;
-    fGrRenderTarget = NULL;
-
+    
 #ifdef DEFAULT_TO_GPU
-    fCanvasType = kGPU_CanvasType;
+    fDeviceType = kGPU_DeviceType;
 #else
-    fCanvasType = kRaster_CanvasType;
+    fDeviceType = kRaster_DeviceType;
 #endif
     fUseClip = false;
     fNClip = false;
@@ -428,7 +470,14 @@
     
     fPDFData = NULL;
 
-    this->make3DReady();
+    if (NULL == devManager) {
+        fDevManager = new DefaultDeviceManager();
+    } else {
+        devManager->ref();
+        fDevManager = devManager;
+    }
+    fDevManager->init(this);
+
     // If another constructor set our dimensions, ensure that our
     // onSizeChange gets called.
     if (this->height() && this->width()) {
@@ -441,8 +490,7 @@
     delete fPdfCanvas;
     fTypeface->unref();
 
-    SkSafeUnref(fGrRenderTarget);
-    SkSafeUnref(fGrContext);
+    SkSafeUnref(fDevManager);
 }
 
 static SkBitmap capture_bitmap(SkCanvas* canvas) {
@@ -494,11 +542,10 @@
 #define YCLIP_N  8
 
 void SampleWindow::draw(SkCanvas* canvas) {
-    if (fGrContext && (kGPU_CanvasType == fCanvasType)) {
-        canvas->setDevice(new SkGpuDevice(fGrContext,
-                                          fGrRenderTarget))->unref();
-    }
 
+    if (!fDevManager->prepareCanvas(fDeviceType, canvas, this)) {
+        return;
+    }
     // update the animation time
     gAnimTimePrev = gAnimTime;
     gAnimTime = SkTime::GetMSecs();
@@ -581,29 +628,12 @@
     } else {
         this->INHERITED::draw(canvas);
     }
-    if (fShowZoomer && fCanvasType != kGPU_CanvasType && !fSaveToPdf) {
-        // In the GPU case, INHERITED::draw calls beforeChildren, which
-        // creates an SkGpuCanvas.  All further draw calls are directed
-        // at that canvas, which is deleted in afterChildren (which is
-        // also called by draw), so we cannot show the zoomer here.
-        // Instead, we call it inside afterChildren.
+    if (fShowZoomer && !fSaveToPdf) {
         showZoomer(canvas);
     }
 
     // do this last
-    if (fGrContext) {
-        // in case we have queued drawing calls
-        fGrContext->flush();
-        if (fCanvasType != kGPU_CanvasType) {
-            // need to send the raster bits to the (gpu) window
-            fGrContext->setRenderTarget(fGrRenderTarget);
-            const SkBitmap& bm = this->getBitmap();
-            fGrContext->writePixels(0, 0, bm.width(), bm.height(),
-                                    kRGBA_8888_GrPixelConfig, bm.getPixels(),
-                                    bm.rowBytes());
-        }
-    }
-    presentGL();
+    fDevManager->publishCanvas(fDeviceType, canvas, this);
 }
 
 void SampleWindow::showZoomer(SkCanvas* canvas) {
@@ -731,12 +761,12 @@
         pdfDevice->unref();
         canvas = fPdfCanvas;
     } else {
-        switch (fCanvasType) {
-            case kRaster_CanvasType:
-            case kGPU_CanvasType:
+        switch (fDeviceType) {
+            case kRaster_DeviceType:
+            case kGPU_DeviceType:
                 canvas = this->INHERITED::beforeChildren(canvas);
                 break;
-            case kPicture_CanvasType:
+            case kPicture_DeviceType:
                 fPicture = new SkPicture;
                 canvas = fPicture->beginRecording(9999, 9999);
                 break;
@@ -811,37 +841,26 @@
         }
     }
 
-    switch (fCanvasType) {
-        case kRaster_CanvasType:
-            break;
-        case kPicture_CanvasType:
-            if (true) {
-                SkPicture* pict = new SkPicture(*fPicture);
-                fPicture->unref();
-                orig->drawPicture(*pict);
-                pict->unref();
-            } else if (true) {
-                SkDynamicMemoryWStream ostream;
-                fPicture->serialize(&ostream);
-                fPicture->unref();
+    if (kPicture_DeviceType == fDeviceType) {
+        if (true) {
+            SkPicture* pict = new SkPicture(*fPicture);
+            fPicture->unref();
+            orig->drawPicture(*pict);
+            pict->unref();
+        } else if (true) {
+            SkDynamicMemoryWStream ostream;
+            fPicture->serialize(&ostream);
+            fPicture->unref();
 
-                SkAutoDataUnref data(ostream.copyToData());
-                SkMemoryStream istream(data.data(), data.size());
-                SkPicture pict(&istream);
-                orig->drawPicture(pict);
-            } else {
-                fPicture->draw(orig);
-                fPicture->unref();
-            }
-            fPicture = NULL;
-            break;
-#ifdef SK_SUPPORT_GL
-        case kGPU_CanvasType:
-            if (fShowZoomer) {
-                this->showZoomer(orig);
-            }
-            break;
-#endif
+            SkAutoDataUnref data(ostream.copyToData());
+            SkMemoryStream istream(data.data(), data.size());
+            SkPicture pict(&istream);
+            orig->drawPicture(pict);
+        } else {
+            fPicture->draw(orig);
+            fPicture->unref();
+        }
+        fPicture = NULL;
     }
 
     // Do this after presentGL and other finishing, rather than in afterChild
@@ -1165,7 +1184,11 @@
 }
 
 void SampleWindow::toggleRendering() {
-    fCanvasType = cycle_canvastype(fCanvasType);
+    DeviceType origDevType = fDeviceType;
+    do {
+        fDeviceType = cycle_devicetype(fDeviceType);
+    } while (origDevType != fDeviceType &&
+             !fDevManager->supportsDeviceType(fDeviceType));
     this->updateTitle();
     this->inval(NULL);
 }
@@ -1322,7 +1345,7 @@
     return gConfigNames[c];
 }
 
-static const char* gCanvasTypePrefix[] = {
+static const char* gDeviceTypePrefix[] = {
     "raster: ",
     "picture: ",
     "opengl: "
@@ -1351,7 +1374,7 @@
         title.set("<unknown>");
     }
 
-    title.prepend(gCanvasTypePrefix[fCanvasType]);
+    title.prepend(gDeviceTypePrefix[fDeviceType]);
 
     title.prepend(" ");
     title.prepend(configToString(this->getBitmap().config()));
@@ -1394,25 +1417,6 @@
 
 void SampleWindow::onSizeChange() {
     this->INHERITED::onSizeChange();
-
-    if (fGrContext) {
-        this->attachGL();
-
-        GrPlatformSurfaceDesc desc;
-        desc.reset();
-        desc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
-        desc.fWidth = SkScalarRound(this->width());
-        desc.fHeight = SkScalarRound(this->height());
-        desc.fConfig = kRGBA_8888_GrPixelConfig;
-        desc.fStencilBits = 8;
-        GrGLint buffer;
-        GR_GL_GetIntegerv(GR_GL_FRAMEBUFFER_BINDING, &buffer);
-        desc.fPlatformRenderTarget = buffer;
-
-        SkSafeUnref(fGrRenderTarget);
-        fGrRenderTarget = static_cast<GrRenderTarget*>(
-                                      fGrContext->createPlatformSurface(desc));
-    }
     
     SkView::F2BIter iter(this);
     SkView* view = iter.next();
@@ -1449,6 +1453,7 @@
     this->postInvalDelay();
 #endif
     this->updateTitle();    // to refresh our config
+    fDevManager->windowSizeChanged(this);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1692,7 +1697,7 @@
 
 SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
 //    test();
-    return new SampleWindow(hwnd, argc, argv);
+    return new SampleWindow(hwnd, argc, argv, NULL);
 }
 
 void get_preferred_size(int* x, int* y, int* width, int* height) {