diff options
Diffstat (limited to 'src/views/win/SkOSWindow_win.cpp')
-rw-r--r-- | src/views/win/SkOSWindow_win.cpp | 726 |
1 files changed, 0 insertions, 726 deletions
diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp deleted file mode 100644 index 8788b10ef4..0000000000 --- a/src/views/win/SkOSWindow_win.cpp +++ /dev/null @@ -1,726 +0,0 @@ -/* - * 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 "SkLeanWindows.h" - -#include <GL/gl.h> -#include <WindowsX.h> -#include "win/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/GrGLAssembleInterface.h" -#include "gl/GrGLInterface.h" -#include "GLES2/gl2.h" -#include <EGL/egl.h> -#include <EGL/eglext.h> -#endif // SK_ANGLE - -const int kDefaultWindowWidth = 1024; -const int kDefaultWindowHeight = 768; - -#define GL_CALL(IFACE, X) \ - SkASSERT(IFACE); \ - do { \ - (IFACE)->fFunctions.f##X; \ - } while (false) - -#define WM_EVENT_CALLBACK (WM_USER+0) - -void post_skwinevent(HWND hwnd) -{ - PostMessage(hwnd, WM_EVENT_CALLBACK, 0, 0); -} - -SkTHashMap<void*, SkOSWindow*> SkOSWindow::gHwndToOSWindowMap; - -SkOSWindow::SkOSWindow(const void* winInit) { - this->init(winInit, kDefaultWindowWidth, kDefaultWindowHeight); -} - -SkOSWindow::SkOSWindow(const void* winInit, int w, int h) { - this->init(winInit, w, h); -} - -void SkOSWindow::init(const void* winInit, int w, int h) { - fWinInit = *(const WindowInit*)winInit; - - fHWND = CreateWindow(fWinInit.fClass, NULL, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, 0, w, h, NULL, NULL, - fWinInit.fInstance, NULL); - gHwndToOSWindowMap.set(fHWND, this); -#if SK_SUPPORT_GPU -#if SK_ANGLE - fDisplay = EGL_NO_DISPLAY; - fContext = EGL_NO_CONTEXT; - fSurface = EGL_NO_SURFACE; -#endif - - fHGLRC = NULL; -#endif - fAttached = kNone_BackEndType; - fFullscreen = false; -} - -SkOSWindow::~SkOSWindow() { -#if SK_SUPPORT_GPU - if (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 // SK_ANGLE -#endif // SK_SUPPORT_GPU - this->closeWindow(); -} - -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; -} - -static unsigned getModifiers(UINT message) { - return 0; // TODO -} - -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((SkUnichar) wParam); - return true; - case WM_CHAR: { - const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam); - this->handleChar(SkUTF16_NextUnichar(&c)); - return true; - } break; - case WM_SIZE: { - INT width = LOWORD(lParam); - INT height = HIWORD(lParam); - this->resize(width, height); - break; - } - case WM_PAINT: { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hWnd, &ps); - this->doPaint(hdc); - EndPaint(hWnd, &ps); - return true; - } break; - - case WM_LBUTTONDOWN: - this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), - Click::kDown_State, NULL, getModifiers(message)); - return true; - - case WM_MOUSEMOVE: - this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), - Click::kMoved_State, NULL, getModifiers(message)); - return true; - - case WM_LBUTTONUP: - this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), - Click::kUp_State, NULL, getModifiers(message)); - return true; - - case WM_EVENT_CALLBACK: - if (SkEvent::ProcessEvent()) { - post_skwinevent(hWnd); - } - 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()); - int ret = SetDIBitsToDevice(hdc, - 0, 0, - bitmap.width(), bitmap.height(), - 0, 0, - 0, bitmap.height(), - bitmap.getPixels(), - &bmi, - DIB_RGB_COLORS); - (void)ret; // we're ignoring potential failures for now. - } -} - -void SkOSWindow::updateSize() -{ - RECT r; - GetWindowRect((HWND)fHWND, &r); - this->resize(r.right - r.left, r.bottom - r.top); -} - -void SkOSWindow::onHandleInval(const SkIRect& r) { - RECT rect; - rect.left = r.fLeft; - rect.top = r.fTop; - rect.right = r.fRight; - rect.bottom = r.fBottom; - InvalidateRect((HWND)fHWND, &rect, FALSE); -} - -void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) -{ -} - -void SkOSWindow::onSetTitle(const char title[]){ - SetWindowTextA((HWND)fHWND, title); -} - -/////////////////////////////////////////////////////////////////////////////////////// - -void SkEvent::SignalNonEmptyQueue() -{ - SkOSWindow::ForAllWindows([](void* hWND, SkOSWindow**) { - post_skwinevent((HWND)hWND); - }); -} - -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); - } -} - -#if SK_SUPPORT_GPU - -bool SkOSWindow::attachGL(int msaaSampleCount, bool deepColor, AttachmentInfo* info) { - HDC dc = GetDC((HWND)fHWND); - if (NULL == fHGLRC) { - fHGLRC = SkCreateWGLContext(dc, msaaSampleCount, deepColor, - kGLPreferCompatibilityProfile_SkWGLContextRequest); - 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(dc, (HGLRC)fHGLRC)) { - // use DescribePixelFormat to get the stencil and color bit depth. - int pixelFormat = GetPixelFormat(dc); - PIXELFORMATDESCRIPTOR pfd; - DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd); - info->fStencilBits = pfd.cStencilBits; - // pfd.cColorBits includes alpha, so it will be 32 in 8/8/8/8 and 10/10/10/2 - info->fColorBits = pfd.cRedBits + pfd.cGreenBits + pfd.cBlueBits; - - // Get sample count if the MSAA WGL extension is present - SkWGLExtensions extensions; - if (extensions.hasExtension(dc, "WGL_ARB_multisample")) { - static const int kSampleCountAttr = SK_WGL_SAMPLES; - extensions.getPixelFormatAttribiv(dc, - pixelFormat, - 0, - 1, - &kSampleCountAttr, - &info->fSampleCount); - } else { - info->fSampleCount = 0; - } - - glViewport(0, 0, - SkScalarRoundToInt(this->width()), - SkScalarRoundToInt(this->height())); - return true; - } - return false; -} - -void SkOSWindow::detachGL() { - wglMakeCurrent(GetDC((HWND)fHWND), 0); - wglDeleteContext((HGLRC)fHGLRC); - fHGLRC = NULL; -} - -void SkOSWindow::presentGL() { - HDC dc = GetDC((HWND)fHWND); - SwapBuffers(dc); - ReleaseDC((HWND)fHWND, dc); -} - -#if SK_ANGLE - -static void* get_angle_egl_display(void* nativeDisplay) { - PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; - eglGetPlatformDisplayEXT = - (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); - - // We expect ANGLE to support this extension - if (!eglGetPlatformDisplayEXT) { - return EGL_NO_DISPLAY; - } - - EGLDisplay display = EGL_NO_DISPLAY; - // Try for an ANGLE D3D11 context, fall back to D3D9, and finally GL. - EGLint attribs[3][3] = { - { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_NONE - }, - { - EGL_PLATFORM_ANGLE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, - EGL_NONE - }, - }; - for (int i = 0; i < 3 && display == EGL_NO_DISPLAY; ++i) { - display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,nativeDisplay, attribs[i]); - } - return display; -} - -struct ANGLEAssembleContext { - ANGLEAssembleContext() { - fEGL = GetModuleHandle("libEGL.dll"); - fGL = GetModuleHandle("libGLESv2.dll"); - } - - bool isValid() const { return SkToBool(fEGL) && SkToBool(fGL); } - - HMODULE fEGL; - HMODULE fGL; -}; - -static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) { - const ANGLEAssembleContext& context = *reinterpret_cast<const ANGLEAssembleContext*>(ctx); - GrGLFuncPtr proc = (GrGLFuncPtr) GetProcAddress(context.fGL, name); - if (proc) { - return proc; - } - proc = (GrGLFuncPtr) GetProcAddress(context.fEGL, name); - if (proc) { - return proc; - } - return eglGetProcAddress(name); -} - -static const GrGLInterface* get_angle_gl_interface() { - ANGLEAssembleContext context; - if (!context.isValid()) { - return nullptr; - } - return GrGLAssembleGLESInterface(&context, angle_get_gl_proc); -} - -bool create_ANGLE(EGLNativeWindowType hWnd, - int msaaSampleCount, - EGLDisplay* eglDisplay, - EGLContext* eglContext, - EGLSurface* eglSurface, - EGLConfig* eglConfig) { - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE, EGL_NONE - }; - static const 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 - }; - static const EGLint surfaceAttribList[] = { - EGL_NONE, EGL_NONE - }; - - EGLDisplay display = get_angle_egl_display(GetDC(hWnd)); - - if (EGL_NO_DISPLAY == display) { - SkDebugf("Could not create ANGLE egl display!\n"); - 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 - bool foundConfig = false; - if (msaaSampleCount) { - static const int kConfigAttribListCnt = - SK_ARRAY_COUNT(configAttribList); - EGLint msaaConfigAttribList[kConfigAttribListCnt + 4]; - memcpy(msaaConfigAttribList, - configAttribList, - sizeof(configAttribList)); - SkASSERT(EGL_NONE == msaaConfigAttribList[kConfigAttribListCnt - 1]); - msaaConfigAttribList[kConfigAttribListCnt - 1] = EGL_SAMPLE_BUFFERS; - msaaConfigAttribList[kConfigAttribListCnt + 0] = 1; - msaaConfigAttribList[kConfigAttribListCnt + 1] = EGL_SAMPLES; - msaaConfigAttribList[kConfigAttribListCnt + 2] = msaaSampleCount; - msaaConfigAttribList[kConfigAttribListCnt + 3] = EGL_NONE; - if (eglChooseConfig(display, msaaConfigAttribList, eglConfig, 1, &numConfigs)) { - SkASSERT(numConfigs > 0); - foundConfig = true; - } - } - if (!foundConfig) { - if (!eglChooseConfig(display, configAttribList, eglConfig, 1, &numConfigs)) { - return false; - } - } - - // Create a surface - EGLSurface surface = eglCreateWindowSurface(display, *eglConfig, - (EGLNativeWindowType)hWnd, - surfaceAttribList); - if (surface == EGL_NO_SURFACE) { - return false; - } - - // Create a GL context - EGLContext context = eglCreateContext(display, *eglConfig, - 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(int msaaSampleCount, AttachmentInfo* info) { - if (EGL_NO_DISPLAY == fDisplay) { - bool bResult = create_ANGLE((HWND)fHWND, - msaaSampleCount, - &fDisplay, - &fContext, - &fSurface, - &fConfig); - if (false == bResult) { - return false; - } - fANGLEInterface.reset(get_angle_gl_interface()); - if (!fANGLEInterface) { - this->detachANGLE(); - return false; - } - GL_CALL(fANGLEInterface, ClearStencil(0)); - GL_CALL(fANGLEInterface, ClearColor(0, 0, 0, 0)); - GL_CALL(fANGLEInterface, StencilMask(0xffffffff)); - GL_CALL(fANGLEInterface, Clear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT)); - } - if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { - this->detachANGLE(); - return false; - } - eglGetConfigAttrib(fDisplay, fConfig, EGL_STENCIL_SIZE, &info->fStencilBits); - eglGetConfigAttrib(fDisplay, fConfig, EGL_SAMPLES, &info->fSampleCount); - - GL_CALL(fANGLEInterface, Viewport(0, 0, SkScalarRoundToInt(this->width()), - SkScalarRoundToInt(this->height()))); - return true; -} - -void SkOSWindow::detachANGLE() { - fANGLEInterface.reset(nullptr); - 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() { - GL_CALL(fANGLEInterface, Flush()); - - eglSwapBuffers(fDisplay, fSurface); -} -#endif // SK_ANGLE - -#endif // SK_SUPPORT_GPU - -// return true on success -bool SkOSWindow::attach(SkBackEndTypes attachType, int msaaSampleCount, bool deepColor, - AttachmentInfo* info) { - - // 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; -#if SK_SUPPORT_GPU - case kNativeGL_BackEndType: - result = attachGL(msaaSampleCount, deepColor, info); - break; -#if SK_ANGLE - case kANGLE_BackEndType: - result = attachANGLE(msaaSampleCount, info); - break; -#endif // SK_ANGLE -#endif // SK_SUPPORT_GPU - default: - SkASSERT(false); - result = false; - break; - } - - if (result) { - fAttached = attachType; - } - - return result; -} - -void SkOSWindow::release() { - switch (fAttached) { - case kNone_BackEndType: - // nothing to do - break; -#if SK_SUPPORT_GPU - case kNativeGL_BackEndType: - detachGL(); - break; -#if SK_ANGLE - case kANGLE_BackEndType: - detachANGLE(); - break; -#endif // SK_ANGLE -#endif // SK_SUPPORT_GPU - default: - SkASSERT(false); - break; - } - fAttached = kNone_BackEndType; -} - -void SkOSWindow::present() { - switch (fAttached) { - case kNone_BackEndType: - // nothing to do - return; -#if SK_SUPPORT_GPU - case kNativeGL_BackEndType: - presentGL(); - break; -#if SK_ANGLE - case kANGLE_BackEndType: - presentANGLE(); - break; -#endif // SK_ANGLE -#endif // SK_SUPPORT_GPU - default: - SkASSERT(false); - break; - } -} - -bool SkOSWindow::makeFullscreen() { - if (fFullscreen) { - return true; - } -#if SK_SUPPORT_GPU - if (fHGLRC) { - this->detachGL(); - } -#endif // SK_SUPPORT_GPU - // This is hacked together from various sources on the web. It can certainly be improved and be - // made more robust. - - // Save current window/resolution information. We do this in case we ever implement switching - // back to windowed mode. - fSavedWindowState.fZoomed = SkToBool(IsZoomed((HWND)fHWND)); - if (fSavedWindowState.fZoomed) { - SendMessage((HWND)fHWND, WM_SYSCOMMAND, SC_RESTORE, 0); - } - fSavedWindowState.fStyle = GetWindowLong((HWND)fHWND, GWL_STYLE); - fSavedWindowState.fExStyle = GetWindowLong((HWND)fHWND, GWL_EXSTYLE); - GetWindowRect((HWND)fHWND, &fSavedWindowState.fRect); - DEVMODE currScreenSettings; - memset(&currScreenSettings,0,sizeof(currScreenSettings)); - currScreenSettings.dmSize = sizeof(currScreenSettings); - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &currScreenSettings); - fSavedWindowState.fScreenWidth = currScreenSettings.dmPelsWidth; - fSavedWindowState.fScreenHeight = currScreenSettings.dmPelsHeight; - fSavedWindowState.fScreenBits = currScreenSettings.dmBitsPerPel; - fSavedWindowState.fHWND = fHWND; - - // Try different sizes to find an allowed setting? Use ChangeDisplaySettingsEx? - static const int kWidth = 1280; - static const int kHeight = 1024; - DEVMODE newScreenSettings; - memset(&newScreenSettings, 0, sizeof(newScreenSettings)); - newScreenSettings.dmSize = sizeof(newScreenSettings); - newScreenSettings.dmPelsWidth = kWidth; - newScreenSettings.dmPelsHeight = kHeight; - newScreenSettings.dmBitsPerPel = 32; - newScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - if (ChangeDisplaySettings(&newScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { - return false; - } - RECT WindowRect; - WindowRect.left = 0; - WindowRect.right = kWidth; - WindowRect.top = 0; - WindowRect.bottom = kHeight; - ShowCursor(FALSE); - AdjustWindowRectEx(&WindowRect, WS_POPUP, FALSE, WS_EX_APPWINDOW); - HWND fsHWND = CreateWindowEx( - WS_EX_APPWINDOW, - fWinInit.fClass, - NULL, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, - 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, - NULL, - NULL, - fWinInit.fInstance, - NULL - ); - if (!fsHWND) { - return false; - } - // Hide the old window and set the entry in the global mapping for this SkOSWindow to the - // new HWND. - ShowWindow((HWND)fHWND, SW_HIDE); - gHwndToOSWindowMap.remove(fHWND); - fHWND = fsHWND; - gHwndToOSWindowMap.set(fHWND, this); - this->updateSize(); - - fFullscreen = true; - return true; -} - -void SkOSWindow::setVsync(bool enable) { - SkWGLExtensions wgl; - wgl.swapInterval(enable ? 1 : 0); -} - -void SkOSWindow::closeWindow() { - DestroyWindow((HWND)fHWND); - if (fFullscreen) { - DestroyWindow((HWND)fSavedWindowState.fHWND); - } - gHwndToOSWindowMap.remove(fHWND); -} -#endif |