From 3160cb86aa9234ff78e11fe7a00f30bfb5cb8445 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Louis-Francis=20Ratt=C3=A9-Boulianne?= Date: Fri, 6 Oct 2017 01:26:51 -0400 Subject: [PATCH] egl/x11: Re-allocate buffers if format is suboptimal MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If PresentCompleteNotify event says the pixmap was presented with mode PresentCompleteModeSuboptimalCopy, it means the pixmap could possibly have been flipped instead if allocated with a different format/modifier. Signed-off-by: Louis-Francis Ratté-Boulianne Reviewed-by: Daniel Stone --- src/egl/drivers/dri2/egl_dri2.c | 2 ++ src/egl/drivers/dri2/egl_dri2.h | 2 ++ src/egl/drivers/dri2/platform_x11_dri3.c | 3 ++ src/glx/dri3_glx.c | 4 ++- src/loader/loader_dri3_helper.c | 39 ++++++++++++++++++++---- src/loader/loader_dri3_helper.h | 1 + 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 1bd57c9ea31..864f7eb0c68 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -885,6 +885,8 @@ dri2_setup_extensions(_EGLDisplay *disp) dri2_dpy->multibuffers_available = (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 && dri2_dpy->dri3_minor_version >= 2)) && + (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 && + dri2_dpy->present_minor_version >= 2)) && (dri2_dpy->image && dri2_dpy->image->base.version >= 15); #endif diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 00c4768d421..bd637f73c9d 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -202,6 +202,8 @@ struct dri2_egl_display bool multibuffers_available; int dri3_major_version; int dri3_minor_version; + int present_major_version; + int present_minor_version; struct loader_dri3_extensions loader_dri3_ext; #endif #endif diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c index c1efa930159..dce33561a6f 100644 --- a/src/egl/drivers/dri2/platform_x11_dri3.c +++ b/src/egl/drivers/dri2/platform_x11_dri3.c @@ -565,6 +565,9 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy) free(error); return EGL_FALSE; } + + dri2_dpy->present_major_version = present_query->major_version; + dri2_dpy->present_minor_version = present_query->minor_version; free(present_query); dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0); diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index 71ecebbc16c..aec803adfd8 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -372,7 +372,9 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable, pdraw->base.psc = &psc->base; if ((psc->image && psc->image->base.version >= 15) && - (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 2))) + (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 2)) && + (pdp->presentMajor > 1 || + (pdp->presentMajor == 1 && pdp->presentMinor >= 2))) has_multibuffer = true; (void) __glXInitialize(psc->base.dpy); diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c index 6587281c4ab..585f7ce3ece 100644 --- a/src/loader/loader_dri3_helper.c +++ b/src/loader/loader_dri3_helper.c @@ -374,6 +374,29 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw, if (draw->recv_sbc > draw->send_sbc) draw->recv_sbc -= 0x100000000; + /* When moving from flip to copy, we assume that we can allocate in + * a more optimal way if we don't need to cater for the display + * controller. + */ + if (ce->mode == XCB_PRESENT_COMPLETE_MODE_COPY && + draw->last_present_mode == XCB_PRESENT_COMPLETE_MODE_FLIP) { + for (int b = 0; b < ARRAY_SIZE(draw->buffers); b++) { + if (draw->buffers[b]) + draw->buffers[b]->reallocate = true; + } + } + + /* If the server tells us that our allocation is suboptimal, we + * reallocate once. + */ + if (ce->mode == XCB_PRESENT_COMPLETE_MODE_SUBOPTIMAL_COPY && + draw->last_present_mode != ce->mode) { + for (int b = 0; b < ARRAY_SIZE(draw->buffers); b++) { + if (draw->buffers[b]) + draw->buffers[b]->reallocate = true; + } + } + draw->last_present_mode = ce->mode; if (draw->vtable->show_fps) @@ -397,9 +420,9 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw, if (buf && buf->pixmap == ie->pixmap) buf->busy = 0; - if (buf && draw->num_back <= b && b < LOADER_DRI3_MAX_BACK && - draw->cur_blit_source != b && - !buf->busy) { + if (buf && draw->cur_blit_source != b && !buf->busy && + (buf->reallocate || + (draw->num_back <= b && b < LOADER_DRI3_MAX_BACK))) { dri3_free_render_buffer(draw, buf); draw->buffers[b] = NULL; } @@ -881,6 +904,9 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, if (!loader_dri3_have_image_blit(draw) && draw->cur_blit_source != -1) options |= XCB_PRESENT_OPTION_COPY; + if (draw->multiplanes_available) + options |= XCB_PRESENT_OPTION_SUBOPTIMAL; + back->busy = 1; back->last_swap = draw->send_sbc; xcb_present_pixmap(draw->conn, @@ -1626,11 +1652,12 @@ dri3_get_buffer(__DRIdrawable *driDrawable, buffer = draw->buffers[buf_id]; - /* Allocate a new buffer if there isn't an old one, or if that - * old one is the wrong size + /* Allocate a new buffer if there isn't an old one, if that + * old one is the wrong size, or if it's suboptimal */ if (!buffer || buffer->width != draw->width || - buffer->height != draw->height) { + buffer->height != draw->height || + buffer->reallocate) { struct loader_dri3_buffer *new_buffer; /* Allocate the new buffers diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h index c54c668032e..de22c19a578 100644 --- a/src/loader/loader_dri3_helper.h +++ b/src/loader/loader_dri3_helper.h @@ -61,6 +61,7 @@ struct loader_dri3_buffer { struct xshmfence *shm_fence; /* pointer to xshmfence object */ bool busy; /* Set on swap, cleared on IdleNotify */ bool own_pixmap; /* We allocated the pixmap ID, free on destroy */ + bool reallocate; /* Buffer should be reallocated and not reused */ uint32_t num_planes; uint32_t size; -- 2.30.2