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
Kristian Høgsberg 12 years ago
parent fe7aa90ed4
commit 9e885d4bec
  1. 40
      clients/simple-egl.c

@ -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 = {

Loading…
Cancel
Save