Reverting r3555
authorrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 30 Mar 2012 15:18:14 +0000 (15:18 +0000)
committerrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 30 Mar 2012 15:18:14 +0000 (15:18 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@3556 2bbb7eff-a529-9590-31e7-b0007b416f81

include/views/SkOSWindow_Win.h
samplecode/SampleApp.cpp
samplecode/SampleApp.h
src/views/win/SkOSWindow_win.cpp

index 0592818..c17807a 100644 (file)
@@ -26,19 +26,20 @@ 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
-        kANGLE_BackEndType,
+    bool attachANGLE();
+    void detachANGLE();
+    void presentANGLE();
 #endif
-        kD3D9_BackEndType
-    };
 
-    bool attach(SkBackEndTypes attachType);
-    void detach();
-    void present();
+    bool attachD3D9();
+    void detachD3D9();
+    void presentD3D9();
 
     void* d3d9Device() { return fD3D9Device; }
 
@@ -72,26 +73,13 @@ private:
     angle::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 92c9e6c..dc522b6 100644 (file)
@@ -53,12 +53,7 @@ SkTDArray<char> gTempDataStore;
 #endif
 
 #define USE_ARROWS_FOR_ZOOM true
-
-#if SK_ANGLE
-//#define DEFAULT_TO_ANGLE 1
-#else
-//#define DEFAULT_TO_GPU 1
-#endif
+//#define DEFAULT_TO_GPU
 
 extern SkView* create_overview(int, const SkViewFactory*[]);
 extern bool is_overview(SkView* view);
@@ -136,129 +131,113 @@ class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
 public:
 
     DefaultDeviceManager()
-        : fCurContext(NULL)
-        , fCurIntf(NULL)
-        , fCurRenderTarget(NULL)
-        , fBackend(kNone_BackEndType) {
+#if SK_ANGLE
+    : fUseAltContext(false) 
+#endif
+    {
+        fGrRenderTarget = NULL;
+        fGrContext = NULL;
+        fGL = NULL;
+        fNullGrContext = NULL;
+        fNullGrRenderTarget = NULL;
     }
 
     virtual ~DefaultDeviceManager() {
-        SkSafeUnref(fCurContext);
-        SkSafeUnref(fCurIntf);
-        SkSafeUnref(fCurRenderTarget);
+        SkSafeUnref(fGrRenderTarget);
+        SkSafeUnref(fGrContext);
+        SkSafeUnref(fGL);
+        SkSafeUnref(fNullGrContext);
+        SkSafeUnref(fNullGrRenderTarget);
     }
 
-    virtual void setUpBackend(SampleWindow* win) {
-        SkASSERT(kNone_BackEndType == fBackend);
-
-        fBackend = kNone_BackEndType;
+    virtual void init(SampleWindow* win, bool useAltContext) {
+#if SK_ANGLE
+        fUseAltContext = useAltContext;
+#endif
+        bool result;
 
-        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
-            case kANGLE_DeviceType:
-                // ANGLE is really the only odd man out
-                fBackend = kANGLE_BackEndType;
-                break;
+        if (useAltContext) {
+            result = win->attachANGLE();
+        } else 
 #endif
-            default:
-                SkASSERT(false);
-                break;
+        {
+            result = win->attachGL();
         }
-
-        bool result = win->attach(fBackend);
         if (!result) {
             SkDebugf("Failed to initialize GL");
-            return;
         }
-
-        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 (NULL == fGL) {
 #if SK_ANGLE
-            case kANGLE_DeviceType:
-                fCurIntf = GrGLCreateANGLEInterface();
-                break;
+            if (useAltContext) {
+                fGL = GrGLCreateANGLEInterface();
+            } else 
 #endif
-            case kNullGPU_DeviceType:
-                fCurIntf = GrGLCreateNullInterface();
-                break;
-            default:
-                SkASSERT(false);
-                break;
+            {
+                fGL = GrGLCreateNativeInterface();
+            }
+            GrAssert(NULL == fGrContext);
+            fGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine,
+                                           (GrPlatform3DContext) 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);
+        if (NULL == fGrContext || NULL == fGL) {
+            SkSafeUnref(fGrContext);
+            SkSafeUnref(fGL);
             SkDebugf("Failed to setup 3D");
-
-            win->detach();
+#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();
         }
-
-        // call windowSizeChanged to create the render target
-        windowSizeChanged(win);
     }
 
-    virtual void tearDownBackend(SampleWindow *win) {
-        win->detach();
-        fBackend = kNone_BackEndType;
-
-        SkSafeUnref(fCurContext);
-        fCurContext = NULL;
-
-        SkSafeUnref(fCurIntf);
-        fCurIntf = NULL;
-
-        SkSafeUnref(fCurRenderTarget);
-        fCurRenderTarget = NULL;
+    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 bool prepareCanvas(SampleWindow::DeviceType dType,
                                SkCanvas* canvas,
                                SampleWindow* win) {
         switch (dType) {
-            case kRaster_DeviceType:
-                // fallthrough
-            case kPicture_DeviceType:
-                // fallthrough
-#if SK_ANGLE
-            case kANGLE_DeviceType:
-#endif
-                break;
             case kGPU_DeviceType:
+                if (fGrContext) {
+                    canvas->setDevice(new SkGpuDevice(fGrContext,
+                                                    fGrRenderTarget))->unref();
+                } else {
+                    return false;
+                }
+                break;
             case kNullGPU_DeviceType:
-                if (fCurContext) {
-                    canvas->setDevice(new SkGpuDevice(fCurContext,
-                                                    fCurRenderTarget))->unref();
+                if (fNullGrContext) {
+                    canvas->setDevice(new SkGpuDevice(fNullGrContext,
+                                                      fNullGrRenderTarget))->unref();
                 } else {
                     return false;
                 }
                 break;
-            default:
-                SkASSERT(false);
-                return false;
+            case kRaster_DeviceType:
+            case kPicture_DeviceType:
+                break;
         }
         return true;
     }
@@ -266,55 +245,85 @@ public:
     virtual void publishCanvas(SampleWindow::DeviceType dType,
                                SkCanvas* canvas,
                                SampleWindow* win) {
-        if (fCurContext) {
+        if (fGrContext) {
             // in case we have queued drawing calls
-            fCurContext->flush();
-
-            if (kGPU_DeviceType != dType && kNullGPU_DeviceType != dType) {
+            fGrContext->flush();
+            if (NULL != fNullGrContext) {
+                fNullGrContext->flush();
+            }
+            if (dType != kGPU_DeviceType &&
+                dType != kNullGPU_DeviceType) {
                 // need to send the raster bits to the (gpu) window
-                fCurContext->setRenderTarget(fCurRenderTarget);
+                fGrContext->setRenderTarget(fGrRenderTarget);
                 const SkBitmap& bm = win->getBitmap();
-                fCurRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
+                fGrRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
                                              kSkia8888_PM_GrPixelConfig,
                                              bm.getPixels(),
                                              bm.rowBytes());
             }
         }
-
-        win->present();
+#if SK_ANGLE
+        if (fUseAltContext) {
+            win->presentANGLE();
+        } else 
+#endif
+        {
+            win->presentGL();
+        }
     }
 
     virtual void windowSizeChanged(SampleWindow* win) {
-
-        if (fCurContext) {
-            win->attach(fBackend);
+        if (fGrContext) {
+#if SK_ANGLE
+            if (fUseAltContext) {
+                win->attachANGLE();
+            } else 
+#endif
+            {
+                win->attachGL();
+            }
 
             GrPlatformRenderTargetDesc desc;
             desc.fWidth = SkScalarRound(win->width());
             desc.fHeight = SkScalarRound(win->height());
             desc.fConfig = kSkia8888_PM_GrPixelConfig;
-            GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt);
-            GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits);
+            GR_GL_GetIntegerv(fGL, GR_GL_SAMPLES, &desc.fSampleCnt);
+            GR_GL_GetIntegerv(fGL, GR_GL_STENCIL_BITS, &desc.fStencilBits);
             GrGLint buffer;
-            GR_GL_GetIntegerv(fCurIntf, GR_GL_FRAMEBUFFER_BINDING, &buffer);
+            GR_GL_GetIntegerv(fGL, GR_GL_FRAMEBUFFER_BINDING, &buffer);
             desc.fRenderTargetHandle = buffer;
 
-            SkSafeUnref(fCurRenderTarget);
-            fCurRenderTarget = fCurContext->createPlatformRenderTarget(desc);
+            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);
         }
     }
 
-    virtual GrContext* getGrContext() {
-        return fCurContext;
+    virtual GrContext* getGrContext(SampleWindow::DeviceType dType) {
+        if (kNullGPU_DeviceType == dType) {
+            return fNullGrContext;
+        } else {
+            return fGrContext;
+        }
     }
 private:
-    GrContext*              fCurContext;
-    const GrGLInterface*    fCurIntf;
-    GrRenderTarget*         fCurRenderTarget;
-
-    SkOSWindow::SkBackEndTypes fBackend;
-
-    typedef SampleWindow::DeviceManager INHERITED;
+#if SK_ANGLE
+    bool fUseAltContext;
+#endif
+    GrContext* fGrContext;
+    const GrGLInterface* fGL;
+    GrRenderTarget* fGrRenderTarget;
+    GrContext* fNullGrContext;
+    GrRenderTarget* fNullGrRenderTarget;
 };
 
 ///////////////
@@ -635,9 +644,6 @@ 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
     };
@@ -663,6 +669,7 @@ 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;
@@ -681,6 +688,12 @@ 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);
         }
@@ -707,15 +720,11 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
      
     fPicture = NULL;
     
-    fDeviceType = kRaster_DeviceType;
-
-#if DEFAULT_TO_GPU
+#ifdef DEFAULT_TO_GPU
     fDeviceType = kGPU_DeviceType;
+#else
+    fDeviceType = kRaster_DeviceType;
 #endif
-#if SK_ANGLE && DEFAULT_TO_ANGLE
-    fDeviceType = kANGLE_DeviceType;
-#endif
-
     fUseClip = false;
     fNClip = false;
     fAnimating = false;
@@ -755,11 +764,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
     int itemID;
     
     itemID =fAppMenu.appendList("Device Type", "Device Type", sinkID, 0, 
-                                "Raster", "Picture", "OpenGL", 
-#if SK_ANGLE
-                                "ANGLE",
-#endif
-                                NULL);
+                                "Raster", "Picture", "OpenGL", NULL);
     fAppMenu.assignKeyEquivalentToItem(itemID, 'd');
     itemID = fAppMenu.appendTriState("AA", "AA", sinkID, fAAState);
     fAppMenu.assignKeyEquivalentToItem(itemID, 'b');
@@ -820,7 +825,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
         devManager->ref();
         fDevManager = devManager;
     }
-    fDevManager->setUpBackend(this);
+    fDevManager->init(this, useAltContext);
 
     // If another constructor set our dimensions, ensure that our
     // onSizeChange gets called.
@@ -1128,12 +1133,7 @@ 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,9 +1142,6 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
                 break;
             case kNullGPU_DeviceType:
                 break;
-            default:
-                SkASSERT(false);
-                break;
         }
     }
 
@@ -1631,9 +1628,11 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
             this->updateTitle();
             return true;
         case '\\':
-            this->setDeviceType(kNullGPU_DeviceType);
-            this->inval(NULL);
-            this->updateTitle();
+            if (fDevManager->supportsDeviceType(kNullGPU_DeviceType)) {
+                fDeviceType=  kNullGPU_DeviceType;
+                this->inval(NULL);
+                this->updateTitle();
+            }
             return true;
         case 'p':
             {
@@ -1664,15 +1663,8 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
 }
 
 void SampleWindow::setDeviceType(DeviceType type) {
-    if (type == fDeviceType)
-        return;
-
-    fDevManager->tearDownBackend(this);
-
-    fDeviceType = type;
-
-    fDevManager->setUpBackend(this);
-
+    if (type != fDeviceType && fDevManager->supportsDeviceType(fDeviceType))
+        fDeviceType = type;
     this->updateTitle();
     this->inval(NULL);
 }
@@ -1684,7 +1676,11 @@ void SampleWindow::toggleSlideshow() {
 }
 
 void SampleWindow::toggleRendering() {
-    this->setDeviceType(cycle_devicetype(fDeviceType));
+    DeviceType origDevType = fDeviceType;
+    do {
+        fDeviceType = cycle_devicetype(fDeviceType);
+    } while (origDevType != fDeviceType &&
+             !fDevManager->supportsDeviceType(fDeviceType));
     this->updateTitle();
     this->inval(NULL);
 }
@@ -1861,9 +1857,6 @@ static const char* gDeviceTypePrefix[] = {
     "raster: ",
     "picture: ",
     "opengl: ",
-#if SK_ANGLE
-    "angle: ",
-#endif
     "null-gl: "
 };
 
index ba404da..94f663f 100644 (file)
@@ -36,9 +36,6 @@ public:
         kRaster_DeviceType,
         kPicture_DeviceType,
         kGPU_DeviceType,
-#if SK_ANGLE
-        kANGLE_DeviceType,
-#endif
         kNullGPU_DeviceType
     };
     /**
@@ -50,9 +47,12 @@ public:
      */
     class DeviceManager : public SkRefCnt {
     public:
-        virtual void setUpBackend(SampleWindow* win) = 0;
+        // called at end of SampleWindow cons
+        virtual void init(SampleWindow* win, bool useAltContext) = 0;
 
-        virtual void tearDownBackend(SampleWindow* win) = 0;
+        // called when selecting a new device type
+        // can disallow a device type by returning false.
+        virtual bool supportsDeviceType(DeviceType dType) = 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() = 0;
+        virtual GrContext* getGrContext(DeviceType dType) = 0;
     };
 
     SampleWindow(void* hwnd, int argc, char** argv, DeviceManager*);
@@ -85,7 +85,7 @@ public:
     void toggleFPS();
     void showOverview();
 
-    GrContext* getGrContext() const { return fDevManager->getGrContext(); }
+    GrContext* getGrContext() const { return fDevManager->getGrContext(fDeviceType); }
 
     void setZoomCenter(float x, float y);
     void changeZoomLevel(float delta);
@@ -100,8 +100,6 @@ public:
     SkData* getPDFData() { return fPDFData; }
     void postInvalDelay();
 
-    DeviceType getDeviceType() const { return fDeviceType; }
-
 protected:
     virtual void onDraw(SkCanvas* canvas);
     virtual bool onHandleKey(SkKey key);
index 6921219..bf59e76 100644 (file)
-\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 "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
-        angle::eglDestroyContext(fDisplay, fContext);\r
-        fContext = EGL_NO_CONTEXT;\r
-    }\r
-\r
-    if (EGL_NO_SURFACE != fSurface) {\r
-        angle::eglDestroySurface(fDisplay, fSurface);\r
-        fSurface = EGL_NO_SURFACE;\r
-    }\r
-\r
-    if (EGL_NO_DISPLAY != fDisplay) {\r
-        angle::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, angle::EGLDisplay* eglDisplay,\r
-                  angle::EGLContext* eglContext, angle::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
-    angle::EGLDisplay display = angle::eglGetDisplay(GetDC(hWnd));\r
-    if (display == EGL_NO_DISPLAY ) {\r
-       return false;\r
-    }\r
-\r
-    // Initialize EGL\r
-    EGLint majorVersion, minorVersion;\r
-    if (!angle::eglInitialize(display, &majorVersion, &minorVersion)) {\r
-       return false;\r
-    }\r
-\r
-    EGLint numConfigs;\r
-    if (!angle::eglGetConfigs(display, NULL, 0, &numConfigs)) {\r
-       return false;\r
-    }\r
-\r
-    // Choose config\r
-    angle::EGLConfig config;\r
-    if (!angle::eglChooseConfig(display, configAttribList, \r
-                                &config, 1, &numConfigs)) {\r
-       return false;\r
-    }\r
-\r
-    // Create a surface\r
-    angle::EGLSurface surface = angle::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
-    angle::EGLContext context = angle::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 (!angle::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
-        angle::glClearStencil(0);\r
-        angle::glClearColor(0, 0, 0, 0);\r
-        angle::glStencilMask(0xffffffff);\r
-        angle::glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);\r
-    }\r
-    if (angle::eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {\r
-        angle::glViewport(0, 0, SkScalarRound(this->width()),\r
-                   SkScalarRound(this->height()));\r
-        return true;\r
-    }\r
-    return false;\r
-}\r
-\r
-void SkOSWindow::detachANGLE() {\r
-    angle::eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);\r
-\r
-    angle::eglDestroyContext(fDisplay, fContext);\r
-    fContext = EGL_NO_CONTEXT;\r
-\r
-    angle::eglDestroySurface(fDisplay, fSurface);\r
-    fSurface = EGL_NO_SURFACE;\r
-\r
-    angle::eglTerminate(fDisplay);\r
-    fDisplay = EGL_NO_DISPLAY;\r
-}\r
-\r
-void SkOSWindow::presentANGLE() {\r
-    angle::glFlush();\r
-    angle::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
-\r
+
+/*
+ * 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 "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) {
+        angle::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, angle::EGLDisplay* eglDisplay,
+                  angle::EGLContext* eglContext, angle::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
+    };
+
+    angle::EGLDisplay display = angle::eglGetDisplay(GetDC(hWnd));
+    if (display == EGL_NO_DISPLAY ) {
+       return false;
+    }
+
+    // Initialize EGL
+    EGLint majorVersion, minorVersion;
+    if (!angle::eglInitialize(display, &majorVersion, &minorVersion)) {
+       return false;
+    }
+
+    EGLint numConfigs;
+    if (!angle::eglGetConfigs(display, NULL, 0, &numConfigs)) {
+       return false;
+    }
+
+    // Choose config
+    angle::EGLConfig config;
+    if (!angle::eglChooseConfig(display, configAttribList, 
+                                &config, 1, &numConfigs)) {
+       return false;
+    }
+
+    // Create a surface
+    angle::EGLSurface surface = angle::eglCreateWindowSurface(display, config, 
+                                                        (EGLNativeWindowType)hWnd, 
+                                                        surfaceAttribList);
+    if (surface == EGL_NO_SURFACE) {
+       return false;
+    }
+
+    // Create a GL context
+    angle::EGLContext context = angle::eglCreateContext(display, config, 
+                                                        EGL_NO_CONTEXT,
+                                                        contextAttribs );
+    if (context == EGL_NO_CONTEXT ) {
+       return false;
+    }   
+    
+    // Make the context current
+    if (!angle::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;
+        }
+        angle::glClearStencil(0);
+        angle::glClearColor(0, 0, 0, 0);
+        angle::glStencilMask(0xffffffff);
+        angle::glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    }
+    if (angle::eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+        angle::glViewport(0, 0, SkScalarRound(this->width()),
+                   SkScalarRound(this->height()));
+        fGLAttached = true;
+        return true;
+    }
+    return false;
+}
+
+void SkOSWindow::detachANGLE() {
+    angle::eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
+    fGLAttached = false;
+}
+
+void SkOSWindow::presentANGLE() {
+    angle::glFlush();
+    angle::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
+