Merge pull request #619 from emersion/swap-with-damage
Swap buffers with damage
This commit is contained in:
commit
07856580c4
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
39
render/egl.c
39
render/egl.c
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -6,3 +6,5 @@ eglCreatePlatformWindowSurfaceEXT
|
||||||
-eglBindWaylandDisplayWL
|
-eglBindWaylandDisplayWL
|
||||||
-eglUnbindWaylandDisplayWL
|
-eglUnbindWaylandDisplayWL
|
||||||
-glEGLImageTargetTexture2DOES
|
-glEGLImageTargetTexture2DOES
|
||||||
|
-eglSwapBuffersWithDamageEXT
|
||||||
|
-eglSwapBuffersWithDamageKHR
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue