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