diff options
-rw-r--r-- | include/views/SkOSWindow_Win.h | 38 | ||||
-rw-r--r-- | samplecode/SampleApp.cpp | 319 | ||||
-rw-r--r-- | samplecode/SampleApp.h | 16 | ||||
-rw-r--r-- | src/views/win/SkOSWindow_win.cpp | 1318 |
4 files changed, 784 insertions, 907 deletions
diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h index 0592818ad0..c17807a2d9 100644 --- a/include/views/SkOSWindow_Win.h +++ b/include/views/SkOSWindow_Win.h @@ -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; }; diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 92c9e6c984..dc522b603a 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -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: " }; diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h index ba404da515..94f663feb0 100644 --- a/samplecode/SampleApp.h +++ b/samplecode/SampleApp.h @@ -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); diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp index 6921219504..bf59e76715 100644 --- a/src/views/win/SkOSWindow_win.cpp +++ b/src/views/win/SkOSWindow_win.cpp @@ -1,710 +1,608 @@ -
-/*
- * 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)
- , 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) {
- angle::eglDestroyContext(fDisplay, fContext);
- fContext = EGL_NO_CONTEXT;
- }
-
- if (EGL_NO_SURFACE != fSurface) {
- angle::eglDestroySurface(fDisplay, fSurface);
- fSurface = EGL_NO_SURFACE;
- }
-
- if (EGL_NO_DISPLAY != fDisplay) {
- angle::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, 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()));
- return true;
- }
- return false;
-}
-
-void SkOSWindow::detachANGLE() {
- angle::eglMakeCurrent(fDisplay, EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT);
-
- angle::eglDestroyContext(fDisplay, fContext);
- fContext = EGL_NO_CONTEXT;
-
- angle::eglDestroySurface(fDisplay, fSurface);
- fSurface = EGL_NO_SURFACE;
-
- angle::eglTerminate(fDisplay);
- fDisplay = EGL_NO_DISPLAY;
-}
-
-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();
- 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
-
+ +/* + * 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 + |