From 0cc4c7e33ed7700fc20b6a642a74599a241e0811 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 11 Aug 2017 09:49:54 +0200 Subject: [PATCH] loader_dri3: Make sure we have an updated back v3 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit With GLX_SWAP_COPY_OML and GLX_SWAP_EXCHANGE_OML it may happen in situations when glXSwapBuffers() is immediately followed by for example another glXSwapBuffers() or glXCopyBuffers() or back buffer age querying, that we haven't yet allocated and initialized a new back buffer because there was no GL rendering in between. Make sure that we have a back buffer in those situations. v2: Eliminate the drawable have_back_format member. v3: Make sure we re-initialize the back even if it exists. Signed-off-by: Thomas Hellstrom Reviewed-by: Michel Dänzer --- src/loader/loader_dri3_helper.c | 59 +++++++++++++++++++++++++++------ src/loader/loader_dri3_helper.h | 1 + 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c index 55e14718bc3..e7d471517ee 100644 --- a/src/loader/loader_dri3_helper.c +++ b/src/loader/loader_dri3_helper.c @@ -59,6 +59,9 @@ static struct loader_dri3_blit_context blit_context = { static void dri3_flush_present_events(struct loader_dri3_drawable *draw); +static struct loader_dri3_buffer * +dri3_find_back_alloc(struct loader_dri3_drawable *draw); + /** * Do we have blit functionality in the image blit extension? * @@ -269,6 +272,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn, draw->first_init = true; draw->cur_blit_source = -1; + draw->back_format = __DRI_IMAGE_FORMAT_NONE; if (draw->ext->config) draw->ext->config->configQueryi(draw->dri_screen, @@ -616,7 +620,10 @@ loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, flags |= __DRI2_FLUSH_CONTEXT; loader_dri3_flush(draw, flags, __DRI2_THROTTLE_SWAPBUFFER); - back = dri3_back_buffer(draw); + back = dri3_find_back_alloc(draw); + if (!back) + return; + y = draw->height - y - height; if (draw->is_different_gpu) { @@ -641,7 +648,7 @@ loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, loader_dri3_swapbuffer_barrier(draw); dri3_fence_reset(draw->conn, back); dri3_copy_area(draw->conn, - dri3_back_buffer(draw)->pixmap, + back->pixmap, draw->drawable, dri3_drawable_gc(draw), x, y, x, y, width, height); @@ -652,7 +659,7 @@ loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, if (draw->have_fake_front && !draw->is_different_gpu) { dri3_fence_reset(draw->conn, dri3_fake_front_buffer(draw)); dri3_copy_area(draw->conn, - dri3_back_buffer(draw)->pixmap, + back->pixmap, dri3_fake_front_buffer(draw)->pixmap, dri3_drawable_gc(draw), x, y, x, y, width, height); @@ -763,7 +770,8 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, draw->vtable->flush_drawable(draw, flush_flags); - back = draw->buffers[dri3_find_back(draw)]; + back = dri3_find_back_alloc(draw); + if (draw->is_different_gpu && back) { /* Update the linear buffer before presenting the pixmap */ (void) loader_dri3_blit_image(draw, @@ -892,15 +900,12 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw) { - int back_id = LOADER_DRI3_BACK_ID(dri3_find_back(draw)); + struct loader_dri3_buffer *back = dri3_find_back_alloc(draw); - if (back_id < 0 || !draw->buffers[back_id]) + if (!back || back->last_swap == 0) return 0; - if (draw->buffers[back_id]->last_swap != 0) - return draw->send_sbc - draw->buffers[back_id]->last_swap + 1; - else - return 0; + return draw->send_sbc - back->last_swap + 1; } /** loader_dri3_open @@ -1334,6 +1339,8 @@ dri3_get_buffer(__DRIdrawable *driDrawable, int buf_id; if (buffer_type == loader_dri3_buffer_back) { + draw->back_format = format; + buf_id = dri3_find_back(draw); if (buf_id < 0) @@ -1620,3 +1627,35 @@ loader_dri3_close_screen(__DRIscreen *dri_screen) } mtx_unlock(&blit_context.mtx); } + +/** + * Find a backbuffer slot - potentially allocating a back buffer + * + * \param draw[in,out] Pointer to the drawable for which to find back. + * \return Pointer to a new back buffer or NULL if allocation failed or was + * not mandated. + * + * Find a potentially new back buffer, and if it's not been allocated yet and + * in addition needs initializing, then try to allocate and initialize it. + */ +static struct loader_dri3_buffer * +dri3_find_back_alloc(struct loader_dri3_drawable *draw) +{ + struct loader_dri3_buffer *back; + int id; + + id = dri3_find_back(draw); + back = (id >= 0) ? draw->buffers[id] : NULL; + + if (back || (id >= 0 && draw->back_format != __DRI_IMAGE_FORMAT_NONE)) { + if (dri3_update_drawable(draw->dri_drawable, draw)) { + (void) dri3_get_buffer(draw->dri_drawable, + draw->back_format, + loader_dri3_buffer_back, + draw); + back = (id >= 0) ? draw->buffers[id] : NULL; + } + } + + return back; +} diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h index 1a7d44dc1da..d3f4b0c00a9 100644 --- a/src/loader/loader_dri3_helper.h +++ b/src/loader/loader_dri3_helper.h @@ -158,6 +158,7 @@ struct loader_dri3_drawable { const struct loader_dri3_vtable *vtable; unsigned int swap_method; + unsigned int back_format; }; void -- 2.30.2