Add a glfwSwapBuffersWithDamage() symbol

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.
This commit is contained in:
Emmanuel Gil Peyrot 2019-11-28 15:47:53 +01:00
parent 7dbdd2e6a5
commit e0b1f518cf
3 changed files with 92 additions and 0 deletions

View File

@ -1780,6 +1780,33 @@ typedef struct GLFWimage
unsigned char* pixels; unsigned char* pixels;
} GLFWimage; } 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 /*! @brief Gamepad input state
* *
* This describes the input state of a gamepad. * 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. * @thread_safety This function may be called from any thread.
* *
* @sa @ref buffer_swap * @sa @ref buffer_swap
* @sa @ref glfwSwapBuffersWithDamage
* @sa @ref glfwSwapInterval * @sa @ref glfwSwapInterval
* *
* @since Added in version 1.0. * @since Added in version 1.0.
@ -5593,6 +5621,48 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
*/ */
GLFWAPI void glfwSwapBuffers(GLFWwindow* window); 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 shouldnt 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. /*! @brief Sets the swap interval for the current context.
* *
* This function sets the swap interval for the current OpenGL or OpenGL ES * This function sets the swap interval for the current OpenGL or OpenGL ES

View File

@ -657,6 +657,26 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
window->context.swapBuffers(window); 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) GLFWAPI void glfwSwapInterval(int interval)
{ {
_GLFWwindow* window; _GLFWwindow* window;

View File

@ -78,6 +78,7 @@ typedef struct _GLFWmutex _GLFWmutex;
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*); typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*); typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
typedef void (* _GLFWswapbufferswithdamagefun)(_GLFWwindow*,GLFWrect*,int);
typedef void (* _GLFWswapintervalfun)(int); typedef void (* _GLFWswapintervalfun)(int);
typedef int (* _GLFWextensionsupportedfun)(const char*); typedef int (* _GLFWextensionsupportedfun)(const char*);
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*); typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
@ -350,6 +351,7 @@ struct _GLFWcontext
_GLFWmakecontextcurrentfun makeCurrent; _GLFWmakecontextcurrentfun makeCurrent;
_GLFWswapbuffersfun swapBuffers; _GLFWswapbuffersfun swapBuffers;
_GLFWswapbufferswithdamagefun swapBuffersWithDamage;
_GLFWswapintervalfun swapInterval; _GLFWswapintervalfun swapInterval;
_GLFWextensionsupportedfun extensionSupported; _GLFWextensionsupportedfun extensionSupported;
_GLFWgetprocaddressfun getProcAddress; _GLFWgetprocaddressfun getProcAddress;