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