diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c index 16cb1faf7b3..e808bcf9741 100644 --- a/src/loader/loader_dri3_helper.c +++ b/src/loader/loader_dri3_helper.c @@ -679,7 +679,7 @@ loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw, * wait for a present idle notify event from the X server */ static int -dri3_find_back(struct loader_dri3_drawable *draw) +dri3_find_back(struct loader_dri3_drawable *draw, bool prefer_a_different) { int b; int num_to_consider; @@ -701,12 +701,23 @@ dri3_find_back(struct loader_dri3_drawable *draw) max_num = draw->max_num_back; } + /* In a DRI_PRIME situation, if prefer_a_different is true, we first try + * to find an idle buffer that is not the last used one. + * This is useful if we receive a XCB_PRESENT_EVENT_IDLE_NOTIFY event + * for a pixmap but it's not actually idle (eg: the DRI_PRIME blit is + * still in progress). + * Unigine Superposition hits this and this allows to use 2 back buffers + * instead of reusing the same one all the time, causing the next frame + * to wait for the copy to finish. + */ + int current_back_id = draw->cur_back; for (;;) { for (b = 0; b < num_to_consider; b++) { int id = LOADER_DRI3_BACK_ID((b + draw->cur_back) % draw->cur_num_back); struct loader_dri3_buffer *buffer = draw->buffers[id]; - if (!buffer || !buffer->busy) { + if (!buffer || (!buffer->busy && + (!prefer_a_different || id != current_back_id))) { draw->cur_back = id; mtx_unlock(&draw->mtx); return id; @@ -715,6 +726,8 @@ dri3_find_back(struct loader_dri3_drawable *draw) if (num_to_consider < max_num) { num_to_consider = ++draw->cur_num_back; + } else if (prefer_a_different) { + prefer_a_different = false; } else if (!dri3_wait_for_event_locked(draw, NULL)) { mtx_unlock(&draw->mtx); return -1; @@ -1921,7 +1934,7 @@ dri3_get_buffer(__DRIdrawable *driDrawable, if (buffer_type == loader_dri3_buffer_back) { draw->back_format = format; - buf_id = dri3_find_back(draw); + buf_id = dri3_find_back(draw, !draw->prefer_back_buffer_reuse); if (buf_id < 0) return NULL; @@ -2246,7 +2259,7 @@ dri3_find_back_alloc(struct loader_dri3_drawable *draw) struct loader_dri3_buffer *back; int id; - id = dri3_find_back(draw); + id = dri3_find_back(draw, false); if (id < 0) return NULL;