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);
}
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_backend *drm = (struct wlr_drm_backend *)output->backend;
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 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) {
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);
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);

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);
}
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) {
gbm_surface_release_buffer(surf->gbm, surf->front);
}
if (!eglSwapBuffers(surf->renderer->egl.display, surf->egl)) {
wlr_log(L_ERROR, "eglSwapBuffers failed");
}
wlr_egl_swap_buffers(&surf->renderer->egl, surf->egl, damage);
surf->front = surf->back;
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);
glClearColor(0.0, 0.0, 0.0, 1.0);
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) {
@ -244,7 +243,7 @@ struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest,
glClear(GL_COLOR_BUFFER_BIT);
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,

View file

@ -55,7 +55,8 @@ static bool output_make_current(struct wlr_output *wlr_output, int *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
}

View file

@ -47,7 +47,8 @@ static bool wlr_wl_output_make_current(struct wlr_output *wlr_output,
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 *)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);
wl_callback_add_listener(output->frame_callback, &frame_listener, output);
if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) {
wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
return false;
}
return true;
return wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface,
damage);
}
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);
}
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_backend *x11 = output->x11;
if (!eglSwapBuffers(x11->egl.display, output->surf)) {
wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
return false;
}
return true;
return wlr_egl_swap_buffers(&x11->egl, output->surf, damage);
}
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,
uint32_t format, uint32_t flags);
bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm,
int32_t width, uint32_t height, uint32_t format);
bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane,
struct wlr_drm_backend *drm, int32_t width, uint32_t height,
uint32_t format);
void wlr_drm_surface_finish(struct wlr_drm_surface *surf);
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);
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

View file

@ -19,7 +19,7 @@ struct wlr_output_impl {
bool (*move_cursor)(struct wlr_output *output, int x, int y);
void (*destroy)(struct wlr_output *output);
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,
uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
uint32_t (*get_gamma_size)(struct wlr_output *output);

View file

@ -1,9 +1,10 @@
#ifndef WLR_EGL_H
#define WLR_EGL_H
#include <stdbool.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdbool.h>
#include <pixman.h>
#include <wayland-server.h>
struct wlr_egl {
@ -16,6 +17,7 @@ struct wlr_egl {
struct {
bool buffer_age;
bool swap_buffers_with_damage;
} egl_exts;
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,
int *buffer_age);
bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
pixman_region32_t *damage);
#endif

View file

@ -1,8 +1,8 @@
#include <assert.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <stdlib.h>
#include <wlr/util/log.h>
#include <wlr/render/egl.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 =
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;
@ -242,3 +245,37 @@ bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface,
}
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
-eglUnbindWaylandDisplayWL
-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
if (!output->impl->swap_buffers(output)) {
// Transform damage into renderer coordinates, ie. upside down
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;
}