From 3dc48ef05ec5c452f69fd8ccf9ea457a14b62941 Mon Sep 17 00:00:00 2001 From: Attila Uygun Date: Sat, 1 Jul 2023 21:36:26 +0200 Subject: [PATCH] Implement window resize --- src/engine/engine.cc | 41 ++++++++++--------- src/engine/engine.h | 2 + src/engine/platform/platform_linux.cc | 6 ++- src/engine/renderer/opengl/renderer_opengl.cc | 16 +++++++- src/engine/renderer/opengl/renderer_opengl.h | 8 ++++ .../renderer/opengl/renderer_opengl_linux.cc | 9 ++-- src/engine/renderer/renderer.h | 11 +++-- src/engine/renderer/vulkan/renderer_vulkan.cc | 26 ++++++++---- src/engine/renderer/vulkan/renderer_vulkan.h | 5 +++ .../vulkan/renderer_vulkan_android.cc | 7 ++-- .../renderer/vulkan/renderer_vulkan_linux.cc | 4 +- src/engine/renderer/vulkan/vulkan_context.h | 4 +- 12 files changed, 90 insertions(+), 49 deletions(-) diff --git a/src/engine/engine.cc b/src/engine/engine.cc index 9f93114..f727985 100644 --- a/src/engine/engine.cc +++ b/src/engine/engine.cc @@ -113,18 +113,7 @@ void Engine::Initialize() { CreateRendererInternal(RendererType::kVulkan); - // Normalize viewport. - if (GetScreenWidth() > GetScreenHeight()) { - float aspect_ratio = (float)GetScreenWidth() / (float)GetScreenHeight(); - LOG(0) << "aspect ratio: " << aspect_ratio; - screen_size_ = {aspect_ratio * 2.0f, 2.0f}; - projection_.CreateOrthoProjection(-aspect_ratio, aspect_ratio, -1.0f, 1.0f); - } else { - float aspect_ratio = (float)GetScreenHeight() / (float)GetScreenWidth(); - LOG(0) << "aspect_ratio: " << aspect_ratio; - screen_size_ = {2.0f, aspect_ratio * 2.0f}; - projection_.CreateOrthoProjection(-1.0, 1.0, -aspect_ratio, aspect_ratio); - } + CreateProjectionMatrix(); LOG(0) << "image scale factor: " << GetImageScaleFactor(); @@ -458,11 +447,11 @@ TextureCompressor* Engine::GetTextureCompressor(bool opacity) { } int Engine::GetScreenWidth() const { - return renderer_->screen_width(); + return renderer_->GetScreenWidth(); } int Engine::GetScreenHeight() const { - return renderer_->screen_height(); + return renderer_->GetScreenHeight(); } int Engine::GetDeviceDpi() const { @@ -470,7 +459,7 @@ int Engine::GetDeviceDpi() const { } float Engine::GetImageScaleFactor() const { - float width_inch = static_cast(renderer_->screen_width()) / + float width_inch = static_cast(renderer_->GetScreenWidth()) / static_cast(platform_->GetDeviceDpi()); return 2.57143f / width_inch; } @@ -504,10 +493,10 @@ void Engine::OnWindowDestroyed() { } void Engine::OnWindowResized(int width, int height) { - if (width != renderer_->screen_width() || - height != renderer_->screen_height()) { - renderer_->Shutdown(); - renderer_->Initialize(platform_); + if (width != renderer_->GetScreenWidth() || + height != renderer_->GetScreenHeight()) { + renderer_->OnWindowResized(width, height); + CreateProjectionMatrix(); } } @@ -615,6 +604,20 @@ void Engine::CreateTextureCompressors() { } } +void Engine::CreateProjectionMatrix() { + if (GetScreenWidth() > GetScreenHeight()) { + float aspect_ratio = (float)GetScreenWidth() / (float)GetScreenHeight(); + LOG(0) << "aspect ratio: " << aspect_ratio; + screen_size_ = {aspect_ratio * 2.0f, 2.0f}; + projection_.CreateOrthoProjection(-aspect_ratio, aspect_ratio, -1.0f, 1.0f); + } else { + float aspect_ratio = (float)GetScreenHeight() / (float)GetScreenWidth(); + LOG(0) << "aspect_ratio: " << aspect_ratio; + screen_size_ = {2.0f, aspect_ratio * 2.0f}; + projection_.CreateOrthoProjection(-1.0, 1.0, -aspect_ratio, aspect_ratio); + } +} + void Engine::ContextLost() { CreateRenderResources(); WaitForAsyncWork(); diff --git a/src/engine/engine.h b/src/engine/engine.h index 525a20b..e6f1b53 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -239,6 +239,8 @@ class Engine : public PlatformObserver { void CreateTextureCompressors(); + void CreateProjectionMatrix(); + void ContextLost(); void CreateRenderResources(); diff --git a/src/engine/platform/platform_linux.cc b/src/engine/platform/platform_linux.cc index 581eb1e..51c8868 100644 --- a/src/engine/platform/platform_linux.cc +++ b/src/engine/platform/platform_linux.cc @@ -30,7 +30,7 @@ Platform::Platform() { XSelectInput(display_, window_, KeyPressMask | Button1MotionMask | ButtonPressMask | - ButtonReleaseMask | FocusChangeMask); + ButtonReleaseMask | FocusChangeMask | StructureNotifyMask); Atom WM_DELETE_WINDOW = XInternAtom(display_, "WM_DELETE_WINDOW", false); XSetWMProtocols(display_, window_, &WM_DELETE_WINDOW, 1); } @@ -91,6 +91,10 @@ void Platform::Update() { should_exit_ = true; break; } + case ConfigureNotify: { + XConfigureEvent xce = e.xconfigure; + observer_->OnWindowResized(xce.width, xce.height); + } } } } diff --git a/src/engine/renderer/opengl/renderer_opengl.cc b/src/engine/renderer/opengl/renderer_opengl.cc index 7bc2997..19ae60e 100644 --- a/src/engine/renderer/opengl/renderer_opengl.cc +++ b/src/engine/renderer/opengl/renderer_opengl.cc @@ -46,6 +46,20 @@ void RendererOpenGL::Shutdown() { ShutdownInternal(); } +void RendererOpenGL::OnWindowResized(int width, int height) { + screen_width_ = width; + screen_height_ = height; + glViewport(0, 0, screen_width_, screen_height_); +} + +int RendererOpenGL::GetScreenWidth() const { + return screen_width_; +} + +int RendererOpenGL::GetScreenHeight() const { + return screen_height_; +} + uint64_t RendererOpenGL::CreateGeometry(std::unique_ptr mesh) { // Verify that we have a valid layout and get the total byte size per vertex. GLuint vertex_size = mesh->GetVertexSize(); @@ -483,8 +497,6 @@ bool RendererOpenGL::InitCommon() { LOG(0) << " etc1: " << texture_compression_.etc1; LOG(0) << " s3tc: " << texture_compression_.s3tc; - glViewport(0, 0, screen_width_, screen_height_); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index a2e04d2..d4f10ec 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -25,6 +25,11 @@ class RendererOpenGL final : public Renderer { bool IsInitialzed() const final { return is_initialized_; } + void OnWindowResized(int width, int height) final; + + int GetScreenWidth() const final; + int GetScreenHeight() const final; + uint64_t CreateGeometry(std::unique_ptr mesh) final; void DestroyGeometry(uint64_t resource_id) final; void Draw(uint64_t resource_id) final; @@ -109,6 +114,9 @@ class RendererOpenGL final : public Renderer { // Stats. size_t fps_ = 0; + int screen_width_ = 0; + int screen_height_ = 0; + #if defined(__ANDROID__) ANativeWindow* window_; #elif defined(__linux__) diff --git a/src/engine/renderer/opengl/renderer_opengl_linux.cc b/src/engine/renderer/opengl/renderer_opengl_linux.cc index 4e5e4bc..c1c6d4e 100644 --- a/src/engine/renderer/opengl/renderer_opengl_linux.cc +++ b/src/engine/renderer/opengl/renderer_opengl_linux.cc @@ -11,11 +11,6 @@ bool RendererOpenGL::Initialize(Platform* platform) { display_ = platform->GetDisplay(); window_ = platform->GetWindow(); - XWindowAttributes xwa; - XGetWindowAttributes(display_, window_, &xwa); - screen_width_ = xwa.width; - screen_height_ = xwa.height; - GLint glx_attributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None}; XVisualInfo* visual_info = glXChooseVisual(display_, 0, glx_attributes); @@ -32,6 +27,10 @@ bool RendererOpenGL::Initialize(Platform* platform) { return false; } + XWindowAttributes xwa; + XGetWindowAttributes(display_, window_, &xwa); + OnWindowResized(xwa.width, xwa.height); + return InitCommon(); } diff --git a/src/engine/renderer/renderer.h b/src/engine/renderer/renderer.h index d0dae50..e01e7d6 100644 --- a/src/engine/renderer/renderer.h +++ b/src/engine/renderer/renderer.h @@ -30,6 +30,11 @@ class Renderer { virtual bool IsInitialzed() const = 0; + virtual void OnWindowResized(int width, int height) = 0; + + virtual int GetScreenWidth() const = 0; + virtual int GetScreenHeight() const = 0; + virtual uint64_t CreateGeometry(std::unique_ptr mesh) = 0; virtual void DestroyGeometry(uint64_t resource_id) = 0; virtual void Draw(uint64_t resource_id) = 0; @@ -77,9 +82,6 @@ class Renderer { bool SupportsDXT5() const { return texture_compression_.s3tc; } bool SupportsATC() const { return texture_compression_.atc; } - int screen_width() const { return screen_width_; } - int screen_height() const { return screen_height_; } - virtual size_t GetAndResetFPS() = 0; virtual const char* GetDebugName() = 0; @@ -106,9 +108,6 @@ class Renderer { TextureCompression texture_compression_; - int screen_width_ = 0; - int screen_height_ = 0; - base::Closure context_lost_cb_; Renderer(const Renderer&) = delete; diff --git a/src/engine/renderer/vulkan/renderer_vulkan.cc b/src/engine/renderer/vulkan/renderer_vulkan.cc index 075b1ee..27ac937 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan.cc @@ -377,6 +377,18 @@ RendererVulkan::~RendererVulkan() { Shutdown(); } +void RendererVulkan::OnWindowResized(int width, int height) { + context_.ResizeWindow(width, height); +} + +int RendererVulkan::GetScreenWidth() const { + return context_.GetWindowWidth(); +} + +int RendererVulkan::GetScreenHeight() const { + return context_.GetWindowHeight(); +} + uint64_t RendererVulkan::CreateGeometry(std::unique_ptr mesh) { auto& geometry = geometries_[++last_resource_id_] = {}; @@ -1915,8 +1927,8 @@ void RendererVulkan::DrawListBegin() { render_pass_begin.renderPass = context_.GetRenderPass(); render_pass_begin.framebuffer = context_.GetFramebuffer(); - render_pass_begin.renderArea.extent.width = screen_width_; - render_pass_begin.renderArea.extent.height = screen_height_; + render_pass_begin.renderArea.extent.width = context_.GetWindowWidth(); + render_pass_begin.renderArea.extent.height = context_.GetWindowHeight(); render_pass_begin.renderArea.offset.x = 0; render_pass_begin.renderArea.offset.y = 0; @@ -1932,9 +1944,9 @@ void RendererVulkan::DrawListBegin() { VkViewport viewport; viewport.x = 0; - viewport.y = (float)screen_height_; - viewport.width = (float)screen_width_; - viewport.height = -(float)screen_height_; + viewport.y = (float)context_.GetWindowHeight(); + viewport.width = (float)context_.GetWindowWidth(); + viewport.height = -(float)context_.GetWindowHeight(); viewport.minDepth = 0; viewport.maxDepth = 1.0; @@ -1943,8 +1955,8 @@ void RendererVulkan::DrawListBegin() { VkRect2D scissor; scissor.offset.x = 0; scissor.offset.y = 0; - scissor.extent.width = screen_width_; - scissor.extent.height = screen_height_; + scissor.extent.width = context_.GetWindowWidth(); + scissor.extent.height = context_.GetWindowHeight(); vkCmdSetScissor(command_buffer, 0, 1, &scissor); } diff --git a/src/engine/renderer/vulkan/renderer_vulkan.h b/src/engine/renderer/vulkan/renderer_vulkan.h index 544f6b0..0b47b5b 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.h +++ b/src/engine/renderer/vulkan/renderer_vulkan.h @@ -28,6 +28,11 @@ class RendererVulkan final : public Renderer { bool IsInitialzed() const final { return device_ != VK_NULL_HANDLE; } + void OnWindowResized(int width, int height) final; + + int GetScreenWidth() const final; + int GetScreenHeight() const final; + uint64_t CreateGeometry(std::unique_ptr mesh) final; void DestroyGeometry(uint64_t resource_id) final; void Draw(uint64_t resource_id) final; diff --git a/src/engine/renderer/vulkan/renderer_vulkan_android.cc b/src/engine/renderer/vulkan/renderer_vulkan_android.cc index 719beff..51f29a2 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan_android.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan_android.cc @@ -10,15 +10,14 @@ namespace eng { bool RendererVulkan::Initialize(Platform* platform) { LOG(0) << "Initializing renderer."; - screen_width_ = ANativeWindow_getWidth(platform->GetWindow()); - screen_height_ = ANativeWindow_getHeight(platform->GetWindow()); + int width = ANativeWindow_getWidth(platform->GetWindow()); + int height = ANativeWindow_getHeight(platform->GetWindow()); if (!context_.Initialize()) { LOG(0) << "Failed to initialize Vulkan context."; return false; } - if (!context_.CreateWindow(platform->GetWindow(), screen_width_, - screen_height_)) { + if (!context_.CreateWindow(platform->GetWindow(), width, height)) { LOG(0) << "Vulkan context failed to create window."; return false; } diff --git a/src/engine/renderer/vulkan/renderer_vulkan_linux.cc b/src/engine/renderer/vulkan/renderer_vulkan_linux.cc index 9134584..9db7491 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan_linux.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan_linux.cc @@ -10,15 +10,13 @@ bool RendererVulkan::Initialize(Platform* platform) { XWindowAttributes xwa; XGetWindowAttributes(platform->GetDisplay(), platform->GetWindow(), &xwa); - screen_width_ = xwa.width; - screen_height_ = xwa.height; if (!context_.Initialize()) { LOG(0) << "Failed to initialize Vulkan context."; return false; } if (!context_.CreateWindow(platform->GetDisplay(), platform->GetWindow(), - screen_width_, screen_height_)) { + xwa.width, xwa.height)) { LOG(0) << "Vulkan context failed to create window."; return false; } diff --git a/src/engine/renderer/vulkan/vulkan_context.h b/src/engine/renderer/vulkan/vulkan_context.h index ff5107d..5537483 100644 --- a/src/engine/renderer/vulkan/vulkan_context.h +++ b/src/engine/renderer/vulkan/vulkan_context.h @@ -58,8 +58,8 @@ class VulkanContext { VkPhysicalDeviceLimits GetDeviceLimits() const { return gpu_props_.limits; } - int GetWidth() { return window_.width; } - int GetHeight() { return window_.height; } + int GetWindowWidth() const { return window_.width; } + int GetWindowHeight() const { return window_.height; } size_t GetAndResetFPS();