diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/util/windows')
12 files changed, 1582 insertions, 0 deletions
diff --git a/Source/ThirdParty/ANGLE/util/windows/WindowsTimer.cpp b/Source/ThirdParty/ANGLE/util/windows/WindowsTimer.cpp new file mode 100644 index 000000000..c6a9e9dd8 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/WindowsTimer.cpp @@ -0,0 +1,57 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowsTimer.cpp: Implementation of a high precision timer class on Windows + +#include "windows/WindowsTimer.h" + +WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0) +{ +} + +void WindowsTimer::start() +{ + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + mFrequency = frequency.QuadPart; + + LARGE_INTEGER curTime; + QueryPerformanceCounter(&curTime); + mStartTime = curTime.QuadPart; + + mRunning = true; +} + +void WindowsTimer::stop() +{ + LARGE_INTEGER curTime; + QueryPerformanceCounter(&curTime); + mStopTime = curTime.QuadPart; + + mRunning = false; +} + +double WindowsTimer::getElapsedTime() const +{ + LONGLONG endTime; + if (mRunning) + { + LARGE_INTEGER curTime; + QueryPerformanceCounter(&curTime); + endTime = curTime.QuadPart; + } + else + { + endTime = mStopTime; + } + + return static_cast<double>(endTime - mStartTime) / mFrequency; +} + +Timer *CreateTimer() +{ + return new WindowsTimer(); +} diff --git a/Source/ThirdParty/ANGLE/util/windows/WindowsTimer.h b/Source/ThirdParty/ANGLE/util/windows/WindowsTimer.h new file mode 100644 index 000000000..a19430005 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/WindowsTimer.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WindowsTimer.h: Definition of a high precision timer class on Windows + +#ifndef UTIL_WINDOWS_TIMER_H +#define UTIL_WINDOWS_TIMER_H + +#include <windows.h> + +#include "Timer.h" + +class WindowsTimer : public Timer +{ + public: + WindowsTimer(); + + void start() override; + void stop() override; + double getElapsedTime() const override; + + private: + bool mRunning; + LONGLONG mStartTime; + LONGLONG mStopTime; + + LONGLONG mFrequency; +}; + +#endif // UTIL_WINDOWS_TIMER_H diff --git a/Source/ThirdParty/ANGLE/util/windows/Windows_system_utils.cpp b/Source/ThirdParty/ANGLE/util/windows/Windows_system_utils.cpp new file mode 100644 index 000000000..ce97e27ed --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/Windows_system_utils.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Windows_system_utils.cpp: Implementation of OS-specific functions for Windows + +#include "system_utils.h" + +#include <stdarg.h> +#include <windows.h> +#include <array> +#include <vector> + +namespace angle +{ + +namespace +{ + +std::string GetExecutablePathImpl() +{ + std::array<char, MAX_PATH> executableFileBuf; + DWORD executablePathLen = GetModuleFileNameA(NULL, executableFileBuf.data(), + static_cast<DWORD>(executableFileBuf.size())); + return (executablePathLen > 0 ? std::string(executableFileBuf.data()) : ""); +} + +std::string GetExecutableDirectoryImpl() +{ + std::string executablePath = GetExecutablePath(); + size_t lastPathSepLoc = executablePath.find_last_of("\\/"); + return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : ""; +} + +} // anonymous namespace + +const char *GetExecutablePath() +{ + const static std::string &exePath = GetExecutablePathImpl(); + return exePath.c_str(); +} + +const char *GetExecutableDirectory() +{ + const static std::string &exeDir = GetExecutableDirectoryImpl(); + return exeDir.c_str(); +} + +const char *GetSharedLibraryExtension() +{ + return "dll"; +} + +void Sleep(unsigned int milliseconds) +{ + ::Sleep(static_cast<DWORD>(milliseconds)); +} + +void WriteDebugMessage(const char *format, ...) +{ + va_list args; + va_start(args, format); + int size = vsnprintf(nullptr, 0, format, args); + va_end(args); + + std::vector<char> buffer(size + 2); + va_start(args, format); + vsnprintf(buffer.data(), size + 1, format, args); + va_end(args); + + OutputDebugStringA(buffer.data()); +} + +} // namespace angle diff --git a/Source/ThirdParty/ANGLE/util/windows/win32/Win32Pixmap.cpp b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Pixmap.cpp new file mode 100644 index 000000000..801513163 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Pixmap.cpp @@ -0,0 +1,59 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Win32Pixmap.cpp: Implementation of OSPixmap for Win32 (Windows) + +#include "windows/win32/Win32Pixmap.h" + +Win32Pixmap::Win32Pixmap() : mBitmap(nullptr) +{ +} + +Win32Pixmap::~Win32Pixmap() +{ + if (mBitmap) + { + DeleteObject(mBitmap); + } +} + +bool Win32Pixmap::initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) +{ + BITMAPINFO bitmapInfo; + memset(&bitmapInfo, 0, sizeof(bitmapInfo)); + + if (depth != 24 && depth != 32) + { + return false; + } + + bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo); + bitmapInfo.bmiHeader.biWidth = static_cast<LONG>(width); + bitmapInfo.bmiHeader.biHeight = static_cast<LONG>(height); + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biBitCount = static_cast<WORD>(depth); + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = 0; + bitmapInfo.bmiHeader.biXPelsPerMeter = 1; + bitmapInfo.bmiHeader.biYPelsPerMeter = 1; + bitmapInfo.bmiHeader.biClrUsed = 0; + bitmapInfo.bmiHeader.biClrImportant = 0; + + void *bitmapPtr = nullptr; + mBitmap = CreateDIBSection(display, &bitmapInfo, DIB_RGB_COLORS, &bitmapPtr, nullptr, 0); + + return mBitmap != nullptr; +} + +EGLNativePixmapType Win32Pixmap::getNativePixmap() const +{ + return mBitmap; +} + +OSPixmap *CreateOSPixmap() +{ + return new Win32Pixmap(); +} diff --git a/Source/ThirdParty/ANGLE/util/windows/win32/Win32Pixmap.h b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Pixmap.h new file mode 100644 index 000000000..7e14f8a11 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Pixmap.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Win32Pixmap.h: Definition of the implementation of OSPixmap for Win32 (Windows) + +#ifndef UTIL_WIN32_PIXMAP_H_ +#define UTIL_WIN32_PIXMAP_H_ + +#include <windows.h> + +#include "OSPixmap.h" + +class Win32Pixmap : public OSPixmap +{ + public: + Win32Pixmap(); + ~Win32Pixmap() override; + + bool initialize(EGLNativeDisplayType display, size_t width, size_t height, int depth) override; + + EGLNativePixmapType getNativePixmap() const override; + + private: + HBITMAP mBitmap; +}; + +#endif // UTIL_WIN32_PIXMAP_H_ diff --git a/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp new file mode 100644 index 000000000..abd1132b2 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.cpp @@ -0,0 +1,831 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Win32Window.cpp: Implementation of OSWindow for Win32 (Windows) + +#include "windows/win32/Win32Window.h" + +#include <sstream> + +#include "common/debug.h" + +Key VirtualKeyCodeToKey(WPARAM key, LPARAM flags) +{ + switch (key) + { + // Check the scancode to distinguish between left and right shift + case VK_SHIFT: + { + static unsigned int lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC); + unsigned int scancode = static_cast<unsigned int>((flags & (0xFF << 16)) >> 16); + return scancode == lShift ? KEY_LSHIFT : KEY_RSHIFT; + } + + // Check the "extended" flag to distinguish between left and right alt + case VK_MENU: + return (HIWORD(flags) & KF_EXTENDED) ? KEY_RALT : KEY_LALT; + + // Check the "extended" flag to distinguish between left and right control + case VK_CONTROL: + return (HIWORD(flags) & KF_EXTENDED) ? KEY_RCONTROL : KEY_LCONTROL; + + // Other keys are reported properly + case VK_LWIN: + return KEY_LSYSTEM; + case VK_RWIN: + return KEY_RSYSTEM; + case VK_APPS: + return KEY_MENU; + case VK_OEM_1: + return KEY_SEMICOLON; + case VK_OEM_2: + return KEY_SLASH; + case VK_OEM_PLUS: + return KEY_EQUAL; + case VK_OEM_MINUS: + return KEY_DASH; + case VK_OEM_4: + return KEY_LBRACKET; + case VK_OEM_6: + return KEY_RBRACKET; + case VK_OEM_COMMA: + return KEY_COMMA; + case VK_OEM_PERIOD: + return KEY_PERIOD; + case VK_OEM_7: + return KEY_QUOTE; + case VK_OEM_5: + return KEY_BACKSLASH; + case VK_OEM_3: + return KEY_TILDE; + case VK_ESCAPE: + return KEY_ESCAPE; + case VK_SPACE: + return KEY_SPACE; + case VK_RETURN: + return KEY_RETURN; + case VK_BACK: + return KEY_BACK; + case VK_TAB: + return KEY_TAB; + case VK_PRIOR: + return KEY_PAGEUP; + case VK_NEXT: + return KEY_PAGEDOWN; + case VK_END: + return KEY_END; + case VK_HOME: + return KEY_HOME; + case VK_INSERT: + return KEY_INSERT; + case VK_DELETE: + return KEY_DELETE; + case VK_ADD: + return KEY_ADD; + case VK_SUBTRACT: + return KEY_SUBTRACT; + case VK_MULTIPLY: + return KEY_MULTIPLY; + case VK_DIVIDE: + return KEY_DIVIDE; + case VK_PAUSE: + return KEY_PAUSE; + case VK_F1: + return KEY_F1; + case VK_F2: + return KEY_F2; + case VK_F3: + return KEY_F3; + case VK_F4: + return KEY_F4; + case VK_F5: + return KEY_F5; + case VK_F6: + return KEY_F6; + case VK_F7: + return KEY_F7; + case VK_F8: + return KEY_F8; + case VK_F9: + return KEY_F9; + case VK_F10: + return KEY_F10; + case VK_F11: + return KEY_F11; + case VK_F12: + return KEY_F12; + case VK_F13: + return KEY_F13; + case VK_F14: + return KEY_F14; + case VK_F15: + return KEY_F15; + case VK_LEFT: + return KEY_LEFT; + case VK_RIGHT: + return KEY_RIGHT; + case VK_UP: + return KEY_UP; + case VK_DOWN: + return KEY_DOWN; + case VK_NUMPAD0: + return KEY_NUMPAD0; + case VK_NUMPAD1: + return KEY_NUMPAD1; + case VK_NUMPAD2: + return KEY_NUMPAD2; + case VK_NUMPAD3: + return KEY_NUMPAD3; + case VK_NUMPAD4: + return KEY_NUMPAD4; + case VK_NUMPAD5: + return KEY_NUMPAD5; + case VK_NUMPAD6: + return KEY_NUMPAD6; + case VK_NUMPAD7: + return KEY_NUMPAD7; + case VK_NUMPAD8: + return KEY_NUMPAD8; + case VK_NUMPAD9: + return KEY_NUMPAD9; + case 'A': + return KEY_A; + case 'Z': + return KEY_Z; + case 'E': + return KEY_E; + case 'R': + return KEY_R; + case 'T': + return KEY_T; + case 'Y': + return KEY_Y; + case 'U': + return KEY_U; + case 'I': + return KEY_I; + case 'O': + return KEY_O; + case 'P': + return KEY_P; + case 'Q': + return KEY_Q; + case 'S': + return KEY_S; + case 'D': + return KEY_D; + case 'F': + return KEY_F; + case 'G': + return KEY_G; + case 'H': + return KEY_H; + case 'J': + return KEY_J; + case 'K': + return KEY_K; + case 'L': + return KEY_L; + case 'M': + return KEY_M; + case 'W': + return KEY_W; + case 'X': + return KEY_X; + case 'C': + return KEY_C; + case 'V': + return KEY_V; + case 'B': + return KEY_B; + case 'N': + return KEY_N; + case '0': + return KEY_NUM0; + case '1': + return KEY_NUM1; + case '2': + return KEY_NUM2; + case '3': + return KEY_NUM3; + case '4': + return KEY_NUM4; + case '5': + return KEY_NUM5; + case '6': + return KEY_NUM6; + case '7': + return KEY_NUM7; + case '8': + return KEY_NUM8; + case '9': + return KEY_NUM9; + } + + return Key(0); +} + +LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_NCCREATE: + { + LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam); + SetWindowLongPtr(hWnd, GWLP_USERDATA, + reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams)); + return DefWindowProcA(hWnd, message, wParam, lParam); + } + } + + Win32Window *window = reinterpret_cast<Win32Window *>(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (window) + { + switch (message) + { + case WM_DESTROY: + case WM_CLOSE: + { + Event event; + event.Type = Event::EVENT_CLOSED; + window->pushEvent(event); + break; + } + + case WM_MOVE: + { + RECT winRect; + GetClientRect(hWnd, &winRect); + + POINT topLeft; + topLeft.x = winRect.left; + topLeft.y = winRect.top; + ClientToScreen(hWnd, &topLeft); + + Event event; + event.Type = Event::EVENT_MOVED; + event.Move.X = topLeft.x; + event.Move.Y = topLeft.y; + window->pushEvent(event); + + break; + } + + case WM_SIZE: + { + RECT winRect; + GetClientRect(hWnd, &winRect); + + POINT topLeft; + topLeft.x = winRect.left; + topLeft.y = winRect.top; + ClientToScreen(hWnd, &topLeft); + + POINT botRight; + botRight.x = winRect.right; + botRight.y = winRect.bottom; + ClientToScreen(hWnd, &botRight); + + Event event; + event.Type = Event::EVENT_RESIZED; + event.Size.Width = botRight.x - topLeft.x; + event.Size.Height = botRight.y - topLeft.y; + window->pushEvent(event); + + break; + } + + case WM_SETFOCUS: + { + Event event; + event.Type = Event::EVENT_GAINED_FOCUS; + window->pushEvent(event); + break; + } + + case WM_KILLFOCUS: + { + Event event; + event.Type = Event::EVENT_LOST_FOCUS; + window->pushEvent(event); + break; + } + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + { + bool down = (message == WM_KEYDOWN || message == WM_SYSKEYDOWN); + + Event event; + event.Type = down ? Event::EVENT_KEY_PRESSED : Event::EVENT_KEY_RELEASED; + event.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; + event.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; + event.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; + event.Key.System = + HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); + event.Key.Code = VirtualKeyCodeToKey(wParam, lParam); + window->pushEvent(event); + + break; + } + + case WM_MOUSEWHEEL: + { + Event event; + event.Type = Event::EVENT_MOUSE_WHEEL_MOVED; + event.MouseWheel.Delta = static_cast<short>(HIWORD(wParam)) / 120; + window->pushEvent(event); + break; + } + + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; + event.MouseButton.Button = MOUSEBUTTON_LEFT; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + case WM_LBUTTONUP: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; + event.MouseButton.Button = MOUSEBUTTON_LEFT; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; + event.MouseButton.Button = MOUSEBUTTON_RIGHT; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + // Mouse right button up event + case WM_RBUTTONUP: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; + event.MouseButton.Button = MOUSEBUTTON_RIGHT; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + // Mouse wheel button down event + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; + event.MouseButton.Button = MOUSEBUTTON_MIDDLE; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + // Mouse wheel button up event + case WM_MBUTTONUP: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; + event.MouseButton.Button = MOUSEBUTTON_MIDDLE; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + // Mouse X button down event + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_PRESSED; + event.MouseButton.Button = + (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + // Mouse X button up event + case WM_XBUTTONUP: + { + Event event; + event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED; + event.MouseButton.Button = + (HIWORD(wParam) == XBUTTON1) ? MOUSEBUTTON_BUTTON4 : MOUSEBUTTON_BUTTON5; + event.MouseButton.X = static_cast<short>(LOWORD(lParam)); + event.MouseButton.Y = static_cast<short>(HIWORD(lParam)); + window->pushEvent(event); + break; + } + + case WM_MOUSEMOVE: + { + if (!window->mIsMouseInWindow) + { + window->mIsMouseInWindow = true; + Event event; + event.Type = Event::EVENT_MOUSE_ENTERED; + window->pushEvent(event); + } + + int mouseX = static_cast<short>(LOWORD(lParam)); + int mouseY = static_cast<short>(HIWORD(lParam)); + + Event event; + event.Type = Event::EVENT_MOUSE_MOVED; + event.MouseMove.X = mouseX; + event.MouseMove.Y = mouseY; + window->pushEvent(event); + break; + } + + case WM_MOUSELEAVE: + { + Event event; + event.Type = Event::EVENT_MOUSE_LEFT; + window->pushEvent(event); + window->mIsMouseInWindow = false; + break; + } + + case WM_USER: + { + Event testEvent; + testEvent.Type = Event::EVENT_TEST; + window->pushEvent(testEvent); + break; + } + } + } + return DefWindowProcA(hWnd, message, wParam, lParam); +} + +Win32Window::Win32Window() + : mIsVisible(false), + mSetVisibleTimer(CreateTimer()), + mIsMouseInWindow(false), + mNativeWindow(0), + mParentWindow(0), + mNativeDisplay(0) +{ +} + +Win32Window::~Win32Window() +{ + destroy(); + delete mSetVisibleTimer; +} + +bool Win32Window::initialize(const std::string &name, size_t width, size_t height) +{ + destroy(); + + // Use a new window class name for ever window to ensure that a new window can be created + // even if the last one was not properly destroyed + static size_t windowIdx = 0; + std::ostringstream nameStream; + nameStream << name << "_" << windowIdx++; + + mParentClassName = nameStream.str(); + mChildClassName = mParentClassName + "_Child"; + + // Work around compile error from not defining "UNICODE" while Chromium does + const LPSTR idcArrow = MAKEINTRESOURCEA(32512); + + WNDCLASSEXA parentWindowClass = {0}; + parentWindowClass.cbSize = sizeof(WNDCLASSEXA); + parentWindowClass.style = 0; + parentWindowClass.lpfnWndProc = WndProc; + parentWindowClass.cbClsExtra = 0; + parentWindowClass.cbWndExtra = 0; + parentWindowClass.hInstance = GetModuleHandle(NULL); + parentWindowClass.hIcon = NULL; + parentWindowClass.hCursor = LoadCursorA(NULL, idcArrow); + parentWindowClass.hbrBackground = 0; + parentWindowClass.lpszMenuName = NULL; + parentWindowClass.lpszClassName = mParentClassName.c_str(); + if (!RegisterClassExA(&parentWindowClass)) + { + return false; + } + + WNDCLASSEXA childWindowClass = {0}; + childWindowClass.cbSize = sizeof(WNDCLASSEXA); + childWindowClass.style = CS_OWNDC; + childWindowClass.lpfnWndProc = WndProc; + childWindowClass.cbClsExtra = 0; + childWindowClass.cbWndExtra = 0; + childWindowClass.hInstance = GetModuleHandle(NULL); + childWindowClass.hIcon = NULL; + childWindowClass.hCursor = LoadCursorA(NULL, idcArrow); + childWindowClass.hbrBackground = 0; + childWindowClass.lpszMenuName = NULL; + childWindowClass.lpszClassName = mChildClassName.c_str(); + if (!RegisterClassExA(&childWindowClass)) + { + return false; + } + + DWORD parentStyle = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU; + DWORD parentExtendedStyle = WS_EX_APPWINDOW; + + RECT sizeRect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height)}; + AdjustWindowRectEx(&sizeRect, parentStyle, FALSE, parentExtendedStyle); + + mParentWindow = + CreateWindowExA(parentExtendedStyle, mParentClassName.c_str(), name.c_str(), parentStyle, + CW_USEDEFAULT, CW_USEDEFAULT, sizeRect.right - sizeRect.left, + sizeRect.bottom - sizeRect.top, NULL, NULL, GetModuleHandle(NULL), this); + + mNativeWindow = CreateWindowExA(0, mChildClassName.c_str(), name.c_str(), WS_CHILD, 0, 0, + static_cast<int>(width), static_cast<int>(height), + mParentWindow, NULL, GetModuleHandle(NULL), this); + + mNativeDisplay = GetDC(mNativeWindow); + if (!mNativeDisplay) + { + destroy(); + return false; + } + + return true; +} + +void Win32Window::destroy() +{ + if (mNativeDisplay) + { + ReleaseDC(mNativeWindow, mNativeDisplay); + mNativeDisplay = 0; + } + + if (mNativeWindow) + { + DestroyWindow(mNativeWindow); + mNativeWindow = 0; + } + + if (mParentWindow) + { + DestroyWindow(mParentWindow); + mParentWindow = 0; + } + + UnregisterClassA(mParentClassName.c_str(), NULL); + UnregisterClassA(mChildClassName.c_str(), NULL); +} + +bool Win32Window::takeScreenshot(uint8_t *pixelData) +{ + if (mIsVisible) + { + return false; + } + + bool error = false; + + // Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait + // for a while before issuing screenshot if window was just made visible. + { + static const double WAIT_WINDOW_VISIBLE_MS = 0.5; // Half a second for the animation + double timeSinceVisible = mSetVisibleTimer->getElapsedTime(); + + if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS) + { + Sleep(static_cast<DWORD>((WAIT_WINDOW_VISIBLE_MS - timeSinceVisible) * 1000)); + } + } + + HDC screenDC = nullptr; + HDC windowDC = nullptr; + HDC tmpDC = nullptr; + HBITMAP tmpBitmap = nullptr; + + if (!error) + { + screenDC = GetDC(nullptr); + error = screenDC == nullptr; + } + + if (!error) + { + windowDC = GetDC(mNativeWindow); + error = windowDC == nullptr; + } + + if (!error) + { + tmpDC = CreateCompatibleDC(screenDC); + error = tmpDC == nullptr; + } + + if (!error) + { + tmpBitmap = CreateCompatibleBitmap(screenDC, mWidth, mHeight); + error = tmpBitmap == nullptr; + } + + RECT rect = {0, 0, 0, 0}; + if (!error) + { + MapWindowPoints(mNativeWindow, nullptr, reinterpret_cast<LPPOINT>(&rect), 0); + + error = SelectObject(tmpDC, tmpBitmap) == nullptr; + } + + if (!error) + { + error = + BitBlt(tmpDC, 0, 0, mWidth, mHeight, screenDC, rect.left, rect.top, SRCCOPY) == TRUE; + } + + if (!error) + { + BITMAPINFOHEADER bitmapInfo; + bitmapInfo.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.biWidth = mWidth; + bitmapInfo.biHeight = -mHeight; + bitmapInfo.biPlanes = 1; + bitmapInfo.biBitCount = 32; + bitmapInfo.biCompression = BI_RGB; + bitmapInfo.biSizeImage = 0; + bitmapInfo.biXPelsPerMeter = 0; + bitmapInfo.biYPelsPerMeter = 0; + bitmapInfo.biClrUsed = 0; + bitmapInfo.biClrImportant = 0; + int getBitsResult = GetDIBits(screenDC, tmpBitmap, 0, mHeight, pixelData, + reinterpret_cast<BITMAPINFO *>(&bitmapInfo), DIB_RGB_COLORS); + error = getBitsResult != 0; + } + + if (tmpBitmap != nullptr) + { + DeleteObject(tmpBitmap); + } + if (tmpDC != nullptr) + { + DeleteDC(tmpDC); + } + if (screenDC != nullptr) + { + ReleaseDC(nullptr, screenDC); + } + if (windowDC != nullptr) + { + ReleaseDC(mNativeWindow, windowDC); + } + + return !error; +} + +EGLNativeWindowType Win32Window::getNativeWindow() const +{ + return mNativeWindow; +} + +EGLNativeDisplayType Win32Window::getNativeDisplay() const +{ + return mNativeDisplay; +} + +void Win32Window::messageLoop() +{ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +void Win32Window::setMousePosition(int x, int y) +{ + RECT winRect; + GetClientRect(mNativeWindow, &winRect); + + POINT topLeft; + topLeft.x = winRect.left; + topLeft.y = winRect.top; + ClientToScreen(mNativeWindow, &topLeft); + + SetCursorPos(topLeft.x + x, topLeft.y + y); +} + +OSWindow *CreateOSWindow() +{ + return new Win32Window(); +} + +bool Win32Window::setPosition(int x, int y) +{ + if (mX == x && mY == y) + { + return true; + } + + RECT windowRect; + if (!GetWindowRect(mParentWindow, &windowRect)) + { + return false; + } + + if (!MoveWindow(mParentWindow, x, y, windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top, TRUE)) + { + return false; + } + + return true; +} + +bool Win32Window::resize(int width, int height) +{ + if (width == mWidth && height == mHeight) + { + return true; + } + + RECT windowRect; + if (!GetWindowRect(mParentWindow, &windowRect)) + { + return false; + } + + RECT clientRect; + if (!GetClientRect(mParentWindow, &clientRect)) + { + return false; + } + + LONG diffX = (windowRect.right - windowRect.left) - clientRect.right; + LONG diffY = (windowRect.bottom - windowRect.top) - clientRect.bottom; + if (!MoveWindow(mParentWindow, windowRect.left, windowRect.top, width + diffX, height + diffY, + TRUE)) + { + return false; + } + + if (!MoveWindow(mNativeWindow, 0, 0, width, height, FALSE)) + { + return false; + } + + return true; +} + +void Win32Window::setVisible(bool isVisible) +{ + int flag = (isVisible ? SW_SHOW : SW_HIDE); + + ShowWindow(mParentWindow, flag); + ShowWindow(mNativeWindow, flag); + + if (isVisible) + { + mSetVisibleTimer->stop(); + mSetVisibleTimer->start(); + } +} + +void Win32Window::pushEvent(Event event) +{ + OSWindow::pushEvent(event); + + switch (event.Type) + { + case Event::EVENT_RESIZED: + MoveWindow(mNativeWindow, 0, 0, mWidth, mHeight, FALSE); + break; + default: + break; + } +} + +void Win32Window::signalTestEvent() +{ + PostMessage(mNativeWindow, WM_USER, 0, 0); +} diff --git a/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.h b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.h new file mode 100644 index 000000000..c0904e930 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/win32/Win32Window.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Win32Window.h: Definition of the implementation of OSWindow for Win32 (Windows) + +#ifndef UTIL_WIN32_WINDOW_H +#define UTIL_WIN32_WINDOW_H + +#include <windows.h> +#include <string> + +#include "OSWindow.h" +#include "Timer.h" + +class Win32Window : public OSWindow +{ + public: + Win32Window(); + ~Win32Window() override; + + bool initialize(const std::string &name, size_t width, size_t height) override; + void destroy() override; + + bool takeScreenshot(uint8_t *pixelData) override; + + EGLNativeWindowType getNativeWindow() const override; + EGLNativeDisplayType getNativeDisplay() const override; + + void messageLoop() override; + + void pushEvent(Event event) override; + + void setMousePosition(int x, int y) override; + bool setPosition(int x, int y) override; + bool resize(int width, int height) override; + void setVisible(bool isVisible) override; + + void signalTestEvent() override; + + private: + static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + + std::string mParentClassName; + std::string mChildClassName; + + bool mIsVisible; + Timer *mSetVisibleTimer; + + bool mIsMouseInWindow; + + EGLNativeWindowType mNativeWindow; + EGLNativeWindowType mParentWindow; + EGLNativeDisplayType mNativeDisplay; +}; + +#endif // UTIL_WIN32_WINDOW_H diff --git a/Source/ThirdParty/ANGLE/util/windows/win32/Win32_system_utils.cpp b/Source/ThirdParty/ANGLE/util/windows/win32/Win32_system_utils.cpp new file mode 100644 index 000000000..a9fd97fe7 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/win32/Win32_system_utils.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Win32_system_utils.cpp: Implementation of OS-specific functions for Win32 (Windows) + +#include "system_utils.h" + +#include <windows.h> +#include <array> + +namespace angle +{ + +void SetLowPriorityProcess() +{ + SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); +} + +class Win32Library : public Library +{ + public: + Win32Library(const std::string &libraryName); + ~Win32Library() override; + + void *getSymbol(const std::string &symbolName) override; + + private: + HMODULE mModule; +}; + +Win32Library::Win32Library(const std::string &libraryName) : mModule(nullptr) +{ + const auto &fullName = libraryName + "." + GetSharedLibraryExtension(); + mModule = LoadLibraryA(fullName.c_str()); +} + +Win32Library::~Win32Library() +{ + if (mModule) + { + FreeLibrary(mModule); + } +} + +void *Win32Library::getSymbol(const std::string &symbolName) +{ + if (!mModule) + { + return nullptr; + } + + return GetProcAddress(mModule, symbolName.c_str()); +} + +Library *loadLibrary(const std::string &libraryName) +{ + return new Win32Library(libraryName); +} + +} // namespace angle diff --git a/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTPixmap.cpp b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTPixmap.cpp new file mode 100644 index 000000000..fdc853ae5 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTPixmap.cpp @@ -0,0 +1,17 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WinRTPixmap.cpp: Stub implementation of OSPixmap functions for WinRT (Windows) + +#include "OSPixmap.h" + +#include "common/debug.h" + +OSPixmap *CreateOSPixmap() +{ + UNIMPLEMENTED(); + return nullptr; +}
\ No newline at end of file diff --git a/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTWindow.cpp b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTWindow.cpp new file mode 100644 index 000000000..33f76a29f --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTWindow.cpp @@ -0,0 +1,284 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WinRTWindow.cpp: Implementation of OSWindow for WinRT (Windows) + +#include "windows/winrt/WinRTWindow.h" + +#include <wrl.h> +#include <windows.applicationmodel.core.h> +#include <windows.ui.xaml.h> + +#include "angle_windowsstore.h" +#include "common/debug.h" + +using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Core; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +WinRTWindow::WinRTWindow() : mNativeWindow(nullptr) +{ +} + +WinRTWindow::~WinRTWindow() +{ + destroy(); +} + +bool WinRTWindow::initialize(const std::string &name, size_t width, size_t height) +{ + ComPtr<ICoreWindowStatic> coreWindowStatic; + ComPtr<IActivationFactory> propertySetFactory; + ComPtr<IPropertyValueStatics> propertyValueStatics; + + ComPtr<ICoreApplication> coreApplication; + ComPtr<IPropertySet> coreApplicationProperties; + ComPtr<IMap<HSTRING, IInspectable *>> coreApplicationPropertiesAsMap; + + ComPtr<IMap<HSTRING, IInspectable *>> nativeWindowAsMap; + ComPtr<IInspectable> sizeValue; + + HRESULT result = S_OK; + boolean propertyReplaced = false; + + destroy(); + + // Get all the relevant activation factories + result = GetActivationFactory( + HStringReference(RuntimeClass_Windows_UI_Core_CoreWindow).Get(), &coreWindowStatic); + if (FAILED(result)) + { + return false; + } + + result = GetActivationFactory( + HStringReference(RuntimeClass_Windows_Foundation_Collections_PropertySet).Get(), + &propertySetFactory); + if (FAILED(result)) + { + return false; + } + + result = + GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), + &propertyValueStatics); + if (FAILED(result)) + { + return false; + } + + result = GetActivationFactory( + HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), + &coreApplication); + if (FAILED(result)) + { + return false; + } + + // Create a PropertySet to be used as the native window + result = propertySetFactory->ActivateInstance(&mNativeWindow); + if (FAILED(result)) + { + return false; + } + + // Get the PropertySet as a map, so we can Insert things into it later + ComPtr<IInspectable> tempNativeWindow = mNativeWindow; + result = tempNativeWindow.As(&nativeWindowAsMap); + if (FAILED(result)) + { + return false; + } + + // Get the CoreApplication properties + result = coreApplication->get_Properties(coreApplicationProperties.GetAddressOf()); + if (FAILED(result)) + { + return false; + } + + // Get the CoreApplication properties as a map + result = coreApplicationProperties.As(&coreApplicationPropertiesAsMap); + if (FAILED(result)) + { + return false; + } + + // See if the application properties contain an EGLNativeWindowTypeProperty + boolean hasEGLNativeWindowTypeProperty; + result = coreApplicationPropertiesAsMap->HasKey( + HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEGLNativeWindowTypeProperty); + if (FAILED(result)) + { + return false; + } + + // If an EGLNativeWindowTypeProperty is inputted then use it + if (hasEGLNativeWindowTypeProperty) + { + ComPtr<IInspectable> coreApplicationPropertyNativeWindow; + + result = coreApplicationPropertiesAsMap->Lookup( + HStringReference(EGLNativeWindowTypeProperty).Get(), + &coreApplicationPropertyNativeWindow); + if (FAILED(result)) + { + return false; + } + + // See if the inputted window was a CoreWindow + ComPtr<ICoreWindow> applicationPropertyCoreWindow; + if (SUCCEEDED(coreApplicationPropertyNativeWindow.As(&applicationPropertyCoreWindow))) + { + // Store away the CoreWindow's dispatcher, to be used later to process messages + result = applicationPropertyCoreWindow->get_Dispatcher(&mCoreDispatcher); + if (FAILED(result)) + { + return false; + } + } + else + { + ComPtr<IPropertySet> propSet; + + // Disallow Property Sets here, since we want to wrap this window in + // a property set with the size property below + if (SUCCEEDED(coreApplicationPropertyNativeWindow.As(&propSet))) + { + return false; + } + } + + // Add the window to the map + result = + nativeWindowAsMap->Insert(HStringReference(EGLNativeWindowTypeProperty).Get(), + coreApplicationPropertyNativeWindow.Get(), &propertyReplaced); + if (FAILED(result)) + { + return false; + } + } + else + { + ComPtr<ICoreWindow> currentThreadCoreWindow; + + // Get the CoreWindow for the current thread + result = coreWindowStatic->GetForCurrentThread(¤tThreadCoreWindow); + if (FAILED(result)) + { + return false; + } + + // By default, just add this thread's CoreWindow to the PropertySet + result = nativeWindowAsMap->Insert(HStringReference(EGLNativeWindowTypeProperty).Get(), + currentThreadCoreWindow.Get(), &propertyReplaced); + if (FAILED(result)) + { + return false; + } + + // Store away the CoreWindow's dispatcher, to be used later to process messages + result = currentThreadCoreWindow->get_Dispatcher(&mCoreDispatcher); + if (FAILED(result)) + { + return false; + } + } + + // Create a Size to represent the Native Window's size + Size renderSize; + renderSize.Width = static_cast<float>(width); + renderSize.Height = static_cast<float>(height); + result = propertyValueStatics->CreateSize(renderSize, sizeValue.GetAddressOf()); + if (FAILED(result)) + { + return false; + } + + // Add the Size to the PropertySet + result = nativeWindowAsMap->Insert(HStringReference(EGLRenderSurfaceSizeProperty).Get(), + sizeValue.Get(), &propertyReplaced); + if (FAILED(result)) + { + return false; + } + + return true; +}; + +void WinRTWindow::destroy() +{ + SafeRelease(mNativeWindow); + + mCoreDispatcher.Reset(); +} + +EGLNativeWindowType WinRTWindow::getNativeWindow() const +{ + return mNativeWindow; +} + +EGLNativeDisplayType WinRTWindow::getNativeDisplay() const +{ + UNIMPLEMENTED(); + return static_cast<EGLNativeDisplayType>(0); +} + +void WinRTWindow::messageLoop() +{ + // If we have a CoreDispatcher then use it to process events + if (mCoreDispatcher) + { + HRESULT result = + mCoreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + } +} + +void WinRTWindow::setMousePosition(int /* x */, int /* y */) +{ + UNIMPLEMENTED(); +} + +bool WinRTWindow::setPosition(int /* x */, int /* y */) +{ + UNIMPLEMENTED(); + return false; +} + +bool WinRTWindow::resize(int /* width */, int /* height */) +{ + UNIMPLEMENTED(); + return false; +} + +void WinRTWindow::setVisible(bool isVisible) +{ + if (isVisible) + { + // Already visible by default + return; + } + else + { + // Not implemented in WinRT + UNIMPLEMENTED(); + } +} + +void WinRTWindow::signalTestEvent() +{ + UNIMPLEMENTED(); +} + +OSWindow *CreateOSWindow() +{ + return new WinRTWindow(); +}
\ No newline at end of file diff --git a/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTWindow.h b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTWindow.h new file mode 100644 index 000000000..9eabc049d --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRTWindow.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WinRTWindow.h: Definition of the implementation of OSWindow for WinRT (Windows) + +#ifndef UTIL_WINRT_WINDOW_H +#define UTIL_WINRT_WINDOW_H + +#include <string> +#include <windows.h> +#include <windows.applicationmodel.core.h> +#include <wrl.h> + +#include "OSWindow.h" + +class WinRTWindow : public OSWindow +{ + public: + WinRTWindow(); + ~WinRTWindow() override; + + bool initialize(const std::string &name, size_t width, size_t height) override; + void destroy() override; + + EGLNativeWindowType getNativeWindow() const override; + EGLNativeDisplayType getNativeDisplay() const override; + + void messageLoop() override; + + void setMousePosition(int x, int y) override; + bool setPosition(int x, int y) override; + bool resize(int width, int height) override; + void setVisible(bool isVisible) override; + + void signalTestEvent() override; + + private: + EGLNativeWindowType mNativeWindow; + Microsoft::WRL::ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mCoreDispatcher; +}; + +#endif // UTIL_WINRT_WINDOW_H diff --git a/Source/ThirdParty/ANGLE/util/windows/winrt/WinRT_system_utils.cpp b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRT_system_utils.cpp new file mode 100644 index 000000000..8513bacd9 --- /dev/null +++ b/Source/ThirdParty/ANGLE/util/windows/winrt/WinRT_system_utils.cpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WinRT_system_utils.cpp: Implementation of OS-specific functions for WinRT (Windows) + +#include "system_utils.h" + +#include <windows.h> +#include <array> + +namespace angle +{ + +void SetLowPriorityProcess() +{ + // No equivalent to this in WinRT +} + +Library *loadLibrary(const std::string &libraryName) +{ + // WinRT cannot load code dynamically. + return nullptr; +} + +} // namespace angle |