xwayland: Use window pixmap as a window buffer
Assuming the same number of window buffers, this results in one less pixmap per toplevel window, saving pixmap storage. v2: * Preserve xwl_window_buffer_get_available behaviour (Olivier Fourdan) v3: * Leave RegionEmpty call where it was in xwl_window_buffers_get_pixmap, so it takes effect for a newly allocated struct xwl_window_buffer. * Consolidate xwl_window_buffer->pixmap assignment in the same place.
This commit is contained in:
		
							parent
							
								
									2b577c2e3b
								
							
						
					
					
						commit
						6779ec5bf6
					
				| 
						 | 
				
			
			@ -788,10 +788,11 @@ xwl_window_dmabuf_feedback_done(void *data,
 | 
			
		|||
            xwl_window->window->drawable.id,
 | 
			
		||||
            xwl_window->has_implicit_scanout_support ? "" : "not");
 | 
			
		||||
 | 
			
		||||
    /* If the linux-dmabuf v4 per-surface feedback changed, dispose of the
 | 
			
		||||
     * window buffers so that they get re-created with appropriate parameters.
 | 
			
		||||
    /* If the linux-dmabuf v4 per-surface feedback changed, make sure the
 | 
			
		||||
     * window buffers get re-created with appropriate parameters.
 | 
			
		||||
     */
 | 
			
		||||
    xwl_window_buffers_dispose(xwl_window);
 | 
			
		||||
    xwl_window_recycle_pixmap(xwl_window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -247,14 +247,92 @@ xwl_window_buffers_dispose(struct xwl_window *xwl_window)
 | 
			
		|||
        TimerCancel(xwl_window->window_buffers_timer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pixmap_visit {
 | 
			
		||||
    PixmapPtr old;
 | 
			
		||||
    PixmapPtr new;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
xwl_set_pixmap_visit_window(WindowPtr window, void *data)
 | 
			
		||||
{
 | 
			
		||||
    ScreenPtr screen = window->drawable.pScreen;
 | 
			
		||||
    struct pixmap_visit *visit = data;
 | 
			
		||||
 | 
			
		||||
    if (screen->GetWindowPixmap(window) == visit->old) {
 | 
			
		||||
        screen->SetWindowPixmap(window, visit->new);
 | 
			
		||||
        return WT_WALKCHILDREN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return WT_DONTWALKCHILDREN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
xwl_window_set_pixmap(WindowPtr window, PixmapPtr pixmap)
 | 
			
		||||
{
 | 
			
		||||
    ScreenPtr screen = window->drawable.pScreen;
 | 
			
		||||
    struct pixmap_visit visit;
 | 
			
		||||
 | 
			
		||||
    visit.old = screen->GetWindowPixmap(window);
 | 
			
		||||
    visit.new = pixmap;
 | 
			
		||||
 | 
			
		||||
#ifdef COMPOSITE
 | 
			
		||||
    pixmap->screen_x = visit.old->screen_x;
 | 
			
		||||
    pixmap->screen_y = visit.old->screen_y;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    TraverseTree(window, xwl_set_pixmap_visit_window, &visit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PixmapPtr
 | 
			
		||||
xwl_window_allocate_pixmap(struct xwl_window *xwl_window)
 | 
			
		||||
{
 | 
			
		||||
    ScreenPtr screen = xwl_window->xwl_screen->screen;
 | 
			
		||||
    PixmapPtr window_pixmap;
 | 
			
		||||
 | 
			
		||||
#ifdef XWL_HAS_GLAMOR
 | 
			
		||||
    /* Try the xwayland/glamor direct hook first */
 | 
			
		||||
    window_pixmap = xwl_glamor_create_pixmap_for_window(xwl_window);
 | 
			
		||||
    if (window_pixmap)
 | 
			
		||||
        return window_pixmap;
 | 
			
		||||
#endif /* XWL_HAS_GLAMOR */
 | 
			
		||||
 | 
			
		||||
    window_pixmap = screen->GetWindowPixmap(xwl_window->window);
 | 
			
		||||
    return screen->CreatePixmap(screen,
 | 
			
		||||
                                window_pixmap->drawable.width,
 | 
			
		||||
                                window_pixmap->drawable.height,
 | 
			
		||||
                                window_pixmap->drawable.depth,
 | 
			
		||||
                                CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
xwl_window_recycle_pixmap(struct xwl_window *xwl_window)
 | 
			
		||||
{
 | 
			
		||||
    PixmapPtr window_pixmap, new_window_pixmap;
 | 
			
		||||
    WindowPtr window;
 | 
			
		||||
    ScreenPtr screen;
 | 
			
		||||
 | 
			
		||||
    new_window_pixmap = xwl_window_allocate_pixmap(xwl_window);
 | 
			
		||||
    if (!new_window_pixmap)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    window = xwl_window->window;
 | 
			
		||||
    screen = window->drawable.pScreen;
 | 
			
		||||
    window_pixmap = screen->GetWindowPixmap(window);
 | 
			
		||||
    copy_pixmap_area(window_pixmap,
 | 
			
		||||
                     new_window_pixmap,
 | 
			
		||||
                     0, 0,
 | 
			
		||||
                     window_pixmap->drawable.width,
 | 
			
		||||
                     window_pixmap->drawable.height);
 | 
			
		||||
    xwl_window_set_pixmap(xwl_window->window, new_window_pixmap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PixmapPtr
 | 
			
		||||
xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
			
		||||
                              RegionPtr damage_region)
 | 
			
		||||
{
 | 
			
		||||
    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
 | 
			
		||||
    struct xwl_window_buffer *xwl_window_buffer;
 | 
			
		||||
    PixmapPtr window_pixmap;
 | 
			
		||||
    RegionPtr full_damage;
 | 
			
		||||
    PixmapPtr window_pixmap, new_window_pixmap;
 | 
			
		||||
 | 
			
		||||
    window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -269,14 +347,16 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
			
		|||
 | 
			
		||||
    xwl_window_buffer_add_damage_region(xwl_window, damage_region);
 | 
			
		||||
 | 
			
		||||
    full_damage = xwl_window_buffer->damage_region;
 | 
			
		||||
 | 
			
		||||
    if (xwl_window_buffer->pixmap) {
 | 
			
		||||
        RegionPtr full_damage = xwl_window_buffer->damage_region;
 | 
			
		||||
        BoxPtr pBox = RegionRects(full_damage);
 | 
			
		||||
        int nBox = RegionNumRects(full_damage);
 | 
			
		||||
 | 
			
		||||
        new_window_pixmap = xwl_window_buffer->pixmap;
 | 
			
		||||
 | 
			
		||||
        while (nBox--) {
 | 
			
		||||
            copy_pixmap_area(window_pixmap,
 | 
			
		||||
                             xwl_window_buffer->pixmap,
 | 
			
		||||
                             new_window_pixmap,
 | 
			
		||||
                             pBox->x1 + xwl_window->window->borderWidth,
 | 
			
		||||
                             pBox->y1 + xwl_window->window->borderWidth,
 | 
			
		||||
                             pBox->x2 - pBox->x1,
 | 
			
		||||
| 
						 | 
				
			
			@ -285,31 +365,19 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
			
		|||
            pBox++;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
#ifdef XWL_HAS_GLAMOR
 | 
			
		||||
        /* Try the xwayland/glamor direct hook first */
 | 
			
		||||
        xwl_window_buffer->pixmap =
 | 
			
		||||
            xwl_glamor_create_pixmap_for_window(xwl_window);
 | 
			
		||||
#endif /* XWL_HAS_GLAMOR */
 | 
			
		||||
        if (!xwl_window_buffer->pixmap) {
 | 
			
		||||
            xwl_window_buffer->pixmap =
 | 
			
		||||
                (*xwl_screen->screen->CreatePixmap) (window_pixmap->drawable.pScreen,
 | 
			
		||||
                                                     window_pixmap->drawable.width,
 | 
			
		||||
                                                     window_pixmap->drawable.height,
 | 
			
		||||
                                                     window_pixmap->drawable.depth,
 | 
			
		||||
                                                     CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!xwl_window_buffer->pixmap)
 | 
			
		||||
        new_window_pixmap = xwl_window_allocate_pixmap(xwl_window);
 | 
			
		||||
        if (!new_window_pixmap)
 | 
			
		||||
            return window_pixmap;
 | 
			
		||||
 | 
			
		||||
        copy_pixmap_area(window_pixmap,
 | 
			
		||||
                         xwl_window_buffer->pixmap,
 | 
			
		||||
                         new_window_pixmap,
 | 
			
		||||
                         0, 0,
 | 
			
		||||
                         window_pixmap->drawable.width,
 | 
			
		||||
                         window_pixmap->drawable.height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RegionEmpty(xwl_window_buffer->damage_region);
 | 
			
		||||
    xwl_window_buffer->pixmap = window_pixmap;
 | 
			
		||||
 | 
			
		||||
    /* Hold a reference on the buffer until it's released by the compositor */
 | 
			
		||||
    xwl_window_buffer->refcnt++;
 | 
			
		||||
| 
						 | 
				
			
			@ -321,6 +389,8 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
			
		|||
    xorg_list_append(&xwl_window_buffer->link_buffer,
 | 
			
		||||
                     &xwl_window->window_buffers_unavailable);
 | 
			
		||||
 | 
			
		||||
    xwl_window_set_pixmap(xwl_window->window, new_window_pixmap);
 | 
			
		||||
 | 
			
		||||
    if (xorg_list_is_empty(&xwl_window->window_buffers_available))
 | 
			
		||||
        TimerCancel(xwl_window->window_buffers_timer);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@
 | 
			
		|||
 | 
			
		||||
void xwl_window_buffers_init(struct xwl_window *xwl_window);
 | 
			
		||||
void xwl_window_buffers_dispose(struct xwl_window *xwl_window);
 | 
			
		||||
void xwl_window_recycle_pixmap(struct xwl_window *xwl_window);
 | 
			
		||||
PixmapPtr xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
			
		||||
                                        RegionPtr damage_region);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue