Compare commits
6 Commits
master
...
damage-tra
Author | SHA1 | Date | |
---|---|---|---|
|
8e51c4a577 | ||
|
c8233ce7d3 | ||
|
0d2ce23071 | ||
|
a94b96c954 | ||
|
8e354c2259 | ||
|
e0b1f518cf |
@ -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,49 @@ 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
|
||||
* @sa @ref glfwGetBufferAge
|
||||
*
|
||||
* @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
|
||||
@ -5639,6 +5710,36 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
|
||||
*/
|
||||
GLFWAPI void glfwSwapInterval(int interval);
|
||||
|
||||
/*! @brief Returns the buffer age of the window’s current buffer.
|
||||
*
|
||||
* This function returns the age of the current buffer, in frames. It may be
|
||||
* used to redraw only the parts of the buffer that have changed since this
|
||||
* buffer was last used, thus avoiding a clear and draw of the entire buffer.
|
||||
*
|
||||
* A context must be current on the calling thread. Calling this function
|
||||
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
|
||||
*
|
||||
* This function does not apply to Vulkan. If you are rendering with Vulkan,
|
||||
* see the present mode of your swapchain instead.
|
||||
*
|
||||
* @param[in] window The window whose buffers to swap.
|
||||
* @return The age of the back buffer if the extension is available, or 0
|
||||
* otherwise.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread.
|
||||
*
|
||||
* @sa @ref buffer_swap
|
||||
* @sa @ref glfwSwapBuffersWithDamage
|
||||
*
|
||||
* @since Added in version 3.4.
|
||||
*
|
||||
* @ingroup context
|
||||
*/
|
||||
GLFWAPI int glfwGetBufferAge(GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns whether the specified extension is available.
|
||||
*
|
||||
* This function returns whether the specified
|
||||
|
@ -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;
|
||||
@ -674,6 +694,26 @@ GLFWAPI void glfwSwapInterval(int interval)
|
||||
window->context.swapInterval(interval);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetBufferAge(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
|
||||
if (window->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
||||
"Cannot get buffer age of a window that has no OpenGL or OpenGL ES context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (window->context.getBufferAge)
|
||||
return window->context.getBufferAge(window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
|
@ -232,11 +232,46 @@ static void swapBuffersEGL(_GLFWwindow* window)
|
||||
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
||||
}
|
||||
|
||||
static void swapBuffersWithDamageEGL(_GLFWwindow* window, GLFWrect* rects, int n_rects)
|
||||
{
|
||||
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||
return;
|
||||
}
|
||||
|
||||
if (eglSwapBuffersWithDamageKHR)
|
||||
eglSwapBuffersWithDamageKHR(_glfw.egl.display,
|
||||
window->context.egl.surface,
|
||||
(EGLint*)rects, (EGLint)n_rects);
|
||||
else
|
||||
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
||||
}
|
||||
|
||||
static void swapIntervalEGL(int interval)
|
||||
{
|
||||
eglSwapInterval(_glfw.egl.display, interval);
|
||||
}
|
||||
|
||||
static int getBufferAgeEGL(_GLFWwindow* window)
|
||||
{
|
||||
EGLint buffer_age;
|
||||
|
||||
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!eglQuerySurface(_glfw.egl.display, window->context.egl.surface,
|
||||
EGL_BUFFER_AGE_EXT, &buffer_age))
|
||||
return 0;
|
||||
|
||||
return buffer_age;
|
||||
}
|
||||
|
||||
static int extensionSupportedEGL(const char* extension)
|
||||
{
|
||||
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
|
||||
@ -367,6 +402,8 @@ GLFWbool _glfwInitEGL(void)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
||||
_glfw.egl.QueryString = (PFN_eglQueryString)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
||||
_glfw.egl.QuerySurface = (PFN_eglQuerySurface)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglQuerySurface");
|
||||
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
|
||||
|
||||
@ -385,6 +422,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
!_glfw.egl.SwapBuffers ||
|
||||
!_glfw.egl.SwapInterval ||
|
||||
!_glfw.egl.QueryString ||
|
||||
!_glfw.egl.QuerySurface ||
|
||||
!_glfw.egl.GetProcAddress)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@ -425,6 +463,12 @@ GLFWbool _glfwInitEGL(void)
|
||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||
_glfw.egl.KHR_context_flush_control =
|
||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||
_glfw.egl.KHR_swap_buffers_with_damage =
|
||||
extensionSupportedEGL("EGL_KHR_swap_buffers_with_damage");
|
||||
|
||||
if (_glfw.egl.KHR_swap_buffers_with_damage)
|
||||
_glfw.egl.SwapBuffersWithDamageKHR = (PFN_eglSwapBuffersWithDamageKHR)
|
||||
_glfw.egl.GetProcAddress("eglSwapBuffersWithDamageKHR");
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@ -694,7 +738,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
|
||||
window->context.makeCurrent = makeContextCurrentEGL;
|
||||
window->context.swapBuffers = swapBuffersEGL;
|
||||
window->context.swapBuffersWithDamage = swapBuffersWithDamageEGL;
|
||||
window->context.swapInterval = swapIntervalEGL;
|
||||
window->context.getBufferAge = getBufferAgeEGL;
|
||||
window->context.extensionSupported = extensionSupportedEGL;
|
||||
window->context.getProcAddress = getProcAddressEGL;
|
||||
window->context.destroy = destroyContextEGL;
|
||||
|
@ -107,6 +107,8 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||
|
||||
#define EGL_BUFFER_AGE_EXT 0x313D
|
||||
|
||||
typedef int EGLint;
|
||||
typedef unsigned int EGLBoolean;
|
||||
typedef unsigned int EGLenum;
|
||||
@ -131,7 +133,9 @@ typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLS
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
|
||||
typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglQuerySurface)(EGLDisplay,EGLSurface,EGLint,EGLint*);
|
||||
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffersWithDamageKHR)(EGLDisplay,EGLSurface,EGLint*,EGLint);
|
||||
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
||||
#define eglGetConfigs _glfw.egl.GetConfigs
|
||||
#define eglGetDisplay _glfw.egl.GetDisplay
|
||||
@ -147,7 +151,9 @@ typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
||||
#define eglSwapBuffers _glfw.egl.SwapBuffers
|
||||
#define eglSwapInterval _glfw.egl.SwapInterval
|
||||
#define eglQueryString _glfw.egl.QueryString
|
||||
#define eglQuerySurface _glfw.egl.QuerySurface
|
||||
#define eglGetProcAddress _glfw.egl.GetProcAddress
|
||||
#define eglSwapBuffersWithDamageKHR _glfw.egl.SwapBuffersWithDamageKHR
|
||||
|
||||
#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
|
||||
@ -178,6 +184,7 @@ typedef struct _GLFWlibraryEGL
|
||||
GLFWbool KHR_gl_colorspace;
|
||||
GLFWbool KHR_get_all_proc_addresses;
|
||||
GLFWbool KHR_context_flush_control;
|
||||
GLFWbool KHR_swap_buffers_with_damage;
|
||||
|
||||
void* handle;
|
||||
|
||||
@ -196,7 +203,9 @@ typedef struct _GLFWlibraryEGL
|
||||
PFN_eglSwapBuffers SwapBuffers;
|
||||
PFN_eglSwapInterval SwapInterval;
|
||||
PFN_eglQueryString QueryString;
|
||||
PFN_eglQuerySurface QuerySurface;
|
||||
PFN_eglGetProcAddress GetProcAddress;
|
||||
PFN_eglSwapBuffersWithDamageKHR SwapBuffersWithDamageKHR;
|
||||
|
||||
} _GLFWlibraryEGL;
|
||||
|
||||
|
@ -78,7 +78,9 @@ typedef struct _GLFWmutex _GLFWmutex;
|
||||
|
||||
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
||||
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
||||
typedef void (* _GLFWswapbufferswithdamagefun)(_GLFWwindow*,GLFWrect*,int);
|
||||
typedef void (* _GLFWswapintervalfun)(int);
|
||||
typedef int (* _GLFWgetbufferagefun)(_GLFWwindow*);
|
||||
typedef int (* _GLFWextensionsupportedfun)(const char*);
|
||||
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
|
||||
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||
@ -350,7 +352,9 @@ struct _GLFWcontext
|
||||
|
||||
_GLFWmakecontextcurrentfun makeCurrent;
|
||||
_GLFWswapbuffersfun swapBuffers;
|
||||
_GLFWswapbufferswithdamagefun swapBuffersWithDamage;
|
||||
_GLFWswapintervalfun swapInterval;
|
||||
_GLFWgetbufferagefun getBufferAge;
|
||||
_GLFWextensionsupportedfun extensionSupported;
|
||||
_GLFWgetprocaddressfun getProcAddress;
|
||||
_GLFWdestroycontextfun destroy;
|
||||
|
@ -783,7 +783,7 @@ static void registryHandleGlobal(void* data,
|
||||
{
|
||||
if (strcmp(interface, "wl_compositor") == 0)
|
||||
{
|
||||
_glfw.wl.compositorVersion = min(3, version);
|
||||
_glfw.wl.compositorVersion = min(4, version);
|
||||
_glfw.wl.compositor =
|
||||
wl_registry_bind(registry, name, &wl_compositor_interface,
|
||||
_glfw.wl.compositorVersion);
|
||||
|
20
tests/msaa.c
20
tests/msaa.c
@ -102,6 +102,19 @@ int main(int argc, char** argv)
|
||||
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
|
||||
GLint mvp_location, vpos_location;
|
||||
|
||||
// Minimum static damage for both squares.
|
||||
GLFWrect rects[8] =
|
||||
{{ 25, 25, 350, 90},
|
||||
{ 25, 285, 350, 90},
|
||||
{ 25, 115, 90, 170},
|
||||
{285, 115, 90, 170},
|
||||
|
||||
{425, 25, 350, 90},
|
||||
{425, 285, 350, 90},
|
||||
{425, 115, 90, 170},
|
||||
{685, 115, 90, 170},
|
||||
};
|
||||
|
||||
while ((ch = getopt(argc, argv, "hs:")) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
@ -178,11 +191,13 @@ int main(int argc, char** argv)
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
float ratio;
|
||||
int buffer_age;
|
||||
int width, height;
|
||||
mat4x4 m, p, mvp;
|
||||
const double angle = glfwGetTime() * M_PI / 180.0;
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
buffer_age = glfwGetBufferAge(window);
|
||||
ratio = width / (float) height;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
@ -208,6 +223,11 @@ int main(int argc, char** argv)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
// If buffer_age is 0, we can’t assume anything about the previous buffer
|
||||
// so swap the entire buffer.
|
||||
if (buffer_age > 0)
|
||||
glfwSwapBuffersWithDamage(window, rects, 8);
|
||||
else
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user