diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h index 00a032d5..fe8240e2 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h @@ -1,25 +1,60 @@ #pragma once #include +#include namespace XCEngine { namespace RHI { +enum class PresentMode { + Immediate, + VSync, + Mailbox, + Fifo +}; + +enum class SurfaceFormat { + RGBA8, + RGBA16F, + RGBA32F, + BGRA8 +}; + class OpenGLSwapChain { public: OpenGLSwapChain(); ~OpenGLSwapChain(); - bool Initialize(GLFWwindow* window); + bool Initialize(GLFWwindow* window, bool vsync = true); + bool Initialize(GLFWwindow* window, int width, int height, PresentMode mode = PresentMode::VSync); void Shutdown(); void Present(); void SwapBuffers(); + void Resize(int width, int height); + void SetVSync(bool enabled); + bool IsVSync() const { return m_vsync; } + + void SetFramebufferSize(int width, int height); + int GetWidth() const { return m_width; } + int GetHeight() const { return m_height; } + int GetFramebufferWidth() const { return m_framebufferWidth; } + int GetFramebufferHeight() const { return m_framebufferHeight; } GLFWwindow* GetWindow() const { return m_window; } + bool ShouldClose() const; + void SetShouldClose(bool shouldClose); + void PollEvents(); + private: GLFWwindow* m_window; + int m_width; + int m_height; + int m_framebufferWidth; + int m_framebufferHeight; + bool m_vsync; + PresentMode m_presentMode; }; } // namespace RHI diff --git a/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp b/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp index c07c3b0f..1f94c9e7 100644 --- a/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp +++ b/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp @@ -1,18 +1,70 @@ #define GLFW_INCLUDE_NONE #include "XCEngine/RHI/OpenGL/OpenGLSwapChain.h" #include +#include namespace XCEngine { namespace RHI { -OpenGLSwapChain::OpenGLSwapChain() : m_window(nullptr) { +static int ToGLFWPresentMode(PresentMode mode) { + switch (mode) { + case PresentMode::Immediate: return 0; + case PresentMode::VSync: return 1; + case PresentMode::Mailbox: return -1; + case PresentMode::Fifo: return 1; + default: return 1; + } +} + +OpenGLSwapChain::OpenGLSwapChain() + : m_window(nullptr) + , m_width(0) + , m_height(0) + , m_framebufferWidth(0) + , m_framebufferHeight(0) + , m_vsync(true) + , m_presentMode(PresentMode::VSync) { } OpenGLSwapChain::~OpenGLSwapChain() { + Shutdown(); } -bool OpenGLSwapChain::Initialize(GLFWwindow* window) { +bool OpenGLSwapChain::Initialize(GLFWwindow* window, bool vsync) { m_window = window; + m_vsync = vsync; + m_presentMode = vsync ? PresentMode::VSync : PresentMode::Immediate; + + int w, h; + glfwGetFramebufferSize(window, &w, &h); + m_framebufferWidth = w; + m_framebufferHeight = h; + + glfwGetWindowSize(window, &w, &h); + m_width = w; + m_height = h; + + glfwSwapInterval(m_vsync ? 1 : 0); + + return true; +} + +bool OpenGLSwapChain::Initialize(GLFWwindow* window, int width, int height, PresentMode mode) { + m_window = window; + m_width = width; + m_height = height; + m_presentMode = mode; + m_vsync = (mode == PresentMode::VSync || mode == PresentMode::Fifo); + + glfwSetWindowSize(window, width, height); + + int w, h; + glfwGetFramebufferSize(window, &w, &h); + m_framebufferWidth = w; + m_framebufferHeight = h; + + glfwSwapInterval(m_vsync ? 1 : 0); + return true; } @@ -21,11 +73,47 @@ void OpenGLSwapChain::Shutdown() { } void OpenGLSwapChain::Present() { - glfwSwapBuffers(m_window); + if (m_window) { + glfwSwapBuffers(m_window); + } } void OpenGLSwapChain::SwapBuffers() { - glfwSwapBuffers(m_window); + if (m_window) { + glfwSwapBuffers(m_window); + } +} + +void OpenGLSwapChain::Resize(int width, int height) { + m_width = width; + m_height = height; + if (m_window) { + glfwSetWindowSize(m_window, width, height); + } +} + +void OpenGLSwapChain::SetVSync(bool enabled) { + m_vsync = enabled; + glfwSwapInterval(enabled ? 1 : 0); +} + +void OpenGLSwapChain::SetFramebufferSize(int width, int height) { + m_framebufferWidth = width; + m_framebufferHeight = height; +} + +bool OpenGLSwapChain::ShouldClose() const { + return m_window && glfwWindowShouldClose(m_window); +} + +void OpenGLSwapChain::SetShouldClose(bool shouldClose) { + if (m_window) { + glfwSetWindowShouldClose(m_window, shouldClose ? GLFW_TRUE : GLFW_FALSE); + } +} + +void OpenGLSwapChain::PollEvents() { + glfwPollEvents(); } } // namespace RHI