xwayland: Add SourceValidate hook
A later commit will use it to ensure the toplevel window pixmap has valid contents. It's hooked up only while any xwl_window->surface_window_damage points to a non-empty region. So far it's always NULL, so no functional change intended. v2: * Fix trailing whitespace. (Olivier Fourdan) v3: * Use toplevel local variable more in xwl_window_update_surface_window. Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1300>
This commit is contained in:
parent
fca63f8fb8
commit
aa05f38f3d
|
@ -81,6 +81,7 @@ struct xwl_screen {
|
|||
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
|
||||
ReparentWindowProcPtr ReparentWindow;
|
||||
MoveWindowProcPtr MoveWindow;
|
||||
SourceValidateProcPtr SourceValidate;
|
||||
|
||||
int (*GrabServer) (ClientPtr client);
|
||||
int (*UngrabServer) (ClientPtr client);
|
||||
|
@ -91,6 +92,8 @@ struct xwl_screen {
|
|||
struct xorg_list window_list;
|
||||
Bool ignore_damage;
|
||||
|
||||
int need_source_validate;
|
||||
|
||||
int wayland_fd;
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
|
|
|
@ -189,6 +189,107 @@ xwl_window_update_property(struct xwl_window *xwl_window,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
need_source_validate_dec(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
xwl_screen->need_source_validate--;
|
||||
|
||||
if (!xwl_screen->need_source_validate)
|
||||
xwl_screen->screen->SourceValidate = xwl_screen->SourceValidate;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_source_validate(DrawablePtr drawable, int x, int y, int width, int height,
|
||||
unsigned int sub_window_mode)
|
||||
{
|
||||
struct xwl_window *xwl_window;
|
||||
WindowPtr window, iterator;
|
||||
RegionRec region;
|
||||
BoxRec box;
|
||||
|
||||
if (sub_window_mode != IncludeInferiors ||
|
||||
drawable->type != DRAWABLE_WINDOW)
|
||||
return;
|
||||
|
||||
window = (WindowPtr)drawable;
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window || !xwl_window->surface_window_damage ||
|
||||
!RegionNotEmpty(xwl_window->surface_window_damage))
|
||||
return;
|
||||
|
||||
for (iterator = xwl_window->toplevel;
|
||||
;
|
||||
iterator = iterator->firstChild) {
|
||||
if (iterator == xwl_window->surface_window)
|
||||
return;
|
||||
|
||||
if (iterator == window)
|
||||
break;
|
||||
}
|
||||
|
||||
box.x1 = x;
|
||||
box.y1 = y;
|
||||
box.x2 = x + width;
|
||||
box.y2 = y + height;
|
||||
RegionInit(®ion, &box, 1);
|
||||
RegionIntersect(®ion, ®ion, xwl_window->surface_window_damage);
|
||||
|
||||
if (RegionNotEmpty(®ion)) {
|
||||
ScreenPtr screen = drawable->pScreen;
|
||||
PixmapPtr dst_pix, src_pix;
|
||||
BoxPtr pbox;
|
||||
GCPtr pGC;
|
||||
int nbox;
|
||||
|
||||
dst_pix = screen->GetWindowPixmap(window);
|
||||
pGC = GetScratchGC(dst_pix->drawable.depth, screen);
|
||||
if (!pGC)
|
||||
FatalError("GetScratchGC failed for depth %d", dst_pix->drawable.depth);
|
||||
ValidateGC(&dst_pix->drawable, pGC);
|
||||
|
||||
src_pix = screen->GetWindowPixmap(xwl_window->surface_window);
|
||||
|
||||
RegionSubtract(xwl_window->surface_window_damage,
|
||||
xwl_window->surface_window_damage,
|
||||
®ion);
|
||||
|
||||
if (!RegionNotEmpty(xwl_window->surface_window_damage))
|
||||
need_source_validate_dec(xwl_window->xwl_screen);
|
||||
|
||||
#if defined(COMPOSITE)
|
||||
if (dst_pix->screen_x || dst_pix->screen_y)
|
||||
RegionTranslate(®ion, -dst_pix->screen_x, -dst_pix->screen_y);
|
||||
#endif
|
||||
|
||||
pbox = RegionRects(®ion);
|
||||
nbox = RegionNumRects(®ion);
|
||||
while (nbox--) {
|
||||
(void) (*pGC->ops->CopyArea) (&src_pix->drawable,
|
||||
&dst_pix->drawable,
|
||||
pGC,
|
||||
pbox->x1, pbox->y1,
|
||||
pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
|
||||
pbox->x1, pbox->y1);
|
||||
}
|
||||
FreeScratchGC(pGC);
|
||||
}
|
||||
|
||||
RegionUninit(®ion);
|
||||
}
|
||||
|
||||
static void
|
||||
need_source_validate_inc(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
if (!xwl_screen->need_source_validate) {
|
||||
ScreenPtr screen = xwl_screen->screen;
|
||||
|
||||
xwl_screen->SourceValidate = screen->SourceValidate;
|
||||
screen->SourceValidate = xwl_source_validate;
|
||||
}
|
||||
|
||||
xwl_screen->need_source_validate++;
|
||||
}
|
||||
|
||||
static void
|
||||
damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
|
||||
{
|
||||
|
@ -196,6 +297,16 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
|
|||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
PixmapPtr window_pixmap;
|
||||
|
||||
if (xwl_window->surface_window_damage &&
|
||||
RegionNotEmpty(pRegion)) {
|
||||
if (!RegionNotEmpty(xwl_window->surface_window_damage))
|
||||
need_source_validate_inc(xwl_screen);
|
||||
|
||||
RegionUnion(xwl_window->surface_window_damage,
|
||||
xwl_window->surface_window_damage,
|
||||
DamageRegion(pDamage));
|
||||
}
|
||||
|
||||
if (xwl_screen->ignore_damage)
|
||||
return;
|
||||
|
||||
|
@ -1259,6 +1370,25 @@ xwl_window_update_surface_window(struct xwl_window *xwl_window)
|
|||
if (xwl_window->surface_window == surface_window)
|
||||
return;
|
||||
|
||||
if (xwl_window->surface_window_damage) {
|
||||
if (xwl_present_maybe_unredirect_window(xwl_window->surface_window) &&
|
||||
screen->SourceValidate == xwl_source_validate) {
|
||||
WindowPtr toplevel = xwl_window->toplevel;
|
||||
|
||||
xwl_source_validate(&toplevel->drawable,
|
||||
toplevel->drawable.x, toplevel->drawable.y,
|
||||
toplevel->drawable.width,
|
||||
toplevel->drawable.height,
|
||||
IncludeInferiors);
|
||||
}
|
||||
|
||||
if (RegionNotEmpty(xwl_window->surface_window_damage))
|
||||
need_source_validate_dec(xwl_window->xwl_screen);
|
||||
|
||||
RegionDestroy(xwl_window->surface_window_damage);
|
||||
xwl_window->surface_window_damage = NULL;
|
||||
}
|
||||
|
||||
window_damage = window_get_damage(xwl_window->surface_window);
|
||||
if (window_damage) {
|
||||
RegionInit(&damage_region, NullBox, 1);
|
||||
|
@ -1666,6 +1796,12 @@ xwl_config_notify(WindowPtr window,
|
|||
xwl_window = xwl_window_from_window(window);
|
||||
|
||||
size_changed = width != window->drawable.width || height != window->drawable.height;
|
||||
if (size_changed && xwl_window && xwl_window->toplevel == window &&
|
||||
screen->SourceValidate == xwl_source_validate) {
|
||||
xwl_source_validate(&window->drawable, window->drawable.x, window->drawable.y,
|
||||
window->drawable.width, window->drawable.height,
|
||||
IncludeInferiors);
|
||||
}
|
||||
|
||||
screen->ConfigNotify = xwl_screen->ConfigNotify;
|
||||
ret = screen->ConfigNotify(window, x, y, width, height, bw, sib);
|
||||
|
|
Loading…
Reference in New Issue