diff options
-rw-r--r-- | include/views/SkOSWindow_Android.h | 12 | ||||
-rw-r--r-- | include/views/SkOSWindow_Mac.h | 12 | ||||
-rw-r--r-- | include/views/SkOSWindow_Unix.h | 12 | ||||
-rw-r--r-- | include/views/SkOSWindow_Win.h | 38 | ||||
-rwxr-xr-x | include/views/SkOSWindow_iOS.h | 12 | ||||
-rw-r--r-- | samplecode/SampleApp.cpp | 319 | ||||
-rw-r--r-- | samplecode/SampleApp.h | 16 | ||||
-rw-r--r-- | src/views/mac/SkOSWindow_Mac.cpp | 6 | ||||
-rw-r--r-- | src/views/unix/SkOSWindow_Unix.cpp | 6 | ||||
-rw-r--r-- | src/views/win/SkOSWindow_win.cpp | 1346 |
10 files changed, 963 insertions, 816 deletions
diff --git a/include/views/SkOSWindow_Android.h b/include/views/SkOSWindow_Android.h index bdce5d0d4f..5818a0af69 100644 --- a/include/views/SkOSWindow_Android.h +++ b/include/views/SkOSWindow_Android.h @@ -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[]); diff --git a/include/views/SkOSWindow_Mac.h b/include/views/SkOSWindow_Mac.h index b09f1dd5e4..01fa29f334 100644 --- a/include/views/SkOSWindow_Mac.h +++ b/include/views/SkOSWindow_Mac.h @@ -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 diff --git a/include/views/SkOSWindow_Unix.h b/include/views/SkOSWindow_Unix.h index 3b71af8330..40059bf8d4 100644 --- a/include/views/SkOSWindow_Unix.h +++ b/include/views/SkOSWindow_Unix.h @@ -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); diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h index c857e7a6cd..2663c8c75d 100644 --- a/include/views/SkOSWindow_Win.h +++ b/include/views/SkOSWindow_Win.h @@ -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; }; diff --git a/include/views/SkOSWindow_iOS.h b/include/views/SkOSWindow_iOS.h index ff284843bb..34ce421778 100755 --- a/include/views/SkOSWindow_iOS.h +++ b/include/views/SkOSWindow_iOS.h @@ -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 diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index dc522b603a..92c9e6c984 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -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: " }; diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h index 94f663feb0..ba404da515 100644 --- a/samplecode/SampleApp.h +++ b/samplecode/SampleApp.h @@ -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); diff --git a/src/views/mac/SkOSWindow_Mac.cpp b/src/views/mac/SkOSWindow_Mac.cpp index d41c9a75de..63106f088d 100644 --- a/src/views/mac/SkOSWindow_Mac.cpp +++ b/src/views/mac/SkOSWindow_Mac.cpp @@ -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); } diff --git a/src/views/unix/SkOSWindow_Unix.cpp b/src/views/unix/SkOSWindow_Unix.cpp index b4b0f17cd6..01bc21c89e 100644 --- a/src/views/unix/SkOSWindow_Unix.cpp +++ b/src/views/unix/SkOSWindow_Unix.cpp @@ -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); diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp index 75f6de65c7..d3e49c9171 100644 --- a/src/views/win/SkOSWindow_win.cpp +++ b/src/views/win/SkOSWindow_win.cpp @@ -1,622 +1,724 @@ - -/* - * 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 - +
+/*
+ * 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)
+ , fD3D9Device(NULL)
+ , fAttached(kNone_BackEndType) {
+ gEventTarget = (HWND)hWnd;
+}
+
+SkOSWindow::~SkOSWindow() {
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->Release();
+ }
+ if (NULL != fHGLRC) {
+ wglDeleteContext((HGLRC)fHGLRC);
+ }
+#if SK_ANGLE
+ if (EGL_NO_CONTEXT != fContext) {
+ eglDestroyContext(fDisplay, fContext);
+ fContext = EGL_NO_CONTEXT;
+ }
+
+ if (EGL_NO_SURFACE != fSurface) {
+ eglDestroySurface(fDisplay, fSurface);
+ fSurface = EGL_NO_SURFACE;
+ }
+
+ if (EGL_NO_DISPLAY != fDisplay) {
+ eglTerminate(fDisplay);
+ fDisplay = EGL_NO_DISPLAY;
+ }
+#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 (kNone_BackEndType == fAttached)
+ {
+ 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()));
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachGL() {
+ wglMakeCurrent(GetDC((HWND)fHWND), 0);
+ wglDeleteContext((HGLRC)fHGLRC);
+ fHGLRC = NULL;
+}
+
+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())));
+ }
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachANGLE() {
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
+
+ eglDestroyContext(fDisplay, fContext);
+ fContext = EGL_NO_CONTEXT;
+
+ eglDestroySurface(fDisplay, fSurface);
+ fSurface = EGL_NO_SURFACE;
+
+ eglTerminate(fDisplay);
+ fDisplay = EGL_NO_DISPLAY;
+}
+
+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();
+ return true;
+ }
+ return false;
+}
+
+void SkOSWindow::detachD3D9() {
+ if (NULL != fD3D9Device) {
+ ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+ }
+}
+
+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));
+ }
+}
+
+// return true on success
+bool SkOSWindow::attach(SkBackEndTypes attachType) {
+
+ // attach doubles as "windowResize" so we need to allo
+ // already bound states to pass through again
+ // TODO: split out the resize functionality
+// SkASSERT(kNone_BackEndType == fAttached);
+ bool result = true;
+
+ switch (attachType) {
+ case kNone_BackEndType:
+ // nothing to do
+ break;
+ case kNativeGL_BackEndType:
+ result = attachGL();
+ break;
+#if SK_ANGLE
+ case kANGLE_BackEndType:
+ result = attachANGLE();
+ break;
+#endif
+ case kD3D9_BackEndType:
+ result = attachD3D9();
+ break;
+ default:
+ SkASSERT(false);
+ result = false;
+ break;
+ }
+
+ if (result) {
+ fAttached = attachType;
+ }
+
+ return result;
+}
+
+void SkOSWindow::detach() {
+ switch (fAttached) {
+ case kNone_BackEndType:
+ // nothing to do
+ break;
+ case kNativeGL_BackEndType:
+ detachGL();
+ break;
+#if SK_ANGLE
+ case kANGLE_BackEndType:
+ detachANGLE();
+ break;
+#endif
+ case kD3D9_BackEndType:
+ detachD3D9();
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
+ fAttached = kNone_BackEndType;
+}
+
+void SkOSWindow::present() {
+ switch (fAttached) {
+ case kNone_BackEndType:
+ // nothing to do
+ return;
+ case kNativeGL_BackEndType:
+ presentGL();
+ break;
+#if SK_ANGLE
+ case kANGLE_BackEndType:
+ presentANGLE();
+ break;
+#endif
+ case kD3D9_BackEndType:
+ presentD3D9();
+ break;
+ default:
+ SkASSERT(false);
+ break;
+ }
+}
+
+#endif
|