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