From: Eric Engestrom Date: Fri, 22 May 2020 23:45:42 +0000 (+0200) Subject: egl/x11_dri3: implement EGL_KHR_swap_buffers_with_damage X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=326eb56718925828e886f40f72ea4a97b4657196;p=mesa.git egl/x11_dri3: implement EGL_KHR_swap_buffers_with_damage Passes all of `dEQP-EGL.functional.swap_buffers_with_damage.*`: Passed: 36/54 (66.7%) Failed: 0/54 (0.0%) Not supported: 18/54 (33.3%) Warnings: 0/54 (0.0%) Waived: 0/54 (0.0%) The "not supported" ones are the `preserve_buffer_*` tests, which is not supported on X11/DRI3. Cc: 20.2 Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3030 Signed-off-by: Eric Engestrom Reviewed-by: Michel Dänzer Part-of: --- diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 868da1dcf20..ef48b8ab45d 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -1,2 +1,3 @@ GL 4.5 on llvmpipe GL_NV_half_float +EGL_KHR_swap_buffers_with_damage on X11 (DRI3) diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 605035581d1..96a8a88d725 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -1386,6 +1386,7 @@ dri2_initialize_x11_dri3(_EGLDisplay *disp) disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; disp->Extensions.CHROMIUM_sync_control = EGL_TRUE; disp->Extensions.EXT_buffer_age = EGL_TRUE; + disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE; dri2_set_WL_bind_wayland_display(disp); diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c index 5c69a3b981e..40d203c9ec1 100644 --- a/src/egl/drivers/dri2/platform_x11_dri3.c +++ b/src/egl/drivers/dri2/platform_x11_dri3.c @@ -413,15 +413,23 @@ const __DRIimageLoaderExtension dri3_image_loader_extension = { }; static EGLBoolean -dri3_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) +dri3_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *draw, + const EGLint *rects, EGLint n_rects) { struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw); return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable, 0, 0, 0, 0, + rects, n_rects, draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1; } +static EGLBoolean +dri3_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) +{ + return dri3_swap_buffers_with_damage(disp, draw, NULL, 0); +} + static EGLBoolean dri3_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target) { @@ -488,6 +496,7 @@ struct dri2_egl_display_vtbl dri3_x11_display_vtbl = { .create_image = dri3_create_image_khr, .swap_interval = dri3_set_swap_interval, .swap_buffers = dri3_swap_buffers, + .swap_buffers_with_damage = dri3_swap_buffers_with_damage, .copy_buffers = dri3_copy_buffers, .query_buffer_age = dri3_query_buffer_age, .query_surface = dri3_query_surface, diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index a0929316778..fc8e8157618 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -593,7 +593,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, return loader_dri3_swap_buffers_msc(&priv->loader_drawable, target_msc, divisor, remainder, - flags, false); + flags, NULL, 0, false); } static int diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c index 425faba8f64..cba3dfe2695 100644 --- a/src/loader/loader_dri3_helper.c +++ b/src/loader/loader_dri3_helper.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -908,6 +909,7 @@ int64_t loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, int64_t target_msc, int64_t divisor, int64_t remainder, unsigned flush_flags, + const int *rects, int n_rects, bool force_copy) { struct loader_dri3_buffer *back; @@ -1006,12 +1008,29 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, #endif back->busy = 1; back->last_swap = draw->send_sbc; + + xcb_xfixes_region_t region = 0; + xcb_rectangle_t xcb_rects[64]; + + if (n_rects > 0 && n_rects <= ARRAY_SIZE(xcb_rects)) { + for (int i = 0; i < n_rects; i++) { + const int *rect = &rects[i * 4]; + xcb_rects[i].x = rect[0]; + xcb_rects[i].y = draw->height - rect[1] - rect[3]; + xcb_rects[i].width = rect[2]; + xcb_rects[i].height = rect[3]; + } + + region = xcb_generate_id(draw->conn); + xcb_xfixes_create_region(draw->conn, region, n_rects, xcb_rects); + } + xcb_present_pixmap(draw->conn, draw->drawable, back->pixmap, (uint32_t) draw->send_sbc, 0, /* valid */ - 0, /* update */ + region, /* update */ 0, /* x_off */ 0, /* y_off */ None, /* target_crtc */ @@ -1023,6 +1042,9 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, remainder, 0, NULL); ret = (int64_t) draw->send_sbc; + if (region) + xcb_xfixes_destroy_region(draw->conn, region); + /* Schedule a server-side back-preserving blit if necessary. * This happens iff all conditions below are satisfied: * a) We have a fake front, diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h index c314e4c5a9d..af5fdbc4193 100644 --- a/src/loader/loader_dri3_helper.h +++ b/src/loader/loader_dri3_helper.h @@ -205,6 +205,7 @@ int64_t loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, int64_t target_msc, int64_t divisor, int64_t remainder, unsigned flush_flags, + const int *rects, int n_rects, bool force_copy); int diff --git a/src/loader/meson.build b/src/loader/meson.build index ec8d668813b..34a43e33f09 100644 --- a/src/loader/meson.build +++ b/src/loader/meson.build @@ -28,6 +28,7 @@ if with_platform_x11 and with_dri3 include_directories : [inc_include, inc_src], dependencies : [ dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence, + dep_xcb_xfixes, ], build_by_default : false, )