mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-23 02:19:49 +01:00
Merge pull request #619 from emersion/swap-with-damage
Swap buffers with damage
This commit is contained in:
commit
07856580c4
11 changed files with 80 additions and 33 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
39
render/egl.c
39
render/egl.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -6,3 +6,5 @@ eglCreatePlatformWindowSurfaceEXT
|
|||
-eglBindWaylandDisplayWL
|
||||
-eglUnbindWaylandDisplayWL
|
||||
-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
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue