loader/dri3: Only allocate additional buffers if needed

Previously, we would always allocate 3 buffers for page flipping. But 2
buffers can suffice for clients which always wait for buffer swaps to
complete before starting a new frame.

Therefore, keep track of the maximum number of buffers separately from
the current number, and only bump the latter if both current buffers are
busy.

Cc: mesa-stable
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7033>
This commit is contained in:
Michel Dänzer 2020-10-02 15:20:17 +02:00 committed by Marge Bot
parent ea32691257
commit 60585fc4e3
2 changed files with 31 additions and 12 deletions

View file

@ -272,12 +272,23 @@ dri3_fence_await(xcb_connection_t *c, struct loader_dri3_drawable *draw,
}
static void
dri3_update_num_back(struct loader_dri3_drawable *draw)
dri3_update_max_num_back(struct loader_dri3_drawable *draw)
{
if (draw->last_present_mode == XCB_PRESENT_COMPLETE_MODE_FLIP)
draw->num_back = 3;
else
draw->num_back = 2;
switch (draw->last_present_mode) {
case XCB_PRESENT_COMPLETE_MODE_FLIP:
/* Leave cur_num_back unchanged, it'll grow as needed */
draw->max_num_back = 3;
break;
default:
/* On transition from flips to copies, start with a single buffer again,
* a second one will be allocated if needed
*/
if (draw->max_num_back != 2)
draw->cur_num_back = 1;
draw->max_num_back = 2;
}
}
void
@ -395,7 +406,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
}
draw->swap_interval = swap_interval;
dri3_update_num_back(draw);
dri3_update_max_num_back(draw);
/* Create a new drawable */
draw->dri_drawable =
@ -643,6 +654,7 @@ dri3_find_back(struct loader_dri3_drawable *draw)
{
int b;
int num_to_consider;
int max_num;
mtx_lock(&draw->mtx);
/* Increase the likelyhood of reusing current buffer */
@ -651,15 +663,18 @@ dri3_find_back(struct loader_dri3_drawable *draw)
/* Check whether we need to reuse the current back buffer as new back.
* In that case, wait until it's not busy anymore.
*/
num_to_consider = draw->num_back;
if (!loader_dri3_have_image_blit(draw) && draw->cur_blit_source != -1) {
num_to_consider = 1;
max_num = 1;
draw->cur_blit_source = -1;
} else {
num_to_consider = draw->cur_num_back;
max_num = draw->max_num_back;
}
for (;;) {
for (b = 0; b < num_to_consider; b++) {
int id = LOADER_DRI3_BACK_ID((b + draw->cur_back) % draw->num_back);
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) {
@ -668,7 +683,10 @@ dri3_find_back(struct loader_dri3_drawable *draw)
return id;
}
}
if (!dri3_wait_for_event_locked(draw, NULL)) {
if (num_to_consider < max_num) {
num_to_consider = ++draw->cur_num_back;
} else if (!dri3_wait_for_event_locked(draw, NULL)) {
mtx_unlock(&draw->mtx);
return -1;
}
@ -2014,10 +2032,10 @@ loader_dri3_get_buffers(__DRIdrawable *driDrawable,
if (!dri3_update_drawable(draw))
return false;
dri3_update_num_back(draw);
dri3_update_max_num_back(draw);
/* Free no longer needed back buffers */
for (buf_id = draw->num_back; buf_id < LOADER_DRI3_MAX_BACK; buf_id++) {
for (buf_id = draw->cur_num_back; buf_id < LOADER_DRI3_MAX_BACK; buf_id++) {
if (draw->cur_blit_source != buf_id && draw->buffers[buf_id]) {
dri3_free_render_buffer(draw, draw->buffers[buf_id]);
draw->buffers[buf_id] = NULL;

View file

@ -146,7 +146,8 @@ struct loader_dri3_drawable {
struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS];
int cur_back;
int num_back;
int cur_num_back;
int max_num_back;
int cur_blit_source;
uint32_t *stamp;