simple-egl: Add support for EGL_EXT_swap_buffer_with_damage
This new EGL extension lets us communicate the damage area to the compositor by using eglSwapBuffersWithDamge() instead of the regular eglSwapBuffer(). http://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_swap_buffers_with_damage.txt
This commit is contained in:
+39
-1
@@ -36,6 +36,12 @@
|
|||||||
|
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#ifndef EGL_EXT_swap_buffers_with_damage
|
||||||
|
#define EGL_EXT_swap_buffers_with_damage 1
|
||||||
|
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct window;
|
struct window;
|
||||||
struct seat;
|
struct seat;
|
||||||
@@ -58,6 +64,8 @@ struct display {
|
|||||||
EGLConfig conf;
|
EGLConfig conf;
|
||||||
} egl;
|
} egl;
|
||||||
struct window *window;
|
struct window *window;
|
||||||
|
|
||||||
|
PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct geometry {
|
struct geometry {
|
||||||
@@ -107,6 +115,7 @@ init_egl(struct display *display, int opaque)
|
|||||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
const char *extensions;
|
||||||
|
|
||||||
EGLint config_attribs[] = {
|
EGLint config_attribs[] = {
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
@@ -141,6 +150,18 @@ init_egl(struct display *display, int opaque)
|
|||||||
EGL_NO_CONTEXT, context_attribs);
|
EGL_NO_CONTEXT, context_attribs);
|
||||||
assert(display->egl.ctx);
|
assert(display->egl.ctx);
|
||||||
|
|
||||||
|
display->swap_buffers_with_damage = NULL;
|
||||||
|
extensions = eglQueryString(display->egl.dpy, EGL_EXTENSIONS);
|
||||||
|
if (extensions &&
|
||||||
|
strstr(extensions, "EGL_EXT_swap_buffers_with_damage") &&
|
||||||
|
strstr(extensions, "EGL_EXT_buffer_age"))
|
||||||
|
display->swap_buffers_with_damage =
|
||||||
|
(PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)
|
||||||
|
eglGetProcAddress("eglSwapBuffersWithDamageEXT");
|
||||||
|
|
||||||
|
if (display->swap_buffers_with_damage)
|
||||||
|
printf("has EGL_EXT_buffer_age and EGL_EXT_swap_buffers_with_damage\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -346,6 +367,7 @@ static void
|
|||||||
redraw(void *data, struct wl_callback *callback, uint32_t time)
|
redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
{
|
{
|
||||||
struct window *window = data;
|
struct window *window = data;
|
||||||
|
struct display *display = window->display;
|
||||||
static const GLfloat verts[3][2] = {
|
static const GLfloat verts[3][2] = {
|
||||||
{ -0.5, -0.5 },
|
{ -0.5, -0.5 },
|
||||||
{ 0.5, -0.5 },
|
{ 0.5, -0.5 },
|
||||||
@@ -366,6 +388,8 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
|||||||
static const int32_t speed_div = 5;
|
static const int32_t speed_div = 5;
|
||||||
static uint32_t start_time = 0;
|
static uint32_t start_time = 0;
|
||||||
struct wl_region *region;
|
struct wl_region *region;
|
||||||
|
EGLint rect[4];
|
||||||
|
EGLint buffer_age = 0;
|
||||||
|
|
||||||
assert(window->callback == callback);
|
assert(window->callback == callback);
|
||||||
window->callback = NULL;
|
window->callback = NULL;
|
||||||
@@ -385,6 +409,10 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
|||||||
rotation[2][0] = -sin(angle);
|
rotation[2][0] = -sin(angle);
|
||||||
rotation[2][2] = cos(angle);
|
rotation[2][2] = cos(angle);
|
||||||
|
|
||||||
|
if (display->swap_buffers_with_damage)
|
||||||
|
eglQuerySurface(display->egl.dpy, window->egl_surface,
|
||||||
|
EGL_BUFFER_AGE_EXT, &buffer_age);
|
||||||
|
|
||||||
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||||
|
|
||||||
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
|
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
|
||||||
@@ -417,7 +445,17 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
|||||||
window->callback = wl_surface_frame(window->surface);
|
window->callback = wl_surface_frame(window->surface);
|
||||||
wl_callback_add_listener(window->callback, &frame_listener, window);
|
wl_callback_add_listener(window->callback, &frame_listener, window);
|
||||||
|
|
||||||
eglSwapBuffers(window->display->egl.dpy, window->egl_surface);
|
if (display->swap_buffers_with_damage && buffer_age > 0) {
|
||||||
|
rect[0] = window->geometry.width / 4 - 1;
|
||||||
|
rect[1] = window->geometry.height / 4 - 1;
|
||||||
|
rect[2] = window->geometry.width / 2 + 2;
|
||||||
|
rect[3] = window->geometry.height / 2 + 2;
|
||||||
|
display->swap_buffers_with_damage(display->egl.dpy,
|
||||||
|
window->egl_surface,
|
||||||
|
rect, 1);
|
||||||
|
} else {
|
||||||
|
eglSwapBuffers(display->egl.dpy, window->egl_surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener = {
|
static const struct wl_callback_listener frame_listener = {
|
||||||
|
|||||||
Reference in New Issue
Block a user