Added run-time switching between OpenGL & ANGLE in SampleApp

http://codereview.appspot.com/5969044/



git-svn-id: http://skia.googlecode.com/svn/trunk@3555 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index dc522b6..92c9e6c 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -53,7 +53,12 @@
 #endif
 
 #define USE_ARROWS_FOR_ZOOM true
-//#define DEFAULT_TO_GPU
+
+#if SK_ANGLE
+//#define DEFAULT_TO_ANGLE 1
+#else
+//#define DEFAULT_TO_GPU 1
+#endif
 
 extern SkView* create_overview(int, const SkViewFactory*[]);
 extern bool is_overview(SkView* view);
@@ -131,113 +136,129 @@
 public:
 
     DefaultDeviceManager()
-#if SK_ANGLE
-    : fUseAltContext(false) 
-#endif
-    {
-        fGrRenderTarget = NULL;
-        fGrContext = NULL;
-        fGL = NULL;
-        fNullGrContext = NULL;
-        fNullGrRenderTarget = NULL;
+        : fCurContext(NULL)
+        , fCurIntf(NULL)
+        , fCurRenderTarget(NULL)
+        , fBackend(kNone_BackEndType) {
     }
 
     virtual ~DefaultDeviceManager() {
-        SkSafeUnref(fGrRenderTarget);
-        SkSafeUnref(fGrContext);
-        SkSafeUnref(fGL);
-        SkSafeUnref(fNullGrContext);
-        SkSafeUnref(fNullGrRenderTarget);
+        SkSafeUnref(fCurContext);
+        SkSafeUnref(fCurIntf);
+        SkSafeUnref(fCurRenderTarget);
     }
 
-    virtual void init(SampleWindow* win, bool useAltContext) {
-#if SK_ANGLE
-        fUseAltContext = useAltContext;
-#endif
-        bool result;
+    virtual void setUpBackend(SampleWindow* win) {
+        SkASSERT(kNone_BackEndType == fBackend);
 
+        fBackend = kNone_BackEndType;
+
+        switch (win->getDeviceType()) {
+            case kRaster_DeviceType:
+                // fallthrough
+            case kPicture_DeviceType:
+                // fallthrough
+            case kGPU_DeviceType:
+                // fallthrough
+            case kNullGPU_DeviceType:
+                // all these guys use the native backend
+                fBackend = kNativeGL_BackEndType;
+                break;
 #if SK_ANGLE
-        if (useAltContext) {
-            result = win->attachANGLE();
-        } else 
+            case kANGLE_DeviceType:
+                // ANGLE is really the only odd man out
+                fBackend = kANGLE_BackEndType;
+                break;
 #endif
-        {
-            result = win->attachGL();
+            default:
+                SkASSERT(false);
+                break;
         }
+
+        bool result = win->attach(fBackend);
         if (!result) {
             SkDebugf("Failed to initialize GL");
+            return;
         }
-        if (NULL == fGL) {
+
+        SkASSERT(NULL == fCurIntf);
+        switch (win->getDeviceType()) {
+            case kRaster_DeviceType:
+                // fallthrough
+            case kPicture_DeviceType:
+                // fallthrough
+            case kGPU_DeviceType:
+                // all these guys use the native interface
+                fCurIntf = GrGLCreateNativeInterface();
+                break;
 #if SK_ANGLE
-            if (useAltContext) {
-                fGL = GrGLCreateANGLEInterface();
-            } else 
+            case kANGLE_DeviceType:
+                fCurIntf = GrGLCreateANGLEInterface();
+                break;
 #endif
-            {
-                fGL = GrGLCreateNativeInterface();
-            }
-            GrAssert(NULL == fGrContext);
-            fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
-                                           (GrPlatform3DContext) fGL);
+            case kNullGPU_DeviceType:
+                fCurIntf = GrGLCreateNullInterface();
+                break;
+            default:
+                SkASSERT(false);
+                break;
         }
-        if (NULL == fGrContext || NULL == fGL) {
-            SkSafeUnref(fGrContext);
-            SkSafeUnref(fGL);
+
+        SkASSERT(NULL == fCurContext);
+        fCurContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
+                                        (GrPlatform3DContext) fCurIntf);
+
+        if (NULL == fCurContext || NULL == fCurIntf) {
+            // We need some context and interface to see results
+            SkSafeUnref(fCurContext);
+            SkSafeUnref(fCurIntf);
             SkDebugf("Failed to setup 3D");
-#if SK_ANGLE
-            if (useAltContext) {
-                win->detachANGLE();
-            } else 
-#endif
-            {
-                win->detachGL();
-            }
+
+            win->detach();
         }
-        if (NULL == fNullGrContext) {
-            const GrGLInterface* nullGL = GrGLCreateNullInterface();
-            fNullGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
-                                               (GrPlatform3DContext) nullGL);
-            nullGL->unref();
-        }
+
+        // call windowSizeChanged to create the render target
+        windowSizeChanged(win);
     }
 
-    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;
-            case kNullGPU_DeviceType:
-                return NULL != fNullGrContext && NULL != fNullGrRenderTarget;
-            default:
-                return false;
-        }
+    virtual void tearDownBackend(SampleWindow *win) {
+        win->detach();
+        fBackend = kNone_BackEndType;
+
+        SkSafeUnref(fCurContext);
+        fCurContext = NULL;
+
+        SkSafeUnref(fCurIntf);
+        fCurIntf = NULL;
+
+        SkSafeUnref(fCurRenderTarget);
+        fCurRenderTarget = NULL;
     }
 
     virtual bool prepareCanvas(SampleWindow::DeviceType dType,
                                SkCanvas* canvas,
                                SampleWindow* win) {
         switch (dType) {
-            case kGPU_DeviceType:
-                if (fGrContext) {
-                    canvas->setDevice(new SkGpuDevice(fGrContext,
-                                                    fGrRenderTarget))->unref();
-                } else {
-                    return false;
-                }
-                break;
-            case kNullGPU_DeviceType:
-                if (fNullGrContext) {
-                    canvas->setDevice(new SkGpuDevice(fNullGrContext,
-                                                      fNullGrRenderTarget))->unref();
-                } else {
-                    return false;
-                }
-                break;
             case kRaster_DeviceType:
+                // fallthrough
             case kPicture_DeviceType:
+                // fallthrough
+#if SK_ANGLE
+            case kANGLE_DeviceType:
+#endif
                 break;
+            case kGPU_DeviceType:
+            case kNullGPU_DeviceType:
+                if (fCurContext) {
+                    canvas->setDevice(new SkGpuDevice(fCurContext,
+                                                    fCurRenderTarget))->unref();
+                } else {
+                    return false;
+                }
+                break;
+            default:
+                SkASSERT(false);
+                return false;
         }
         return true;
     }
@@ -245,85 +266,55 @@
     virtual void publishCanvas(SampleWindow::DeviceType dType,
                                SkCanvas* canvas,
                                SampleWindow* win) {
-        if (fGrContext) {
+        if (fCurContext) {
             // in case we have queued drawing calls
-            fGrContext->flush();
-            if (NULL != fNullGrContext) {
-                fNullGrContext->flush();
-            }
-            if (dType != kGPU_DeviceType &&
-                dType != kNullGPU_DeviceType) {
+            fCurContext->flush();
+
+            if (kGPU_DeviceType != dType && kNullGPU_DeviceType != dType) {
                 // need to send the raster bits to the (gpu) window
-                fGrContext->setRenderTarget(fGrRenderTarget);
+                fCurContext->setRenderTarget(fCurRenderTarget);
                 const SkBitmap& bm = win->getBitmap();
-                fGrRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
+                fCurRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
                                              kSkia8888_PM_GrPixelConfig,
                                              bm.getPixels(),
                                              bm.rowBytes());
             }
         }
-#if SK_ANGLE
-        if (fUseAltContext) {
-            win->presentANGLE();
-        } else 
-#endif
-        {
-            win->presentGL();
-        }
+
+        win->present();
     }
 
     virtual void windowSizeChanged(SampleWindow* win) {
-        if (fGrContext) {
-#if SK_ANGLE
-            if (fUseAltContext) {
-                win->attachANGLE();
-            } else 
-#endif
-            {
-                win->attachGL();
-            }
+
+        if (fCurContext) {
+            win->attach(fBackend);
 
             GrPlatformRenderTargetDesc desc;
             desc.fWidth = SkScalarRound(win->width());
             desc.fHeight = SkScalarRound(win->height());
             desc.fConfig = kSkia8888_PM_GrPixelConfig;
-            GR_GL_GetIntegerv(fGL, GR_GL_SAMPLES, &desc.fSampleCnt);
-            GR_GL_GetIntegerv(fGL, GR_GL_STENCIL_BITS, &desc.fStencilBits);
+            GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt);
+            GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits);
             GrGLint buffer;
-            GR_GL_GetIntegerv(fGL, GR_GL_FRAMEBUFFER_BINDING, &buffer);
+            GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer);
             desc.fRenderTargetHandle = buffer;
 
-            SkSafeUnref(fGrRenderTarget);
-            fGrRenderTarget = fGrContext->createPlatformRenderTarget(desc);
-        }
-        if (NULL != fNullGrContext) {
-            GrPlatformRenderTargetDesc desc;
-            desc.fWidth = SkScalarRound(win->width());
-            desc.fHeight = SkScalarRound(win->height());
-            desc.fConfig = kSkia8888_PM_GrPixelConfig;
-            desc.fStencilBits = 8;
-            desc.fSampleCnt = 0;
-            desc.fRenderTargetHandle = 0;
-            fNullGrRenderTarget = fNullGrContext->createPlatformRenderTarget(desc);
+            SkSafeUnref(fCurRenderTarget);
+            fCurRenderTarget = fCurContext->createPlatformRenderTarget(desc);
         }
     }
 
-    virtual GrContext* getGrContext(SampleWindow::DeviceType dType) {
-        if (kNullGPU_DeviceType == dType) {
-            return fNullGrContext;
-        } else {
-            return fGrContext;
-        }
+    virtual GrContext* getGrContext() {
+        return fCurContext;
     }
 private:
-#if SK_ANGLE
-    bool fUseAltContext;
-#endif
-    GrContext* fGrContext;
-    const GrGLInterface* fGL;
-    GrRenderTarget* fGrRenderTarget;
-    GrContext* fNullGrContext;
-    GrRenderTarget* fNullGrRenderTarget;
+    GrContext*              fCurContext;
+    const GrGLInterface*    fCurIntf;
+    GrRenderTarget*         fCurRenderTarget;
+
+    SkOSWindow::SkBackEndTypes fBackend;
+
+    typedef SampleWindow::DeviceManager INHERITED;
 };
 
 ///////////////
@@ -644,6 +635,9 @@
     static const SampleWindow::DeviceType gCT[] = {
         SampleWindow::kPicture_DeviceType,
         SampleWindow::kGPU_DeviceType,
+#if SK_ANGLE
+        SampleWindow::kANGLE_DeviceType,
+#endif
         SampleWindow::kRaster_DeviceType, // skip the null gpu device in normal cycling
         SampleWindow::kRaster_DeviceType
     };
@@ -669,7 +663,6 @@
 
     const char* resourcePath = NULL;
     fCurrIndex = -1;
-    bool useAltContext = false;
 
     const char* const commandName = argv[0];
     char* const* stop = argv + argc;
@@ -688,12 +681,6 @@
                 }
             }
         } 
-#if SK_ANGLE
-        else if (strcmp(*argv, "--angle") == 0) {
-            argv++;
-            useAltContext = true;
-        } 
-#endif
         else {
             usage(commandName);
         }
@@ -720,11 +707,15 @@
      
     fPicture = NULL;
     
-#ifdef DEFAULT_TO_GPU
-    fDeviceType = kGPU_DeviceType;
-#else
     fDeviceType = kRaster_DeviceType;
+
+#if DEFAULT_TO_GPU
+    fDeviceType = kGPU_DeviceType;
 #endif
+#if SK_ANGLE && DEFAULT_TO_ANGLE
+    fDeviceType = kANGLE_DeviceType;
+#endif
+
     fUseClip = false;
     fNClip = false;
     fAnimating = false;
@@ -764,7 +755,11 @@
     int itemID;
     
     itemID =fAppMenu.appendList("Device Type", "Device Type", sinkID, 0, 
-                                "Raster", "Picture", "OpenGL", NULL);
+                                "Raster", "Picture", "OpenGL", 
+#if SK_ANGLE
+                                "ANGLE",
+#endif
+                                NULL);
     fAppMenu.assignKeyEquivalentToItem(itemID, 'd');
     itemID = fAppMenu.appendTriState("AA", "AA", sinkID, fAAState);
     fAppMenu.assignKeyEquivalentToItem(itemID, 'b');
@@ -825,7 +820,7 @@
         devManager->ref();
         fDevManager = devManager;
     }
-    fDevManager->init(this, useAltContext);
+    fDevManager->setUpBackend(this);
 
     // If another constructor set our dimensions, ensure that our
     // onSizeChange gets called.
@@ -1133,7 +1128,12 @@
     } else {
         switch (fDeviceType) {
             case kRaster_DeviceType:
+                // fallthrough
             case kGPU_DeviceType:
+                // fallthrough
+#if SK_ANGLE
+            case kANGLE_DeviceType:
+#endif
                 canvas = this->INHERITED::beforeChildren(canvas);
                 break;
             case kPicture_DeviceType:
@@ -1142,6 +1142,9 @@
                 break;
             case kNullGPU_DeviceType:
                 break;
+            default:
+                SkASSERT(false);
+                break;
         }
     }
 
@@ -1628,11 +1631,9 @@
             this->updateTitle();
             return true;
         case '\\':
-            if (fDevManager->supportsDeviceType(kNullGPU_DeviceType)) {
-                fDeviceType=  kNullGPU_DeviceType;
-                this->inval(NULL);
-                this->updateTitle();
-            }
+            this->setDeviceType(kNullGPU_DeviceType);
+            this->inval(NULL);
+            this->updateTitle();
             return true;
         case 'p':
             {
@@ -1663,8 +1664,15 @@
 }
 
 void SampleWindow::setDeviceType(DeviceType type) {
-    if (type != fDeviceType && fDevManager->supportsDeviceType(fDeviceType))
-        fDeviceType = type;
+    if (type == fDeviceType)
+        return;
+
+    fDevManager->tearDownBackend(this);
+
+    fDeviceType = type;
+
+    fDevManager->setUpBackend(this);
+
     this->updateTitle();
     this->inval(NULL);
 }
@@ -1676,11 +1684,7 @@
 }
 
 void SampleWindow::toggleRendering() {
-    DeviceType origDevType = fDeviceType;
-    do {
-        fDeviceType = cycle_devicetype(fDeviceType);
-    } while (origDevType != fDeviceType &&
-             !fDevManager->supportsDeviceType(fDeviceType));
+    this->setDeviceType(cycle_devicetype(fDeviceType));
     this->updateTitle();
     this->inval(NULL);
 }
@@ -1857,6 +1861,9 @@
     "raster: ",
     "picture: ",
     "opengl: ",
+#if SK_ANGLE
+    "angle: ",
+#endif
     "null-gl: "
 };