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->window->drawable.id,
 | 
				
			||||||
            xwl_window->has_implicit_scanout_support ? "" : "not");
 | 
					            xwl_window->has_implicit_scanout_support ? "" : "not");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* If the linux-dmabuf v4 per-surface feedback changed, dispose of the
 | 
					    /* If the linux-dmabuf v4 per-surface feedback changed, make sure the
 | 
				
			||||||
     * window buffers so that they get re-created with appropriate parameters.
 | 
					     * window buffers get re-created with appropriate parameters.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    xwl_window_buffers_dispose(xwl_window);
 | 
					    xwl_window_buffers_dispose(xwl_window);
 | 
				
			||||||
 | 
					    xwl_window_recycle_pixmap(xwl_window);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,14 +247,92 @@ xwl_window_buffers_dispose(struct xwl_window *xwl_window)
 | 
				
			||||||
        TimerCancel(xwl_window->window_buffers_timer);
 | 
					        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
 | 
					PixmapPtr
 | 
				
			||||||
xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
					xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
				
			||||||
                              RegionPtr damage_region)
 | 
					                              RegionPtr damage_region)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
 | 
					    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
 | 
				
			||||||
    struct xwl_window_buffer *xwl_window_buffer;
 | 
					    struct xwl_window_buffer *xwl_window_buffer;
 | 
				
			||||||
    PixmapPtr window_pixmap;
 | 
					    PixmapPtr window_pixmap, new_window_pixmap;
 | 
				
			||||||
    RegionPtr full_damage;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
 | 
					    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);
 | 
					    xwl_window_buffer_add_damage_region(xwl_window, damage_region);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    full_damage = xwl_window_buffer->damage_region;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (xwl_window_buffer->pixmap) {
 | 
					    if (xwl_window_buffer->pixmap) {
 | 
				
			||||||
 | 
					        RegionPtr full_damage = xwl_window_buffer->damage_region;
 | 
				
			||||||
        BoxPtr pBox = RegionRects(full_damage);
 | 
					        BoxPtr pBox = RegionRects(full_damage);
 | 
				
			||||||
        int nBox = RegionNumRects(full_damage);
 | 
					        int nBox = RegionNumRects(full_damage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        new_window_pixmap = xwl_window_buffer->pixmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (nBox--) {
 | 
					        while (nBox--) {
 | 
				
			||||||
            copy_pixmap_area(window_pixmap,
 | 
					            copy_pixmap_area(window_pixmap,
 | 
				
			||||||
                             xwl_window_buffer->pixmap,
 | 
					                             new_window_pixmap,
 | 
				
			||||||
                             pBox->x1 + xwl_window->window->borderWidth,
 | 
					                             pBox->x1 + xwl_window->window->borderWidth,
 | 
				
			||||||
                             pBox->y1 + xwl_window->window->borderWidth,
 | 
					                             pBox->y1 + xwl_window->window->borderWidth,
 | 
				
			||||||
                             pBox->x2 - pBox->x1,
 | 
					                             pBox->x2 - pBox->x1,
 | 
				
			||||||
| 
						 | 
					@ -285,31 +365,19 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
				
			||||||
            pBox++;
 | 
					            pBox++;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
#ifdef XWL_HAS_GLAMOR
 | 
					        new_window_pixmap = xwl_window_allocate_pixmap(xwl_window);
 | 
				
			||||||
        /* Try the xwayland/glamor direct hook first */
 | 
					        if (!new_window_pixmap)
 | 
				
			||||||
        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)
 | 
					 | 
				
			||||||
            return window_pixmap;
 | 
					            return window_pixmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        copy_pixmap_area(window_pixmap,
 | 
					        copy_pixmap_area(window_pixmap,
 | 
				
			||||||
                         xwl_window_buffer->pixmap,
 | 
					                         new_window_pixmap,
 | 
				
			||||||
                         0, 0,
 | 
					                         0, 0,
 | 
				
			||||||
                         window_pixmap->drawable.width,
 | 
					                         window_pixmap->drawable.width,
 | 
				
			||||||
                         window_pixmap->drawable.height);
 | 
					                         window_pixmap->drawable.height);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RegionEmpty(xwl_window_buffer->damage_region);
 | 
					    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 */
 | 
					    /* Hold a reference on the buffer until it's released by the compositor */
 | 
				
			||||||
    xwl_window_buffer->refcnt++;
 | 
					    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,
 | 
					    xorg_list_append(&xwl_window_buffer->link_buffer,
 | 
				
			||||||
                     &xwl_window->window_buffers_unavailable);
 | 
					                     &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))
 | 
					    if (xorg_list_is_empty(&xwl_window->window_buffers_available))
 | 
				
			||||||
        TimerCancel(xwl_window->window_buffers_timer);
 | 
					        TimerCancel(xwl_window->window_buffers_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void xwl_window_buffers_init(struct xwl_window *xwl_window);
 | 
					void xwl_window_buffers_init(struct xwl_window *xwl_window);
 | 
				
			||||||
void xwl_window_buffers_dispose(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,
 | 
					PixmapPtr xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 | 
				
			||||||
                                        RegionPtr damage_region);
 | 
					                                        RegionPtr damage_region);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue