vl/dri3: Don't leak regions on the X server
authorAdam Jackson <ajax@redhat.com>
Fri, 18 Jun 2021 13:36:13 +0000 (09:36 -0400)
committerMarge Bot <eric+marge@anholt.net>
Thu, 24 Jun 2021 03:18:06 +0000 (03:18 +0000)
I can't tell from a quick read whether this clip region is actually just
the bounding box so could be skipped entirely. But the old code never
destroyed it, which means we'd leak a couple hundred bytes on the X
server side for every SwapBuffers until the client dies of XID
exhaustion, which is somewhere north of 2GB for typical systems so you
may or may not just run out of memory first.

Create the region at swap time and stash it in the drawable state.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11461>

src/gallium/auxiliary/vl/vl_winsys_dri3.c

index 1866dbc..f7cd4c1 100644 (file)
@@ -55,6 +55,7 @@ struct vl_dri3_buffer
    struct pipe_resource *linear_texture;
 
    uint32_t pixmap;
+   uint32_t region;
    uint32_t sync_fence;
    struct xshmfence *shm_fence;
 
@@ -107,6 +108,8 @@ static void
 dri3_free_back_buffer(struct vl_dri3_screen *scrn,
                         struct vl_dri3_buffer *buffer)
 {
+   if (buffer->region)
+      xcb_xfixes_destroy_region(scrn->conn, buffer->region);
    xcb_free_pixmap(scrn->conn, buffer->pixmap);
    xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence);
    xshmfence_unmap_shm(buffer->shm_fence);
@@ -564,7 +567,6 @@ vl_dri3_flush_frontbuffer(struct pipe_screen *screen,
    uint32_t options = XCB_PRESENT_OPTION_NONE;
    struct vl_dri3_buffer *back;
    struct pipe_box src_box;
-   xcb_xfixes_region_t region;
    xcb_rectangle_t rectangle;
 
    back = scrn->back_buffers[scrn->cur_back];
@@ -580,8 +582,11 @@ vl_dri3_flush_frontbuffer(struct pipe_screen *screen,
    rectangle.width = (scrn->output_texture) ? scrn->clip_width : scrn->width;
    rectangle.height = (scrn->output_texture) ? scrn->clip_height : scrn->height;
 
-   region = xcb_generate_id(scrn->conn);
-   xcb_xfixes_create_region(scrn->conn, region, 2, &rectangle);
+   if (!back->region) {
+      back->region = xcb_generate_id(scrn->conn);
+      xcb_xfixes_create_region(scrn->conn, back->region, 0, NULL);
+   }
+   xcb_xfixes_set_region(scrn->conn, back->region, 1, &rectangle);
 
    if (scrn->is_different_gpu) {
       u_box_origin_2d(back->width, back->height, &src_box);
@@ -600,7 +605,7 @@ vl_dri3_flush_frontbuffer(struct pipe_screen *screen,
                       scrn->drawable,
                       back->pixmap,
                       (uint32_t)(++scrn->send_sbc),
-                      0, region, 0, 0,
+                      0, back->region, 0, 0,
                       None, None,
                       back->sync_fence,
                       options,