From e0b1f518cf2da9d8e7c29cc02efc77b6cc7a58f0 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 28 Nov 2019 15:47:53 +0100 Subject: [PATCH] Add a glfwSwapBuffersWithDamage() symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new API helps the user’s compositor reduce memory bandwidth and thus power usage by only re-rendering a bunch of dirty rectangles instead of the entire application buffer. There is no guarantee that it will effectively get used, it is perfectly valid to continue damaging the entire buffer instead like with glfwSwapBuffers() in some cases. --- include/GLFW/glfw3.h | 70 ++++++++++++++++++++++++++++++++++++++++++++ src/context.c | 20 +++++++++++++ src/internal.h | 2 ++ 3 files changed, 92 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8b5b87dd..a918baa5 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1780,6 +1780,33 @@ typedef struct GLFWimage unsigned char* pixels; } GLFWimage; +/*! @brief Rectangle. + * + * This describes a single 2D box. The origin is the bottom-left point of the + * window. + * + * @sa @ref buffer_swap + * + * @since Added in version 3.4. + * + * @ingroup window + */ +typedef struct GLFWrect +{ + /*! The starting horizontal coordinate, in pixels, of this rect. + */ + int x; + /*! The starting vertical coordinate, in pixels, of this rect. + */ + int y; + /*! The width, in pixels, of this rect. + */ + int width; + /*! The height, in pixels, of this rect. + */ + int height; +} GLFWrect; + /*! @brief Gamepad input state * * This describes the input state of a gamepad. @@ -5584,6 +5611,7 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void); * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap + * @sa @ref glfwSwapBuffersWithDamage * @sa @ref glfwSwapInterval * * @since Added in version 1.0. @@ -5593,6 +5621,48 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void); */ GLFWAPI void glfwSwapBuffers(GLFWwindow* window); +/*! @brief Swaps the front and back buffers of the specified window with damage + * hints. + * + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * On supported platforms, this function can damage only the specified rects + * instead of the entire buffer. This is only one possible behaviour, it is + * perfectly acceptable to damage the entire buffer so you shouldn’t rely on + * that and keep providing a fully up to date buffer. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. + * + * @param[in] window The window whose buffers to swap. + * @param[in] rects The rects to update. + * @param[in] n_rects How many rects there are. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref buffer_swap + * @sa @ref glfwSwapBuffers + * @sa @ref glfwSwapInterval + * + * @since Added in version 3.4. + * + * @ingroup window + */ +GLFWAPI void glfwSwapBuffersWithDamage(GLFWwindow* window, GLFWrect* rects, int n_rects); + /*! @brief Sets the swap interval for the current context. * * This function sets the swap interval for the current OpenGL or OpenGL ES diff --git a/src/context.c b/src/context.c index 48311e5f..8f5b868a 100644 --- a/src/context.c +++ b/src/context.c @@ -657,6 +657,26 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) window->context.swapBuffers(window); } +GLFWAPI void glfwSwapBuffersWithDamage(GLFWwindow* handle, GLFWrect* rects, int n_rects) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + if (window->context.client == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, + "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context"); + return; + } + + if (window->context.swapBuffersWithDamage) + window->context.swapBuffersWithDamage(window, rects, n_rects); + else + window->context.swapBuffers(window); +} + GLFWAPI void glfwSwapInterval(int interval) { _GLFWwindow* window; diff --git a/src/internal.h b/src/internal.h index 4c75c9b1..ab0d1ebd 100644 --- a/src/internal.h +++ b/src/internal.h @@ -78,6 +78,7 @@ typedef struct _GLFWmutex _GLFWmutex; typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*); typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*); +typedef void (* _GLFWswapbufferswithdamagefun)(_GLFWwindow*,GLFWrect*,int); typedef void (* _GLFWswapintervalfun)(int); typedef int (* _GLFWextensionsupportedfun)(const char*); typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*); @@ -350,6 +351,7 @@ struct _GLFWcontext _GLFWmakecontextcurrentfun makeCurrent; _GLFWswapbuffersfun swapBuffers; + _GLFWswapbufferswithdamagefun swapBuffersWithDamage; _GLFWswapintervalfun swapInterval; _GLFWextensionsupportedfun extensionSupported; _GLFWgetprocaddressfun getProcAddress;