dri2: Use booleans for (fake) front buffer tracking in do_get_buffers

This works as intended — the (fake) front buffer needs to be added
only if the client didn't request it in the first place — even if the
client requests the same attachment multiple times. This ensures we
never try to access more than (count + 1) entries of the buffers array.

Fixes: ff6c7764c2 ("DRI2: Implement protocol for DRI2GetBuffersWithFormat")
Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2228>
This commit is contained in:
Michel Dänzer 2026-05-13 14:29:26 +02:00 • committed by Enrico Weigelt
commit dce46884f9

View file

@ -564,9 +564,10 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
DRI2ScreenPtr ds; DRI2ScreenPtr ds;
DRI2BufferPtr *buffers; DRI2BufferPtr *buffers;
int need_real_front = 0; Bool need_real_front = FALSE;
int need_fake_front = 0; Bool have_real_front = FALSE;
int have_fake_front = 0; Bool need_fake_front = FALSE;
Bool have_fake_front = FALSE;
int front_format = 0; int front_format = 0;
int dimensions_match; int dimensions_match;
int buffers_changed = 0; int buffers_changed = 0;
@ -599,34 +600,32 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
if (buffers[i] == NULL) if (buffers[i] == NULL)
goto err_out; goto err_out;
/* If the drawable is a window and the front-buffer is requested, /* In certain cases the (fake) front buffer is always needed, so return
* silently add the fake front-buffer to the list of requested * it even if the client failed to request it.
* attachments. The counting logic in the loop accounts for the case * The logic in & after the loop accounts for the case where the client
* where the client requests both the fake and real front-buffer. * does request the (fake) front buffer, to avoid returning it multiple
* times.
*/ */
if (attachment == DRI2BufferBackLeft) { if (attachment == DRI2BufferBackLeft) {
need_real_front++; need_real_front = TRUE;
front_format = format; front_format = format;
} }
if (attachment == DRI2BufferFrontLeft) { if (attachment == DRI2BufferFrontLeft) {
need_real_front--; have_real_front = TRUE;
front_format = format; front_format = format;
if (pDraw->type == DRAWABLE_WINDOW) { if (pDraw->type == DRAWABLE_WINDOW)
need_fake_front++; need_fake_front = TRUE;
}
} }
if (pDraw->type == DRAWABLE_WINDOW) { if (pDraw->type == DRAWABLE_WINDOW) {
if (attachment == DRI2BufferFakeFrontLeft) { if (attachment == DRI2BufferFakeFrontLeft)
need_fake_front--; have_fake_front = TRUE;
have_fake_front = 1;
}
} }
} }
if (need_real_front > 0) { if (need_real_front && !have_real_front) {
if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft, if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft,
front_format, dimensions_match, front_format, dimensions_match,
&buffers[i])) &buffers[i]))
@ -637,7 +636,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
i++; i++;
} }
if (need_fake_front > 0) { if (need_fake_front && !have_fake_front) {
if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft, if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft,
front_format, dimensions_match, front_format, dimensions_match,
&buffers[i])) &buffers[i]))
@ -647,7 +646,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
goto err_out; goto err_out;
i++; i++;
have_fake_front = 1; have_fake_front = TRUE;
} }
*out_count = i; *out_count = i;