Swap buffers with damage

This commit is contained in:
emersion 2018-02-09 22:54:14 +01:00
parent 34489dca16
commit bf6d245400
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
11 changed files with 80 additions and 33 deletions

View File

@ -190,7 +190,8 @@ static bool wlr_drm_connector_make_current(struct wlr_output *output,
return wlr_drm_surface_make_current(&conn->crtc->primary->surf, buffer_age); return wlr_drm_surface_make_current(&conn->crtc->primary->surf, buffer_age);
} }
static bool wlr_drm_connector_swap_buffers(struct wlr_output *output) { static bool wlr_drm_connector_swap_buffers(struct wlr_output *output,
pixman_region32_t *damage) {
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
if (!drm->session->active) { if (!drm->session->active) {
@ -203,7 +204,7 @@ static bool wlr_drm_connector_swap_buffers(struct wlr_output *output) {
} }
struct wlr_drm_plane *plane = crtc->primary; struct wlr_drm_plane *plane = crtc->primary;
struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf); struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf, damage);
if (drm->parent) { if (drm->parent) {
bo = wlr_drm_surface_mgpu_copy(&plane->mgpu_surf, bo); bo = wlr_drm_surface_mgpu_copy(&plane->mgpu_surf, bo);
} }
@ -635,7 +636,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
GL_UNSIGNED_BYTE, bo_data); GL_UNSIGNED_BYTE, bo_data);
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
wlr_drm_surface_swap_buffers(&plane->surf); wlr_drm_surface_swap_buffers(&plane->surf, NULL);
gbm_bo_unmap(bo, bo_data); gbm_bo_unmap(bo, bo_data);

View File

@ -133,14 +133,13 @@ bool wlr_drm_surface_make_current(struct wlr_drm_surface *surf,
return wlr_egl_make_current(&surf->renderer->egl, surf->egl, buffer_damage); return wlr_egl_make_current(&surf->renderer->egl, surf->egl, buffer_damage);
} }
struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf) { struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf,
pixman_region32_t *damage) {
if (surf->front) { if (surf->front) {
gbm_surface_release_buffer(surf->gbm, surf->front); gbm_surface_release_buffer(surf->gbm, surf->front);
} }
if (!eglSwapBuffers(surf->renderer->egl.display, surf->egl)) { wlr_egl_swap_buffers(&surf->renderer->egl, surf->egl, damage);
wlr_log(L_ERROR, "eglSwapBuffers failed");
}
surf->front = surf->back; surf->front = surf->back;
surf->back = gbm_surface_lock_front_buffer(surf->gbm); surf->back = gbm_surface_lock_front_buffer(surf->gbm);
@ -156,7 +155,7 @@ struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) {
glViewport(0, 0, surf->width, surf->height); glViewport(0, 0, surf->width, surf->height);
glClearColor(0.0, 0.0, 0.0, 1.0); glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
return wlr_drm_surface_swap_buffers(surf); return wlr_drm_surface_swap_buffers(surf, NULL);
} }
void wlr_drm_surface_post(struct wlr_drm_surface *surf) { void wlr_drm_surface_post(struct wlr_drm_surface *surf) {
@ -244,7 +243,7 @@ struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest,
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
wlr_render_with_matrix(dest->renderer->wlr_rend, tex, &matrix); wlr_render_with_matrix(dest->renderer->wlr_rend, tex, &matrix);
return wlr_drm_surface_swap_buffers(dest); return wlr_drm_surface_swap_buffers(dest, NULL);
} }
bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm, bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm,

View File

@ -55,7 +55,8 @@ static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age)
buffer_age); buffer_age);
} }
static bool output_swap_buffers(struct wlr_output *wlr_output) { static bool output_swap_buffers(struct wlr_output *wlr_output,
pixman_region32_t *damage) {
return true; // No-op return true; // No-op
} }

View File

@ -47,7 +47,8 @@ static bool wlr_wl_output_make_current(struct wlr_output *wlr_output,
buffer_age); buffer_age);
} }
static bool wlr_wl_output_swap_buffers(struct wlr_output *wlr_output) { static bool wlr_wl_output_swap_buffers(struct wlr_output *wlr_output,
pixman_region32_t *damage) {
struct wlr_wl_backend_output *output = struct wlr_wl_backend_output *output =
(struct wlr_wl_backend_output *)wlr_output; (struct wlr_wl_backend_output *)wlr_output;
@ -59,12 +60,8 @@ static bool wlr_wl_output_swap_buffers(struct wlr_output *wlr_output) {
output->frame_callback = wl_surface_frame(output->surface); output->frame_callback = wl_surface_frame(output->surface);
wl_callback_add_listener(output->frame_callback, &frame_listener, output); wl_callback_add_listener(output->frame_callback, &frame_listener, output);
if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) { return wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface,
wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error()); damage);
return false;
}
return true;
} }
static void wlr_wl_output_transform(struct wlr_output *_output, static void wlr_wl_output_transform(struct wlr_output *_output,

View File

@ -401,16 +401,12 @@ static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age)
return wlr_egl_make_current(&x11->egl, output->surf, buffer_age); return wlr_egl_make_current(&x11->egl, output->surf, buffer_age);
} }
static bool output_swap_buffers(struct wlr_output *wlr_output) { static bool output_swap_buffers(struct wlr_output *wlr_output,
pixman_region32_t *damage) {
struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output;
struct wlr_x11_backend *x11 = output->x11; struct wlr_x11_backend *x11 = output->x11;
if (!eglSwapBuffers(x11->egl.display, output->surf)) { return wlr_egl_swap_buffers(&x11->egl, output->surf, damage);
wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
return false;
}
return true;
} }
static struct wlr_output_impl output_impl = { static struct wlr_output_impl output_impl = {

View File

@ -41,14 +41,17 @@ bool wlr_drm_surface_init(struct wlr_drm_surface *surf,
struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height,
uint32_t format, uint32_t flags); uint32_t format, uint32_t flags);
bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm, bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane,
int32_t width, uint32_t height, uint32_t format); struct wlr_drm_backend *drm, int32_t width, uint32_t height,
uint32_t format);
void wlr_drm_surface_finish(struct wlr_drm_surface *surf); void wlr_drm_surface_finish(struct wlr_drm_surface *surf);
bool wlr_drm_surface_make_current(struct wlr_drm_surface *surf, int *buffer_age); bool wlr_drm_surface_make_current(struct wlr_drm_surface *surf, int *buffer_age);
struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf); struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf,
pixman_region32_t *damage);
struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf); struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf);
void wlr_drm_surface_post(struct wlr_drm_surface *surf); void wlr_drm_surface_post(struct wlr_drm_surface *surf);
struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, struct gbm_bo *src); struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest,
struct gbm_bo *src);
#endif #endif

View File

@ -19,7 +19,7 @@ struct wlr_output_impl {
bool (*move_cursor)(struct wlr_output *output, int x, int y); bool (*move_cursor)(struct wlr_output *output, int x, int y);
void (*destroy)(struct wlr_output *output); void (*destroy)(struct wlr_output *output);
bool (*make_current)(struct wlr_output *output, int *buffer_age); bool (*make_current)(struct wlr_output *output, int *buffer_age);
bool (*swap_buffers)(struct wlr_output *output); bool (*swap_buffers)(struct wlr_output *output, pixman_region32_t *damage);
void (*set_gamma)(struct wlr_output *output, void (*set_gamma)(struct wlr_output *output,
uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b); uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
uint32_t (*get_gamma_size)(struct wlr_output *output); uint32_t (*get_gamma_size)(struct wlr_output *output);

View File

@ -1,9 +1,10 @@
#ifndef WLR_EGL_H #ifndef WLR_EGL_H
#define WLR_EGL_H #define WLR_EGL_H
#include <stdbool.h>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <stdbool.h> #include <pixman.h>
#include <wayland-server.h> #include <wayland-server.h>
struct wlr_egl { struct wlr_egl {
@ -16,6 +17,7 @@ struct wlr_egl {
struct { struct {
bool buffer_age; bool buffer_age;
bool swap_buffers_with_damage;
} egl_exts; } egl_exts;
struct wl_display *wl_display; struct wl_display *wl_display;
@ -72,4 +74,7 @@ const char *egl_error(void);
bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface, bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface,
int *buffer_age); int *buffer_age);
bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
pixman_region32_t *damage);
#endif #endif

View File

@ -1,8 +1,8 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <stdlib.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <wlr/render/egl.h> #include <wlr/render/egl.h>
#include "glapi.h" #include "glapi.h"
@ -143,6 +143,9 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
egl->egl_exts.buffer_age = egl->egl_exts.buffer_age =
strstr(egl->egl_exts_str, "EGL_EXT_buffer_age") != NULL; strstr(egl->egl_exts_str, "EGL_EXT_buffer_age") != NULL;
egl->egl_exts.swap_buffers_with_damage =
strstr(egl->egl_exts_str, "EGL_EXT_swap_buffers_with_damage") != NULL ||
strstr(egl->egl_exts_str, "EGL_KHR_swap_buffers_with_damage") != NULL;
return true; return true;
@ -242,3 +245,37 @@ bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface,
} }
return true; return true;
} }
bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
pixman_region32_t *damage) {
EGLBoolean ret;
if (damage != NULL && egl->egl_exts.swap_buffers_with_damage) {
int nrects;
pixman_box32_t *rects =
pixman_region32_rectangles(damage, &nrects);
EGLint egl_damage[4 * nrects];
for (int i = 0; i < nrects; ++i) {
egl_damage[4*i] = rects[i].x1;
egl_damage[4*i + 1] = rects[i].y1;
egl_damage[4*i + 2] = rects[i].x2 - rects[i].x1;
egl_damage[4*i + 3] = rects[i].y2 - rects[i].y1;
}
assert(eglSwapBuffersWithDamageEXT || eglSwapBuffersWithDamageKHR);
if (eglSwapBuffersWithDamageEXT) {
ret = eglSwapBuffersWithDamageEXT(egl->display, surface, egl_damage,
nrects);
} else {
ret = eglSwapBuffersWithDamageKHR(egl->display, surface, egl_damage,
nrects);
}
} else {
ret = eglSwapBuffers(egl->display, surface);
}
if (!ret) {
wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
return false;
}
return true;
}

View File

@ -6,3 +6,5 @@ eglCreatePlatformWindowSurfaceEXT
-eglBindWaylandDisplayWL -eglBindWaylandDisplayWL
-eglUnbindWaylandDisplayWL -eglUnbindWaylandDisplayWL
-glEGLImageTargetTexture2DOES -glEGLImageTargetTexture2DOES
-eglSwapBuffersWithDamageEXT
-eglSwapBuffersWithDamageKHR

View File

@ -507,8 +507,14 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
} }
} }
// TODO: provide `damage` (not `render_damage`) to backend // Transform damage into renderer coordinates, ie. upside down
if (!output->impl->swap_buffers(output)) { enum wl_output_transform transform = wlr_output_transform_compose(
wlr_output_transform_invert(output->transform),
WL_OUTPUT_TRANSFORM_FLIPPED_180);
wlr_region_transform(&render_damage, &render_damage, transform, width,
height);
if (!output->impl->swap_buffers(output, damage ? &render_damage : NULL)) {
return false; return false;
} }