Redelivering r3555 to re-add run-time switching between ANGLE and native opengl
authorrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 2 Apr 2012 19:24:21 +0000 (19:24 +0000)
committerrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 2 Apr 2012 19:24:21 +0000 (19:24 +0000)
http://codereview.appspot.com/5969044/

git-svn-id: http://skia.googlecode.com/svn/trunk@3578 2bbb7eff-a529-9590-31e7-b0007b416f81

include/views/SkOSWindow_Android.h
include/views/SkOSWindow_Mac.h
include/views/SkOSWindow_Unix.h
include/views/SkOSWindow_Win.h
include/views/SkOSWindow_iOS.h
samplecode/SampleApp.cpp
samplecode/SampleApp.h
src/views/mac/SkOSWindow_Mac.cpp
src/views/unix/SkOSWindow_Unix.cpp
src/views/win/SkOSWindow_win.cpp

index bdce5d0..5818a0a 100644 (file)
@@ -18,9 +18,15 @@ class SkOSWindow : public SkWindow {
 public:
     SkOSWindow(void*) {}
     ~SkOSWindow() {}
-    bool attachGL() { return true; }
-    void detachGL() {}
-    void presentGL() {}
+
+    enum SkBackEndTypes {
+        kNone_BackEndType,
+        kNativeGL_BackEndType,
+    };
+
+    bool attach(SkBackEndTypes /* attachType */) { return true; }
+    void detach() {}
+    void present() {}
 
     virtual void onPDFSaved(const char title[], const char desc[],
         const char path[]);
index b09f1dd..01fa29f 100644 (file)
@@ -19,9 +19,15 @@ public:
     
     virtual bool onDispatchClick(int x, int y, Click::State state, 
                                  void* owner);
-    void    detachGL();
-    bool    attachGL();
-    void    presentGL();
+
+    enum SkBackEndTypes {
+        kNone_BackEndType,
+        kNativeGL_BackEndType,
+    };
+
+    void    detach();
+    bool    attach(SkBackEndTypes attachType);
+    void    present();
     
 protected:
     // overrides from SkEventSink
index 3b71af8..40059bf 100644 (file)
@@ -34,9 +34,15 @@ public:
     void* getUnixWindow() const { return (void*)&fUnixWindow; }
     void loop();
     void post_linuxevent();
-    bool attachGL();
-    void detachGL();
-    void presentGL();
+
+    enum SkBackEndTypes {
+        kNone_BackEndType,
+        kNativeGL_BackEndType,
+    };
+
+    bool attach(SkBackEndTypes attachType);
+    void detach();
+    void present();
 
     //static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
 
index c857e7a..2663c8c 100644 (file)
@@ -26,20 +26,19 @@ public:
     void    updateSize();
 
     static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
-    
-    bool attachGL();
-    void detachGL();
-    void presentGL();
 
+    enum SkBackEndTypes {
+        kNone_BackEndType,
+        kNativeGL_BackEndType,
 #if SK_ANGLE
-    bool attachANGLE();
-    void detachANGLE();
-    void presentANGLE();
+        kANGLE_BackEndType,
 #endif
+        kD3D9_BackEndType
+    };
 
-    bool attachD3D9();
-    void detachD3D9();
-    void presentD3D9();
+    bool attach(SkBackEndTypes attachType);
+    void detach();
+    void present();
 
     void* d3d9Device() { return fD3D9Device; }
 
@@ -73,13 +72,26 @@ private:
     EGLSurface          fSurface;
 #endif
 
-    bool                fGLAttached;
-
     void*               fD3D9Device;
-    bool                fD3D9Attached;
 
     HMENU               fMBar;
 
+    SkBackEndTypes      fAttached;
+
+    bool attachGL();
+    void detachGL();
+    void presentGL();
+
+#if SK_ANGLE
+    bool attachANGLE();
+    void detachANGLE();
+    void presentANGLE();
+#endif
+
+    bool attachD3D9();
+    void detachD3D9();
+    void presentD3D9();
+
     typedef SkWindow INHERITED; 
 };
 
index ff28484..34ce421 100755 (executable)
@@ -18,9 +18,15 @@ public:
 
     virtual bool onDispatchClick(int x, int y, Click::State state, 
                                  void* owner);
-    void    detachGL();
-    bool    attachGL();
-    void    presentGL();
+
+    enum SkBackEndTypes {
+        kNone_BackEndType,
+        kNativeGL_BackEndType,
+    };
+
+    void    detach();
+    bool    attach(SkBackEndTypes attachType);
+    void    present();
 
 protected:
     // overrides from SkEventSink
index dc522b6..92c9e6c 100644 (file)
@@ -53,7 +53,12 @@ SkTDArray<char> gTempDataStore;
 #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 @@ class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
 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();
-            }
-        }
-        if (NULL == fNullGrContext) {
-            const GrGLInterface* nullGL = GrGLCreateNullInterface();
-            fNullGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
-                                               (GrPlatform3DContext) nullGL);
-            nullGL->unref();
+
+            win->detach();
         }
+
+        // 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;
-                }
+            case kRaster_DeviceType:
+                // fallthrough
+            case kPicture_DeviceType:
+                // fallthrough
+#if SK_ANGLE
+            case kANGLE_DeviceType:
+#endif
                 break;
+            case kGPU_DeviceType:
             case kNullGPU_DeviceType:
-                if (fNullGrContext) {
-                    canvas->setDevice(new SkGpuDevice(fNullGrContext,
-                                                      fNullGrRenderTarget))->unref();
+                if (fCurContext) {
+                    canvas->setDevice(new SkGpuDevice(fCurContext,
+                                                    fCurRenderTarget))->unref();
                 } else {
                     return false;
                 }
                 break;
-            case kRaster_DeviceType:
-            case kPicture_DeviceType:
-                break;
+            default:
+                SkASSERT(false);
+                return false;
         }
         return true;
     }
@@ -245,85 +266,55 @@ public:
     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 inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType
     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 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
 
     const char* resourcePath = NULL;
     fCurrIndex = -1;
-    bool useAltContext = false;
 
     const char* const commandName = argv[0];
     char* const* stop = argv + argc;
@@ -688,12 +681,6 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
                 }
             }
         } 
-#if SK_ANGLE
-        else if (strcmp(*argv, "--angle") == 0) {
-            argv++;
-            useAltContext = true;
-        } 
-#endif
         else {
             usage(commandName);
         }
@@ -720,11 +707,15 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
      
     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 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
     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 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
         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 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
     } 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 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
                 break;
             case kNullGPU_DeviceType:
                 break;
+            default:
+                SkASSERT(false);
+                break;
         }
     }
 
@@ -1628,11 +1631,9 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
             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 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
 }
 
 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::toggleSlideshow() {
 }
 
 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 @@ static const char* gDeviceTypePrefix[] = {
     "raster: ",
     "picture: ",
     "opengl: ",
+#if SK_ANGLE
+    "angle: ",
+#endif
     "null-gl: "
 };
 
index 94f663f..ba404da 100644 (file)
@@ -36,6 +36,9 @@ public:
         kRaster_DeviceType,
         kPicture_DeviceType,
         kGPU_DeviceType,
+#if SK_ANGLE
+        kANGLE_DeviceType,
+#endif
         kNullGPU_DeviceType
     };
     /**
@@ -47,12 +50,9 @@ public:
      */
     class DeviceManager : public SkRefCnt {
     public:
-        // called at end of SampleWindow cons
-        virtual void init(SampleWindow* win, bool useAltContext) = 0;
+        virtual void setUpBackend(SampleWindow* win) = 0;
 
-        // called when selecting a new device type
-        // can disallow a device type by returning false.
-        virtual bool supportsDeviceType(DeviceType dType) = 0;
+        virtual void tearDownBackend(SampleWindow* win) = 0;
 
         // called before drawing. should install correct device
         // type on the canvas. Will skip drawing if returns false.
@@ -71,7 +71,7 @@ public:
         virtual void windowSizeChanged(SampleWindow* win) = 0;
 
         // return the GrContext backing gpu devices
-        virtual GrContext* getGrContext(DeviceType dType) = 0;
+        virtual GrContext* getGrContext() = 0;
     };
 
     SampleWindow(void* hwnd, int argc, char** argv, DeviceManager*);
@@ -85,7 +85,7 @@ public:
     void toggleFPS();
     void showOverview();
 
-    GrContext* getGrContext() const { return fDevManager->getGrContext(fDeviceType); }
+    GrContext* getGrContext() const { return fDevManager->getGrContext(); }
 
     void setZoomCenter(float x, float y);
     void changeZoomLevel(float delta);
@@ -100,6 +100,8 @@ public:
     SkData* getPDFData() { return fPDFData; }
     void postInvalDelay();
 
+    DeviceType getDeviceType() const { return fDeviceType; }
+
 protected:
     virtual void onDraw(SkCanvas* canvas);
     virtual bool onHandleKey(SkKey key);
index d41c9a7..63106f0 100644 (file)
@@ -500,7 +500,7 @@ AGLContext create_gl(WindowRef wref)
     return ctx;
 }
 
-bool SkOSWindow::attachGL()
+bool SkOSWindow::attach(SkBackEndTypes /* attachType */)
 {
     if (NULL == fAGLCtx) {
         fAGLCtx = create_gl((WindowRef)fHWND);
@@ -532,11 +532,11 @@ bool SkOSWindow::attachGL()
     return success;
 }
 
-void SkOSWindow::detachGL() {
+void SkOSWindow::detach() {
     aglSetWindowRef((AGLContext)fAGLCtx, NULL);
 }
 
-void SkOSWindow::presentGL() {
+void SkOSWindow::present() {
     aglSwapBuffers((AGLContext)fAGLCtx);
 }
 
index b4b0f17..01bc21c 100644 (file)
@@ -170,7 +170,7 @@ void SkOSWindow::mapWindowAndWait()
 
 }
 
-bool SkOSWindow::attachGL()
+bool SkOSWindow::attach(SkBackEndTypes /* attachType */)
 {
     if (fGLAttached) return true;
     Display* dsp = fUnixWindow.fDisplay;
@@ -194,7 +194,7 @@ bool SkOSWindow::attachGL()
     return true;
 }
 
-void SkOSWindow::detachGL()
+void SkOSWindow::detach()
 {
     if (!fUnixWindow.fDisplay || !fGLAttached) return;
     fGLAttached = false;
@@ -204,7 +204,7 @@ void SkOSWindow::detachGL()
     this->inval(NULL);
 }
 
-void SkOSWindow::presentGL()
+void SkOSWindow::present()
 {
     if (fUnixWindow.fDisplay && fGLAttached) {
         glXSwapBuffers(fUnixWindow.fDisplay, fUnixWindow.fWin);
index 75f6de6..d3e49c9 100644 (file)
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkTypes.h"
-
-#if defined(SK_BUILD_FOR_WIN)
-
-#include <GL/gl.h>
-#include <d3d9.h>
-#include <WindowsX.h>
-#include "SkWGL.h"
-#include "SkWindow.h"
-#include "SkCanvas.h"
-#include "SkOSMenu.h"
-#include "SkTime.h"
-#include "SkUtils.h"
-
-#include "SkGraphics.h"
-
-#if SK_ANGLE
-#include "gl/GrGLInterface.h"
-
-#include "GLES2/gl2.h"
-#endif
-
-#define INVALIDATE_DELAY_MS 200
-
-static SkOSWindow* gCurrOSWin;
-static HWND gEventTarget;
-
-#define WM_EVENT_CALLBACK (WM_USER+0)
-
-void post_skwinevent()
-{
-    PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
-}
-
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) 
-#if SK_ANGLE
-                                     , fDisplay(EGL_NO_DISPLAY)
-                                     , fContext(EGL_NO_CONTEXT)
-                                     , fSurface(EGL_NO_SURFACE)
-#endif
-                                     , fHGLRC(NULL),
-                                     fGLAttached(false),
-                                     fD3D9Device(NULL),
-                                     fD3D9Attached(FALSE) {
-    gEventTarget = (HWND)hWnd;
-}
-
-SkOSWindow::~SkOSWindow() {
-    if (NULL != fD3D9Device) {
-        ((IDirect3DDevice9*)fD3D9Device)->Release();
-    }
-    if (NULL != fHGLRC) {
-        wglDeleteContext((HGLRC)fHGLRC);
-    }
-#if SK_ANGLE
-    if (EGL_NO_DISPLAY != fDisplay) {
-        eglDestroyContext(fDisplay, fContext);
-    }
-#endif
-}
-
-static SkKey winToskKey(WPARAM vk) {
-    static const struct {
-        WPARAM    fVK;
-        SkKey    fKey;
-    } gPair[] = {
-        { VK_BACK,    kBack_SkKey },
-        { VK_CLEAR,    kBack_SkKey },
-        { VK_RETURN, kOK_SkKey },
-        { VK_UP,     kUp_SkKey },
-        { VK_DOWN,     kDown_SkKey },
-        { VK_LEFT,     kLeft_SkKey },
-        { VK_RIGHT,     kRight_SkKey }
-    };
-    for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
-        if (gPair[i].fVK == vk) {
-            return gPair[i].fKey;
-        }
-    }
-    return kNONE_SkKey;
-}
-
-bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
-    switch (message) {
-        case WM_KEYDOWN: {
-            SkKey key = winToskKey(wParam);
-            if (kNONE_SkKey != key) {
-                this->handleKey(key);
-                return true;
-            }
-        } break;
-        case WM_KEYUP: {
-            SkKey key = winToskKey(wParam);
-            if (kNONE_SkKey != key) {
-                this->handleKeyUp(key);
-                return true;
-            }
-        } break;
-        case WM_UNICHAR:
-            this->handleChar(wParam);
-            return true; 
-        case WM_CHAR: {
-            this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
-            return true;
-        } break;
-        case WM_SIZE:
-            this->resize(lParam & 0xFFFF, lParam >> 16);
-            break;
-        case WM_PAINT: {
-            PAINTSTRUCT ps;
-            HDC hdc = BeginPaint(hWnd, &ps);
-            this->doPaint(hdc);
-            EndPaint(hWnd, &ps);
-            return true;
-            } break;
-
-        case WM_TIMER: {
-            RECT* rect = (RECT*)wParam;
-            InvalidateRect(hWnd, rect, FALSE);
-            KillTimer(hWnd, (UINT_PTR)rect);
-            delete rect;
-            return true;
-        } break;
-    
-        case WM_LBUTTONDOWN: 
-            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
-            return true;
-                    
-        case WM_MOUSEMOVE:
-            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
-            return true;
-
-        case WM_LBUTTONUP:
-            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
-            return true;
-
-        case WM_EVENT_CALLBACK:
-            if (SkEvent::ProcessEvent()) {
-                post_skwinevent();
-            }
-            return true;
-    }
-    return false;
-}
-
-void SkOSWindow::doPaint(void* ctx) {
-    this->update(NULL);
-
-    if (!fGLAttached && !fD3D9Attached)
-    {
-        HDC hdc = (HDC)ctx;
-        const SkBitmap& bitmap = this->getBitmap();
-
-        BITMAPINFO bmi;
-        memset(&bmi, 0, sizeof(bmi));
-        bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
-        bmi.bmiHeader.biWidth       = bitmap.width();
-        bmi.bmiHeader.biHeight      = -bitmap.height(); // top-down image 
-        bmi.bmiHeader.biPlanes      = 1;
-        bmi.bmiHeader.biBitCount    = 32;
-        bmi.bmiHeader.biCompression = BI_RGB;
-        bmi.bmiHeader.biSizeImage   = 0;
-
-        // 
-        // Do the SetDIBitsToDevice. 
-        // 
-        // TODO(wjmaclean):
-        //       Fix this call to handle SkBitmaps that have rowBytes != width,
-        //       i.e. may have padding at the end of lines. The SkASSERT below
-        //       may be ignored by builds, and the only obviously safe option
-        //       seems to be to copy the bitmap to a temporary (contiguous)
-        //       buffer before passing to SetDIBitsToDevice().
-        SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
-        bitmap.lockPixels();
-        int iRet = SetDIBitsToDevice(hdc,
-            0, 0,
-            bitmap.width(), bitmap.height(),
-            0, 0,
-            0, bitmap.height(),
-            bitmap.getPixels(),
-            &bmi,
-            DIB_RGB_COLORS);
-        bitmap.unlockPixels();
-    }
-}
-
-#if 0
-void SkOSWindow::updateSize()
-{
-    RECT    r;
-    GetWindowRect((HWND)this->getHWND(), &r);
-    this->resize(r.right - r.left, r.bottom - r.top);
-}
-#endif
-
-void SkOSWindow::onHandleInval(const SkIRect& r) {
-    RECT* rect = new RECT;
-    rect->left    = r.fLeft;
-    rect->top     = r.fTop;
-    rect->right   = r.fRight;
-    rect->bottom  = r.fBottom;
-    SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
-}
-
-void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
-{
-}
-
-void SkOSWindow::onSetTitle(const char title[]){
-    SetWindowTextA((HWND)fHWND, title);
-}
-
-enum {
-    SK_MacReturnKey     = 36,
-    SK_MacDeleteKey     = 51,
-    SK_MacEndKey        = 119,
-    SK_MacLeftKey       = 123,
-    SK_MacRightKey      = 124,
-    SK_MacDownKey       = 125,
-    SK_MacUpKey         = 126,
-    
-    SK_Mac0Key          = 0x52,
-    SK_Mac1Key          = 0x53,
-    SK_Mac2Key          = 0x54,
-    SK_Mac3Key          = 0x55,
-    SK_Mac4Key          = 0x56,
-    SK_Mac5Key          = 0x57,
-    SK_Mac6Key          = 0x58,
-    SK_Mac7Key          = 0x59,
-    SK_Mac8Key          = 0x5b,
-    SK_Mac9Key          = 0x5c
-};
-    
-static SkKey raw2key(uint32_t raw)
-{
-    static const struct {
-        uint32_t  fRaw;
-        SkKey   fKey;
-    } gKeys[] = {
-        { SK_MacUpKey,      kUp_SkKey       },
-        { SK_MacDownKey,    kDown_SkKey     },
-        { SK_MacLeftKey,    kLeft_SkKey     },
-        { SK_MacRightKey,   kRight_SkKey    },
-        { SK_MacReturnKey,  kOK_SkKey       },
-        { SK_MacDeleteKey,  kBack_SkKey     },
-        { SK_MacEndKey,     kEnd_SkKey      },
-        { SK_Mac0Key,       k0_SkKey        },
-        { SK_Mac1Key,       k1_SkKey        },
-        { SK_Mac2Key,       k2_SkKey        },
-        { SK_Mac3Key,       k3_SkKey        },
-        { SK_Mac4Key,       k4_SkKey        },
-        { SK_Mac5Key,       k5_SkKey        },
-        { SK_Mac6Key,       k6_SkKey        },
-        { SK_Mac7Key,       k7_SkKey        },
-        { SK_Mac8Key,       k8_SkKey        },
-        { SK_Mac9Key,       k9_SkKey        }
-    };
-    
-    for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
-        if (gKeys[i].fRaw == raw)
-            return gKeys[i].fKey;
-    return kNONE_SkKey;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void SkEvent::SignalNonEmptyQueue()
-{
-    post_skwinevent();
-    //SkDebugf("signal nonempty\n");
-}
-
-static UINT_PTR gTimer;
-
-VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
-{
-    SkEvent::ServiceQueueTimer();
-    //SkDebugf("timer task fired\n");
-}
-
-void SkEvent::SignalQueueTimer(SkMSec delay)
-{
-    if (gTimer)
-    {
-        KillTimer(NULL, gTimer);
-        gTimer = NULL;
-    }
-    if (delay)
-    {     
-        gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
-        //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
-    }
-}
-
-
-#define USE_MSAA 0
-
-HGLRC create_gl(HWND hwnd) {
-    HDC dc = GetDC(hwnd);
-    SkWGLExtensions extensions;
-    if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
-        return NULL;
-    }
-
-    HDC prevDC = wglGetCurrentDC();
-    HGLRC prevGLRC = wglGetCurrentContext();
-    PIXELFORMATDESCRIPTOR pfd;
-
-    int format = 0;
-
-    GLint iattrs[] = {
-        SK_WGL_DRAW_TO_WINDOW, TRUE,
-        SK_WGL_DOUBLE_BUFFER, TRUE,
-        SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,
-        SK_WGL_SUPPORT_OPENGL, TRUE,
-        SK_WGL_COLOR_BITS, 24,
-        SK_WGL_ALPHA_BITS, 8,
-        SK_WGL_STENCIL_BITS, 8,
-
-        // these must be kept last
-        SK_WGL_SAMPLE_BUFFERS, TRUE,
-        SK_WGL_SAMPLES, 0,
-        0,0
-    };
-    static const int kSampleBuffersValueIdx = SK_ARRAY_COUNT(iattrs) - 5;
-    static const int kSamplesValueIdx = SK_ARRAY_COUNT(iattrs) - 3;
-    if (USE_MSAA && extensions.hasExtension(dc, "WGL_ARB_multisample")) {
-        for (int samples = 16; samples > 1; --samples) {
-            
-            iattrs[kSamplesValueIdx] = samples;
-            GLfloat fattrs[] = {0,0};
-            GLuint num;
-            int formats[64];
-            extensions.choosePixelFormat(dc, iattrs, fattrs, 64, formats, &num);
-            num = min(num,64);
-            for (GLuint i = 0; i < num; ++i) {
-                DescribePixelFormat(dc, formats[i], sizeof(pfd), &pfd);
-                if (SetPixelFormat(dc, formats[i], &pfd)) {
-                    format = formats[i];
-                    break;
-                }
-            }
-        }
-    }
-    if (0 == format) {
-        iattrs[kSampleBuffersValueIdx-1] = iattrs[kSampleBuffersValueIdx] = 0;
-        iattrs[kSamplesValueIdx-1] = iattrs[kSamplesValueIdx] = 0;
-        GLfloat fattrs[] = {0,0};
-        GLuint num;
-        extensions.choosePixelFormat(dc, iattrs, fattrs, 1, &format, &num);
-        DescribePixelFormat(dc, format, sizeof(pfd), &pfd);
-        BOOL set = SetPixelFormat(dc, format, &pfd);
-        SkASSERT(TRUE == set);
-    }
-    
-    HGLRC glrc = wglCreateContext(dc);
-    SkASSERT(glrc);
-
-    wglMakeCurrent(prevDC, prevGLRC);
-    return glrc;
-}
-
-bool SkOSWindow::attachGL() {
-    if (NULL == fHGLRC) {
-        fHGLRC = create_gl((HWND)fHWND);
-        if (NULL == fHGLRC) {
-            return false;
-        }
-        glClearStencil(0);
-        glClearColor(0, 0, 0, 0);
-        glStencilMask(0xffffffff);
-        glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-    }
-    if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
-        glViewport(0, 0, SkScalarRound(this->width()),
-                   SkScalarRound(this->height()));
-        fGLAttached = true;
-        return true;
-    }
-    return false;
-}
-
-void SkOSWindow::detachGL() {
-    wglMakeCurrent(GetDC((HWND)fHWND), 0);
-    fGLAttached = false;
-}
-
-void SkOSWindow::presentGL() {
-    glFlush();
-    SwapBuffers(GetDC((HWND)fHWND));
-}
-
-#if SK_ANGLE
-bool create_ANGLE(EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
-                  EGLContext* eglContext, EGLSurface* eglSurface) {
-    EGLint contextAttribs[] = { 
-        EGL_CONTEXT_CLIENT_VERSION, 2, 
-        EGL_NONE, EGL_NONE 
-    };
-    EGLint configAttribList[] = {
-        EGL_RED_SIZE,       8,
-        EGL_GREEN_SIZE,     8,
-        EGL_BLUE_SIZE,      8,
-        EGL_ALPHA_SIZE,     8,
-        EGL_DEPTH_SIZE,     8,
-        EGL_STENCIL_SIZE,   8,
-        EGL_NONE
-    };
-    EGLint surfaceAttribList[] = {
-        EGL_NONE, EGL_NONE
-    };
-
-    EGLDisplay display = eglGetDisplay(GetDC(hWnd));
-    if (display == EGL_NO_DISPLAY ) {
-       return false;
-    }
-
-    // Initialize EGL
-    EGLint majorVersion, minorVersion;
-    if (!eglInitialize(display, &majorVersion, &minorVersion)) {
-       return false;
-    }
-
-    EGLint numConfigs;
-    if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {
-       return false;
-    }
-
-    // Choose config
-    EGLConfig config;
-    if (!eglChooseConfig(display, configAttribList, 
-                                &config, 1, &numConfigs)) {
-       return false;
-    }
-
-    // Create a surface
-    EGLSurface surface = eglCreateWindowSurface(display, config, 
-                                                (EGLNativeWindowType)hWnd, 
-                                                surfaceAttribList);
-    if (surface == EGL_NO_SURFACE) {
-       return false;
-    }
-
-    // Create a GL context
-    EGLContext context = eglCreateContext(display, config, 
-                                          EGL_NO_CONTEXT,
-                                          contextAttribs );
-    if (context == EGL_NO_CONTEXT ) {
-       return false;
-    }   
-    
-    // Make the context current
-    if (!eglMakeCurrent(display, surface, surface, context)) {
-       return false;
-    }
-    
-    *eglDisplay = display;
-    *eglContext = context;
-    *eglSurface = surface;
-    return true;
-}
-
-bool SkOSWindow::attachANGLE() {
-    if (EGL_NO_DISPLAY == fDisplay) {
-        bool bResult = create_ANGLE((HWND)fHWND, &fDisplay, &fContext, &fSurface);
-        if (false == bResult) {
-            return false;
-        }
-        const GrGLInterface* intf = GrGLCreateANGLEInterface();
-
-        if (intf) {
-            GR_GL_CALL(intf, ClearStencil(0));
-            GR_GL_CALL(intf, ClearColor(0, 0, 0, 0));
-            GR_GL_CALL(intf, StencilMask(0xffffffff));
-            GR_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT));
-        }
-    }
-    if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
-        const GrGLInterface* intf = GrGLCreateANGLEInterface();
-
-        if (intf ) {
-            GR_GL_CALL(intf, Viewport(0, 0, SkScalarRound(this->width()),
-                                      SkScalarRound(this->height())));
-        }
-        fGLAttached = true;
-        return true;
-    }
-    return false;
-}
-
-void SkOSWindow::detachANGLE() {
-    eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
-    fGLAttached = false;
-}
-
-void SkOSWindow::presentANGLE() {
-    const GrGLInterface* intf = GrGLCreateANGLEInterface();
-
-    if (intf) {
-        GR_GL_CALL(intf, Flush());
-    }
-    eglSwapBuffers(fDisplay, fSurface);
-}
-#endif
-
-IDirect3DDevice9* create_d3d9_device(HWND hwnd) {
-    HRESULT hr;
-
-    IDirect3D9* d3d9;
-    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
-    if (NULL == d3d9) {
-        return NULL;
-    }
-    D3DDEVTYPE devType = D3DDEVTYPE_HAL;
-    //D3DDEVTYPE devType = D3DDEVTYPE_REF;
-    DWORD qLevels;
-    DWORD qLevelsDepth;
-    D3DMULTISAMPLE_TYPE type;
-    for (type = D3DMULTISAMPLE_16_SAMPLES; 
-         type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {
-        hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, 
-                                              devType, D3DFMT_D24S8, TRUE,
-                                              type, &qLevels);
-        qLevels = (hr == D3D_OK) ? qLevels : 0;
-        hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, 
-                                              devType, D3DFMT_A8R8G8B8, TRUE,
-                                              type, &qLevelsDepth);
-        qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;
-        qLevels = min(qLevels,qLevelsDepth);
-        if (qLevels > 0) {
-            break;
-        }
-    }
-    qLevels = 0;
-    IDirect3DDevice9* d3d9Device;
-    D3DPRESENT_PARAMETERS pres;
-    memset(&pres, 0, sizeof(pres));
-    pres.EnableAutoDepthStencil = TRUE;
-    pres.AutoDepthStencilFormat = D3DFMT_D24S8;
-    pres.BackBufferCount = 2;
-    pres.BackBufferFormat = D3DFMT_A8R8G8B8;
-    pres.BackBufferHeight = 0;
-    pres.BackBufferWidth = 0;
-    if (qLevels > 0) {
-        pres.MultiSampleType = type;
-        pres.MultiSampleQuality = qLevels-1;
-    } else {
-        pres.MultiSampleType = D3DMULTISAMPLE_NONE;
-        pres.MultiSampleQuality = 0;
-    }
-    pres.SwapEffect = D3DSWAPEFFECT_DISCARD;
-    pres.Windowed = TRUE;
-    pres.hDeviceWindow = hwnd;
-    pres.PresentationInterval = 1;
-    pres.Flags = 0;
-    hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,
-                            devType,
-                            hwnd, 
-                            D3DCREATE_HARDWARE_VERTEXPROCESSING, 
-                            &pres, 
-                            &d3d9Device);    
-    D3DERR_INVALIDCALL;
-    if (SUCCEEDED(hr)) {
-        d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);
-        return d3d9Device;
-    }
-    return NULL;
-}
-
-// This needs some improvement. D3D doesn't have the same notion of attach/detach
-// as GL. However, just allowing GDI to write to the window after creating the 
-// D3D device seems to work. 
-// We need to handle resizing. On XP and earlier Reset() will trash all our textures
-// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we
-// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing
-// everything. Currently we do nothing and the D3D9 image gets stretched/compressed
-// when resized.
-
-bool SkOSWindow::attachD3D9() {
-    if (NULL == fD3D9Device) {
-        fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);
-    }
-    if (NULL != fD3D9Device) {
-        ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
-        fD3D9Attached = true;
-    }
-    return fD3D9Attached;
-}
-
-void SkOSWindow::detachD3D9() {
-    if (NULL != fD3D9Device) {
-        ((IDirect3DDevice9*)fD3D9Device)->EndScene();
-    }
-    fD3D9Attached = false;
-}
-
-void SkOSWindow::presentD3D9() {
-    if (NULL != fD3D9Device) {
-        HRESULT hr;
-        hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();
-        SkASSERT(SUCCEEDED(hr));
-        hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);
-        SkASSERT(SUCCEEDED(hr));
-        hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET | 
-                                                     D3DCLEAR_STENCIL, 0x0, 0, 
-                                                     0);
-        SkASSERT(SUCCEEDED(hr));
-        hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
-        SkASSERT(SUCCEEDED(hr));
-    }
-}
-
-
-#endif
-
+\r
+/*\r
+ * Copyright 2011 Google Inc.\r
+ *\r
+ * Use of this source code is governed by a BSD-style license that can be\r
+ * found in the LICENSE file.\r
+ */\r
+#include "SkTypes.h"\r
+\r
+#if defined(SK_BUILD_FOR_WIN)\r
+\r
+#include <GL/gl.h>\r
+#include <d3d9.h>\r
+#include <WindowsX.h>\r
+#include "SkWGL.h"\r
+#include "SkWindow.h"\r
+#include "SkCanvas.h"\r
+#include "SkOSMenu.h"\r
+#include "SkTime.h"\r
+#include "SkUtils.h"\r
+\r
+#include "SkGraphics.h"\r
+\r
+#if SK_ANGLE\r
+#include "gl/GrGLInterface.h"\r
+\r
+#include "GLES2/gl2.h"\r
+#endif\r
+\r
+#define INVALIDATE_DELAY_MS 200\r
+\r
+static SkOSWindow* gCurrOSWin;\r
+static HWND gEventTarget;\r
+\r
+#define WM_EVENT_CALLBACK (WM_USER+0)\r
+\r
+void post_skwinevent()\r
+{\r
+    PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);\r
+}\r
+\r
+SkOSWindow::SkOSWindow(void* hWnd) \r
+    : fHWND(hWnd) \r
+#if SK_ANGLE\r
+    , fDisplay(EGL_NO_DISPLAY)\r
+    , fContext(EGL_NO_CONTEXT)\r
+    , fSurface(EGL_NO_SURFACE)\r
+#endif\r
+    , fHGLRC(NULL)\r
+    , fD3D9Device(NULL)\r
+    , fAttached(kNone_BackEndType) {\r
+    gEventTarget = (HWND)hWnd;\r
+}\r
+\r
+SkOSWindow::~SkOSWindow() {\r
+    if (NULL != fD3D9Device) {\r
+        ((IDirect3DDevice9*)fD3D9Device)->Release();\r
+    }\r
+    if (NULL != fHGLRC) {\r
+        wglDeleteContext((HGLRC)fHGLRC);\r
+    }\r
+#if SK_ANGLE\r
+    if (EGL_NO_CONTEXT != fContext) {\r
+        eglDestroyContext(fDisplay, fContext);\r
+        fContext = EGL_NO_CONTEXT;\r
+    }\r
+\r
+    if (EGL_NO_SURFACE != fSurface) {\r
+        eglDestroySurface(fDisplay, fSurface);\r
+        fSurface = EGL_NO_SURFACE;\r
+    }\r
+\r
+    if (EGL_NO_DISPLAY != fDisplay) {\r
+        eglTerminate(fDisplay);\r
+        fDisplay = EGL_NO_DISPLAY;\r
+    }\r
+#endif\r
+}\r
+\r
+static SkKey winToskKey(WPARAM vk) {\r
+    static const struct {\r
+        WPARAM    fVK;\r
+        SkKey    fKey;\r
+    } gPair[] = {\r
+        { VK_BACK,    kBack_SkKey },\r
+        { VK_CLEAR,    kBack_SkKey },\r
+        { VK_RETURN, kOK_SkKey },\r
+        { VK_UP,     kUp_SkKey },\r
+        { VK_DOWN,     kDown_SkKey },\r
+        { VK_LEFT,     kLeft_SkKey },\r
+        { VK_RIGHT,     kRight_SkKey }\r
+    };\r
+    for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {\r
+        if (gPair[i].fVK == vk) {\r
+            return gPair[i].fKey;\r
+        }\r
+    }\r
+    return kNONE_SkKey;\r
+}\r
+\r
+bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {\r
+    switch (message) {\r
+        case WM_KEYDOWN: {\r
+            SkKey key = winToskKey(wParam);\r
+            if (kNONE_SkKey != key) {\r
+                this->handleKey(key);\r
+                return true;\r
+            }\r
+        } break;\r
+        case WM_KEYUP: {\r
+            SkKey key = winToskKey(wParam);\r
+            if (kNONE_SkKey != key) {\r
+                this->handleKeyUp(key);\r
+                return true;\r
+            }\r
+        } break;\r
+        case WM_UNICHAR:\r
+            this->handleChar(wParam);\r
+            return true; \r
+        case WM_CHAR: {\r
+            this->handleChar(SkUTF8_ToUnichar((char*)&wParam));\r
+            return true;\r
+        } break;\r
+        case WM_SIZE:\r
+            this->resize(lParam & 0xFFFF, lParam >> 16);\r
+            break;\r
+        case WM_PAINT: {\r
+            PAINTSTRUCT ps;\r
+            HDC hdc = BeginPaint(hWnd, &ps);\r
+            this->doPaint(hdc);\r
+            EndPaint(hWnd, &ps);\r
+            return true;\r
+            } break;\r
+\r
+        case WM_TIMER: {\r
+            RECT* rect = (RECT*)wParam;\r
+            InvalidateRect(hWnd, rect, FALSE);\r
+            KillTimer(hWnd, (UINT_PTR)rect);\r
+            delete rect;\r
+            return true;\r
+        } break;\r
+    \r
+        case WM_LBUTTONDOWN: \r
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);\r
+            return true;\r
+                    \r
+        case WM_MOUSEMOVE:\r
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);\r
+            return true;\r
+\r
+        case WM_LBUTTONUP:\r
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);\r
+            return true;\r
+\r
+        case WM_EVENT_CALLBACK:\r
+            if (SkEvent::ProcessEvent()) {\r
+                post_skwinevent();\r
+            }\r
+            return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+void SkOSWindow::doPaint(void* ctx) {\r
+    this->update(NULL);\r
+\r
+    if (kNone_BackEndType == fAttached)\r
+    {\r
+        HDC hdc = (HDC)ctx;\r
+        const SkBitmap& bitmap = this->getBitmap();\r
+\r
+        BITMAPINFO bmi;\r
+        memset(&bmi, 0, sizeof(bmi));\r
+        bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);\r
+        bmi.bmiHeader.biWidth       = bitmap.width();\r
+        bmi.bmiHeader.biHeight      = -bitmap.height(); // top-down image \r
+        bmi.bmiHeader.biPlanes      = 1;\r
+        bmi.bmiHeader.biBitCount    = 32;\r
+        bmi.bmiHeader.biCompression = BI_RGB;\r
+        bmi.bmiHeader.biSizeImage   = 0;\r
+\r
+        // \r
+        // Do the SetDIBitsToDevice. \r
+        // \r
+        // TODO(wjmaclean):\r
+        //       Fix this call to handle SkBitmaps that have rowBytes != width,\r
+        //       i.e. may have padding at the end of lines. The SkASSERT below\r
+        //       may be ignored by builds, and the only obviously safe option\r
+        //       seems to be to copy the bitmap to a temporary (contiguous)\r
+        //       buffer before passing to SetDIBitsToDevice().\r
+        SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());\r
+        bitmap.lockPixels();\r
+        int iRet = SetDIBitsToDevice(hdc,\r
+            0, 0,\r
+            bitmap.width(), bitmap.height(),\r
+            0, 0,\r
+            0, bitmap.height(),\r
+            bitmap.getPixels(),\r
+            &bmi,\r
+            DIB_RGB_COLORS);\r
+        bitmap.unlockPixels();\r
+    }\r
+}\r
+\r
+#if 0\r
+void SkOSWindow::updateSize()\r
+{\r
+    RECT    r;\r
+    GetWindowRect((HWND)this->getHWND(), &r);\r
+    this->resize(r.right - r.left, r.bottom - r.top);\r
+}\r
+#endif\r
+\r
+void SkOSWindow::onHandleInval(const SkIRect& r) {\r
+    RECT* rect = new RECT;\r
+    rect->left    = r.fLeft;\r
+    rect->top     = r.fTop;\r
+    rect->right   = r.fRight;\r
+    rect->bottom  = r.fBottom;\r
+    SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);\r
+}\r
+\r
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)\r
+{\r
+}\r
+\r
+void SkOSWindow::onSetTitle(const char title[]){\r
+    SetWindowTextA((HWND)fHWND, title);\r
+}\r
+\r
+enum {\r
+    SK_MacReturnKey     = 36,\r
+    SK_MacDeleteKey     = 51,\r
+    SK_MacEndKey        = 119,\r
+    SK_MacLeftKey       = 123,\r
+    SK_MacRightKey      = 124,\r
+    SK_MacDownKey       = 125,\r
+    SK_MacUpKey         = 126,\r
+    \r
+    SK_Mac0Key          = 0x52,\r
+    SK_Mac1Key          = 0x53,\r
+    SK_Mac2Key          = 0x54,\r
+    SK_Mac3Key          = 0x55,\r
+    SK_Mac4Key          = 0x56,\r
+    SK_Mac5Key          = 0x57,\r
+    SK_Mac6Key          = 0x58,\r
+    SK_Mac7Key          = 0x59,\r
+    SK_Mac8Key          = 0x5b,\r
+    SK_Mac9Key          = 0x5c\r
+};\r
+    \r
+static SkKey raw2key(uint32_t raw)\r
+{\r
+    static const struct {\r
+        uint32_t  fRaw;\r
+        SkKey   fKey;\r
+    } gKeys[] = {\r
+        { SK_MacUpKey,      kUp_SkKey       },\r
+        { SK_MacDownKey,    kDown_SkKey     },\r
+        { SK_MacLeftKey,    kLeft_SkKey     },\r
+        { SK_MacRightKey,   kRight_SkKey    },\r
+        { SK_MacReturnKey,  kOK_SkKey       },\r
+        { SK_MacDeleteKey,  kBack_SkKey     },\r
+        { SK_MacEndKey,     kEnd_SkKey      },\r
+        { SK_Mac0Key,       k0_SkKey        },\r
+        { SK_Mac1Key,       k1_SkKey        },\r
+        { SK_Mac2Key,       k2_SkKey        },\r
+        { SK_Mac3Key,       k3_SkKey        },\r
+        { SK_Mac4Key,       k4_SkKey        },\r
+        { SK_Mac5Key,       k5_SkKey        },\r
+        { SK_Mac6Key,       k6_SkKey        },\r
+        { SK_Mac7Key,       k7_SkKey        },\r
+        { SK_Mac8Key,       k8_SkKey        },\r
+        { SK_Mac9Key,       k9_SkKey        }\r
+    };\r
+    \r
+    for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)\r
+        if (gKeys[i].fRaw == raw)\r
+            return gKeys[i].fKey;\r
+    return kNONE_SkKey;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////////////\r
+\r
+void SkEvent::SignalNonEmptyQueue()\r
+{\r
+    post_skwinevent();\r
+    //SkDebugf("signal nonempty\n");\r
+}\r
+\r
+static UINT_PTR gTimer;\r
+\r
+VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)\r
+{\r
+    SkEvent::ServiceQueueTimer();\r
+    //SkDebugf("timer task fired\n");\r
+}\r
+\r
+void SkEvent::SignalQueueTimer(SkMSec delay)\r
+{\r
+    if (gTimer)\r
+    {\r
+        KillTimer(NULL, gTimer);\r
+        gTimer = NULL;\r
+    }\r
+    if (delay)\r
+    {     \r
+        gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);\r
+        //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);\r
+    }\r
+}\r
+\r
+\r
+#define USE_MSAA 0\r
+\r
+HGLRC create_gl(HWND hwnd) {\r
+\r
+    HDC dc = GetDC(hwnd);\r
+\r
+    SkWGLExtensions extensions;\r
+    if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {\r
+        return NULL;\r
+    }\r
+\r
+    HDC prevDC = wglGetCurrentDC();\r
+    HGLRC prevGLRC = wglGetCurrentContext();\r
+    PIXELFORMATDESCRIPTOR pfd;\r
+\r
+    int format = 0;\r
+\r
+    GLint iattrs[] = {\r
+        SK_WGL_DRAW_TO_WINDOW, TRUE,\r
+        SK_WGL_DOUBLE_BUFFER, TRUE,\r
+        SK_WGL_ACCELERATION, SK_WGL_FULL_ACCELERATION,\r
+        SK_WGL_SUPPORT_OPENGL, TRUE,\r
+        SK_WGL_COLOR_BITS, 24,\r
+        SK_WGL_ALPHA_BITS, 8,\r
+        SK_WGL_STENCIL_BITS, 8,\r
+\r
+        // these must be kept last\r
+        SK_WGL_SAMPLE_BUFFERS, TRUE,\r
+        SK_WGL_SAMPLES, 0,\r
+        0,0\r
+    };\r
+\r
+    static const int kSampleBuffersValueIdx = SK_ARRAY_COUNT(iattrs) - 5;\r
+    static const int kSamplesValueIdx = SK_ARRAY_COUNT(iattrs) - 3;\r
+    if (USE_MSAA && extensions.hasExtension(dc, "WGL_ARB_multisample")) {\r
+        for (int samples = 16; samples > 1; --samples) {\r
+            \r
+            iattrs[kSamplesValueIdx] = samples;\r
+            GLfloat fattrs[] = {0,0};\r
+            GLuint num;\r
+            int formats[64];\r
+            extensions.choosePixelFormat(dc, iattrs, fattrs, 64, formats, &num);\r
+            num = min(num,64);\r
+            for (GLuint i = 0; i < num; ++i) {\r
+                DescribePixelFormat(dc, formats[i], sizeof(pfd), &pfd);\r
+                if (SetPixelFormat(dc, formats[i], &pfd)) {\r
+                    format = formats[i];\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    if (0 == format) {\r
+        iattrs[kSampleBuffersValueIdx-1] = iattrs[kSampleBuffersValueIdx] = 0;\r
+        iattrs[kSamplesValueIdx-1] = iattrs[kSamplesValueIdx] = 0;\r
+        GLfloat fattrs[] = {0,0};\r
+        GLuint num;\r
+        extensions.choosePixelFormat(dc, iattrs, fattrs, 1, &format, &num);\r
+        DescribePixelFormat(dc, format, sizeof(pfd), &pfd);\r
+        BOOL set = SetPixelFormat(dc, format, &pfd);\r
+        SkASSERT(TRUE == set);\r
+    }\r
+    \r
+    HGLRC glrc = wglCreateContext(dc);\r
+    SkASSERT(glrc);\r
+\r
+    wglMakeCurrent(prevDC, prevGLRC);\r
+    return glrc;\r
+}\r
+\r
+bool SkOSWindow::attachGL() {\r
+    if (NULL == fHGLRC) {\r
+        fHGLRC = create_gl((HWND)fHWND);\r
+        if (NULL == fHGLRC) {\r
+            return false;\r
+        }\r
+        glClearStencil(0);\r
+        glClearColor(0, 0, 0, 0);\r
+        glStencilMask(0xffffffff);\r
+        glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);\r
+    }\r
+    if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {\r
+        glViewport(0, 0, SkScalarRound(this->width()),\r
+                   SkScalarRound(this->height()));\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+void SkOSWindow::detachGL() {\r
+    wglMakeCurrent(GetDC((HWND)fHWND), 0);\r
+    wglDeleteContext((HGLRC)fHGLRC);\r
+    fHGLRC = NULL;\r
+}\r
+\r
+void SkOSWindow::presentGL() {\r
+    glFlush();\r
+    SwapBuffers(GetDC((HWND)fHWND));\r
+}\r
+\r
+#if SK_ANGLE\r
+bool create_ANGLE(EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,\r
+                  EGLContext* eglContext, EGLSurface* eglSurface) {\r
+    EGLint contextAttribs[] = { \r
+        EGL_CONTEXT_CLIENT_VERSION, 2, \r
+        EGL_NONE, EGL_NONE \r
+    };\r
+    EGLint configAttribList[] = {\r
+        EGL_RED_SIZE,       8,\r
+        EGL_GREEN_SIZE,     8,\r
+        EGL_BLUE_SIZE,      8,\r
+        EGL_ALPHA_SIZE,     8,\r
+        EGL_DEPTH_SIZE,     8,\r
+        EGL_STENCIL_SIZE,   8,\r
+        EGL_NONE\r
+    };\r
+    EGLint surfaceAttribList[] = {\r
+        EGL_NONE, EGL_NONE\r
+    };\r
+\r
+    EGLDisplay display = eglGetDisplay(GetDC(hWnd));\r
+    if (display == EGL_NO_DISPLAY ) {\r
+       return false;\r
+    }\r
+\r
+    // Initialize EGL\r
+    EGLint majorVersion, minorVersion;\r
+    if (!eglInitialize(display, &majorVersion, &minorVersion)) {\r
+       return false;\r
+    }\r
+\r
+    EGLint numConfigs;\r
+    if (!eglGetConfigs(display, NULL, 0, &numConfigs)) {\r
+       return false;\r
+    }\r
+\r
+    // Choose config\r
+    EGLConfig config;\r
+    if (!eglChooseConfig(display, configAttribList, \r
+                                &config, 1, &numConfigs)) {\r
+       return false;\r
+    }\r
+\r
+    // Create a surface\r
+    EGLSurface surface = eglCreateWindowSurface(display, config, \r
+                                                (EGLNativeWindowType)hWnd, \r
+                                                surfaceAttribList);\r
+    if (surface == EGL_NO_SURFACE) {\r
+       return false;\r
+    }\r
+\r
+    // Create a GL context\r
+    EGLContext context = eglCreateContext(display, config, \r
+                                          EGL_NO_CONTEXT,\r
+                                          contextAttribs );\r
+    if (context == EGL_NO_CONTEXT ) {\r
+       return false;\r
+    }   \r
+    \r
+    // Make the context current\r
+    if (!eglMakeCurrent(display, surface, surface, context)) {\r
+       return false;\r
+    }\r
+    \r
+    *eglDisplay = display;\r
+    *eglContext = context;\r
+    *eglSurface = surface;\r
+    return true;\r
+}\r
+\r
+bool SkOSWindow::attachANGLE() {\r
+    if (EGL_NO_DISPLAY == fDisplay) {\r
+        bool bResult = create_ANGLE((HWND)fHWND, &fDisplay, &fContext, &fSurface);\r
+        if (false == bResult) {\r
+            return false;\r
+        }\r
+        const GrGLInterface* intf = GrGLCreateANGLEInterface();\r
+\r
+        if (intf) {\r
+            GR_GL_CALL(intf, ClearStencil(0));\r
+            GR_GL_CALL(intf, ClearColor(0, 0, 0, 0));\r
+            GR_GL_CALL(intf, StencilMask(0xffffffff));\r
+            GR_GL_CALL(intf, Clear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT));\r
+        }\r
+    }\r
+    if (eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {\r
+        const GrGLInterface* intf = GrGLCreateANGLEInterface();\r
+\r
+        if (intf ) {\r
+            GR_GL_CALL(intf, Viewport(0, 0, SkScalarRound(this->width()),\r
+                                      SkScalarRound(this->height())));\r
+        }\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+void SkOSWindow::detachANGLE() {\r
+    eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);\r
+\r
+    eglDestroyContext(fDisplay, fContext);\r
+    fContext = EGL_NO_CONTEXT;\r
+\r
+    eglDestroySurface(fDisplay, fSurface);\r
+    fSurface = EGL_NO_SURFACE;\r
+\r
+    eglTerminate(fDisplay);\r
+    fDisplay = EGL_NO_DISPLAY;\r
+}\r
+\r
+void SkOSWindow::presentANGLE() {\r
+    const GrGLInterface* intf = GrGLCreateANGLEInterface();\r
+\r
+    if (intf) {\r
+        GR_GL_CALL(intf, Flush());\r
+    }\r
+\r
+    eglSwapBuffers(fDisplay, fSurface);\r
+}\r
+#endif\r
+\r
+IDirect3DDevice9* create_d3d9_device(HWND hwnd) {\r
+    HRESULT hr;\r
+\r
+    IDirect3D9* d3d9;\r
+    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);\r
+    if (NULL == d3d9) {\r
+        return NULL;\r
+    }\r
+    D3DDEVTYPE devType = D3DDEVTYPE_HAL;\r
+    //D3DDEVTYPE devType = D3DDEVTYPE_REF;\r
+    DWORD qLevels;\r
+    DWORD qLevelsDepth;\r
+    D3DMULTISAMPLE_TYPE type;\r
+    for (type = D3DMULTISAMPLE_16_SAMPLES; \r
+         type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {\r
+        hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, \r
+                                              devType, D3DFMT_D24S8, TRUE,\r
+                                              type, &qLevels);\r
+        qLevels = (hr == D3D_OK) ? qLevels : 0;\r
+        hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, \r
+                                              devType, D3DFMT_A8R8G8B8, TRUE,\r
+                                              type, &qLevelsDepth);\r
+        qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;\r
+        qLevels = min(qLevels,qLevelsDepth);\r
+        if (qLevels > 0) {\r
+            break;\r
+        }\r
+    }\r
+    qLevels = 0;\r
+    IDirect3DDevice9* d3d9Device;\r
+    D3DPRESENT_PARAMETERS pres;\r
+    memset(&pres, 0, sizeof(pres));\r
+    pres.EnableAutoDepthStencil = TRUE;\r
+    pres.AutoDepthStencilFormat = D3DFMT_D24S8;\r
+    pres.BackBufferCount = 2;\r
+    pres.BackBufferFormat = D3DFMT_A8R8G8B8;\r
+    pres.BackBufferHeight = 0;\r
+    pres.BackBufferWidth = 0;\r
+    if (qLevels > 0) {\r
+        pres.MultiSampleType = type;\r
+        pres.MultiSampleQuality = qLevels-1;\r
+    } else {\r
+        pres.MultiSampleType = D3DMULTISAMPLE_NONE;\r
+        pres.MultiSampleQuality = 0;\r
+    }\r
+    pres.SwapEffect = D3DSWAPEFFECT_DISCARD;\r
+    pres.Windowed = TRUE;\r
+    pres.hDeviceWindow = hwnd;\r
+    pres.PresentationInterval = 1;\r
+    pres.Flags = 0;\r
+    hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,\r
+                            devType,\r
+                            hwnd, \r
+                            D3DCREATE_HARDWARE_VERTEXPROCESSING, \r
+                            &pres, \r
+                            &d3d9Device);    \r
+    D3DERR_INVALIDCALL;\r
+    if (SUCCEEDED(hr)) {\r
+        d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);\r
+        return d3d9Device;\r
+    }\r
+    return NULL;\r
+}\r
+\r
+// This needs some improvement. D3D doesn't have the same notion of attach/detach\r
+// as GL. However, just allowing GDI to write to the window after creating the \r
+// D3D device seems to work. \r
+// We need to handle resizing. On XP and earlier Reset() will trash all our textures\r
+// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we\r
+// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing\r
+// everything. Currently we do nothing and the D3D9 image gets stretched/compressed\r
+// when resized.\r
+\r
+bool SkOSWindow::attachD3D9() {\r
+    if (NULL == fD3D9Device) {\r
+        fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);\r
+    }\r
+    if (NULL != fD3D9Device) {\r
+        ((IDirect3DDevice9*)fD3D9Device)->BeginScene();\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+void SkOSWindow::detachD3D9() {\r
+    if (NULL != fD3D9Device) {\r
+        ((IDirect3DDevice9*)fD3D9Device)->EndScene();\r
+    }\r
+}\r
+\r
+void SkOSWindow::presentD3D9() {\r
+    if (NULL != fD3D9Device) {\r
+        HRESULT hr;\r
+        hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();\r
+        SkASSERT(SUCCEEDED(hr));\r
+        hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);\r
+        SkASSERT(SUCCEEDED(hr));\r
+        hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET | \r
+                                                     D3DCLEAR_STENCIL, 0x0, 0, \r
+                                                     0);\r
+        SkASSERT(SUCCEEDED(hr));\r
+        hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();\r
+        SkASSERT(SUCCEEDED(hr));\r
+    }\r
+}\r
+\r
+// return true on success\r
+bool SkOSWindow::attach(SkBackEndTypes attachType) {\r
+\r
+    // attach doubles as "windowResize" so we need to allo\r
+    // already bound states to pass through again\r
+    // TODO: split out the resize functionality\r
+//    SkASSERT(kNone_BackEndType == fAttached);\r
+    bool result = true;\r
+\r
+    switch (attachType) {\r
+    case kNone_BackEndType:\r
+        // nothing to do\r
+        break; \r
+    case kNativeGL_BackEndType:\r
+        result = attachGL();\r
+        break;\r
+#if SK_ANGLE\r
+    case kANGLE_BackEndType:\r
+        result = attachANGLE();\r
+        break;\r
+#endif\r
+    case kD3D9_BackEndType:\r
+        result = attachD3D9();\r
+        break;\r
+    default:\r
+        SkASSERT(false);\r
+        result = false;\r
+        break;\r
+    }\r
+\r
+    if (result) {\r
+        fAttached = attachType;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+void SkOSWindow::detach() {\r
+    switch (fAttached) {\r
+    case kNone_BackEndType:\r
+        // nothing to do\r
+        break; \r
+    case kNativeGL_BackEndType:\r
+        detachGL();\r
+        break;\r
+#if SK_ANGLE\r
+    case kANGLE_BackEndType:\r
+        detachANGLE();\r
+        break;\r
+#endif\r
+    case kD3D9_BackEndType:\r
+        detachD3D9();\r
+        break;\r
+    default:\r
+        SkASSERT(false);\r
+        break;\r
+    }\r
+    fAttached = kNone_BackEndType;\r
+}\r
+\r
+void SkOSWindow::present() {\r
+    switch (fAttached) {\r
+    case kNone_BackEndType:\r
+        // nothing to do\r
+        return; \r
+    case kNativeGL_BackEndType:\r
+        presentGL();\r
+        break;\r
+#if SK_ANGLE\r
+    case kANGLE_BackEndType:\r
+        presentANGLE();\r
+        break;\r
+#endif\r
+    case kD3D9_BackEndType:\r
+        presentD3D9();\r
+        break;\r
+    default:\r
+        SkASSERT(false);\r
+        break;\r
+    }\r
+}\r
+\r
+#endif\r