diff options
| author | Tony Barbour <tony@LunarG.com> | 2016-02-25 15:44:10 -0700 |
|---|---|---|
| committer | Tony Barbour <tony@LunarG.com> | 2016-02-26 13:53:07 -0700 |
| commit | 6d366c23f50752c8bc39673416040d89a94a586f (patch) | |
| tree | 7a9493a747ffad8b708fd373ffbee359459ddd66 /demos/smoke/ShellWin32.cpp | |
| parent | 2e4f6dfe4624d966fb4db3c477586bd6b1c2b8e1 (diff) | |
| download | usermoji-6d366c23f50752c8bc39673416040d89a94a586f.tar.xz | |
demos: Add Hologram snapshot as Smoke test/demo
Diffstat (limited to 'demos/smoke/ShellWin32.cpp')
| -rw-r--r-- | demos/smoke/ShellWin32.cpp | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/demos/smoke/ShellWin32.cpp b/demos/smoke/ShellWin32.cpp new file mode 100644 index 00000000..1a1a844c --- /dev/null +++ b/demos/smoke/ShellWin32.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2016 Google, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <cassert> +#include <iostream> +#include <sstream> + +#include "Helpers.h" +#include "Game.h" +#include "ShellWin32.h" + +namespace { + +class Win32Timer { +public: + Win32Timer() + { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + freq_ = static_cast<double>(freq.QuadPart); + + reset(); + } + + void reset() + { + QueryPerformanceCounter(&start_); + } + + double get() const + { + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + + return static_cast<double>(now.QuadPart - start_.QuadPart) / freq_; + } + +private: + double freq_; + LARGE_INTEGER start_; +}; + +} // namespace + +ShellWin32::ShellWin32(Game &game) : Shell(game), hwnd_(nullptr) +{ + instance_extensions_.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); + init_vk(); +} + +ShellWin32::~ShellWin32() +{ + cleanup_vk(); + FreeLibrary(hmodule_); +} + +void ShellWin32::create_window() +{ + const std::string class_name(settings_.name + "WindowClass"); + + hinstance_ = GetModuleHandle(nullptr); + + WNDCLASSEX win_class = {}; + win_class.cbSize = sizeof(WNDCLASSEX); + win_class.style = CS_HREDRAW | CS_VREDRAW; + win_class.lpfnWndProc = window_proc; + win_class.hInstance = hinstance_; + win_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + win_class.lpszClassName = class_name.c_str(); + RegisterClassEx(&win_class); + + const DWORD win_style = + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW; + + RECT win_rect = { 0, 0, settings_.initial_width, settings_.initial_height }; + AdjustWindowRect(&win_rect, win_style, false); + + hwnd_ = CreateWindowEx(WS_EX_APPWINDOW, + class_name.c_str(), + settings_.name.c_str(), + win_style, + 0, + 0, + win_rect.right - win_rect.left, + win_rect.bottom - win_rect.top, + nullptr, + nullptr, + hinstance_, + nullptr); + + SetForegroundWindow(hwnd_); + SetWindowLongPtr(hwnd_, GWLP_USERDATA, (LONG_PTR) this); +} + +PFN_vkGetInstanceProcAddr ShellWin32::load_vk() +{ + const char filename[] = "vulkan-1.dll"; + HMODULE mod; + PFN_vkGetInstanceProcAddr get_proc; + + mod = LoadLibrary(filename); + if (mod) { + get_proc = reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetProcAddress( + mod, "vkGetInstanceProcAddr")); + } + + if (!mod || !get_proc) { + std::stringstream ss; + ss << "failed to load " << filename; + + if (mod) + FreeLibrary(mod); + + throw std::runtime_error(ss.str()); + } + + hmodule_ = mod; + + return get_proc; +} + +bool ShellWin32::can_present(VkPhysicalDevice phy, uint32_t queue_family) +{ + return vk::GetPhysicalDeviceWin32PresentationSupportKHR(phy, queue_family); +} + +VkSurfaceKHR ShellWin32::create_surface(VkInstance instance) +{ + VkWin32SurfaceCreateInfoKHR surface_info = {}; + surface_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surface_info.hinstance = hinstance_; + surface_info.hwnd = hwnd_; + + VkSurfaceKHR surface; + vk::assert_success(vk::CreateWin32SurfaceKHR(instance, &surface_info, nullptr, &surface)); + + return surface; +} + +LRESULT ShellWin32::handle_message(UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) { + case WM_SIZE: + { + UINT w = LOWORD(lparam); + UINT h = HIWORD(lparam); + resize_swapchain(w, h); + } + break; + case WM_KEYDOWN: + { + Game::Key key; + + switch (wparam) { + case VK_ESCAPE: + key = Game::KEY_ESC; + break; + case VK_UP: + key = Game::KEY_UP; + break; + case VK_DOWN: + key = Game::KEY_DOWN; + break; + case VK_SPACE: + key = Game::KEY_SPACE; + break; + default: + key = Game::KEY_UNKNOWN; + break; + } + + game_.on_key(key); + } + break; + case WM_CLOSE: + game_.on_key(Game::KEY_SHUTDOWN); + break; + case WM_DESTROY: + quit(); + break; + default: + return DefWindowProc(hwnd_, msg, wparam, lparam); + break; + } + + return 0; +} + +void ShellWin32::quit() +{ + PostQuitMessage(0); +} + +void ShellWin32::run() +{ + create_window(); + + create_context(); + resize_swapchain(settings_.initial_width, settings_.initial_height); + + Win32Timer timer; + double current_time = timer.get(); + + while (true) { + bool quit = false; + + assert(settings_.animate); + + // process all messages + MSG msg; + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + quit = true; + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (quit) + break; + + acquire_back_buffer(); + + double t = timer.get(); + add_game_time(static_cast<float>(t - current_time)); + + present_back_buffer(); + + current_time = t; + } + + destroy_context(); + + DestroyWindow(hwnd_); +} |
