Home | History | Annotate | Line # | Download | only in drm
      1  1.1  riastrad /*	$NetBSD: drm_damage_helper.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad // SPDX-License-Identifier: GPL-2.0 OR MIT
      4  1.1  riastrad /**************************************************************************
      5  1.1  riastrad  *
      6  1.1  riastrad  * Copyright (c) 2018 VMware, Inc., Palo Alto, CA., USA
      7  1.1  riastrad  * All Rights Reserved.
      8  1.1  riastrad  *
      9  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
     10  1.1  riastrad  * copy of this software and associated documentation files (the
     11  1.1  riastrad  * "Software"), to deal in the Software without restriction, including
     12  1.1  riastrad  * without limitation the rights to use, copy, modify, merge, publish,
     13  1.1  riastrad  * distribute, sub license, and/or sell copies of the Software, and to
     14  1.1  riastrad  * permit persons to whom the Software is furnished to do so, subject to
     15  1.1  riastrad  * the following conditions:
     16  1.1  riastrad  *
     17  1.1  riastrad  * The above copyright notice and this permission notice (including the
     18  1.1  riastrad  * next paragraph) shall be included in all copies or substantial portions
     19  1.1  riastrad  * of the Software.
     20  1.1  riastrad  *
     21  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     22  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     23  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     24  1.1  riastrad  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     25  1.1  riastrad  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     26  1.1  riastrad  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     27  1.1  riastrad  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     28  1.1  riastrad  *
     29  1.1  riastrad  * Authors:
     30  1.1  riastrad  * Deepak Rawat <drawat (at) vmware.com>
     31  1.1  riastrad  * Rob Clark <robdclark (at) gmail.com>
     32  1.1  riastrad  *
     33  1.1  riastrad  **************************************************************************/
     34  1.1  riastrad 
     35  1.1  riastrad #include <sys/cdefs.h>
     36  1.1  riastrad __KERNEL_RCSID(0, "$NetBSD: drm_damage_helper.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $");
     37  1.1  riastrad 
     38  1.1  riastrad #include <drm/drm_atomic.h>
     39  1.1  riastrad #include <drm/drm_damage_helper.h>
     40  1.1  riastrad #include <drm/drm_device.h>
     41  1.1  riastrad 
     42  1.1  riastrad /**
     43  1.1  riastrad  * DOC: overview
     44  1.1  riastrad  *
     45  1.1  riastrad  * FB_DAMAGE_CLIPS is an optional plane property which provides a means to
     46  1.1  riastrad  * specify a list of damage rectangles on a plane in framebuffer coordinates of
     47  1.1  riastrad  * the framebuffer attached to the plane. In current context damage is the area
     48  1.1  riastrad  * of plane framebuffer that has changed since last plane update (also called
     49  1.1  riastrad  * page-flip), irrespective of whether currently attached framebuffer is same as
     50  1.1  riastrad  * framebuffer attached during last plane update or not.
     51  1.1  riastrad  *
     52  1.1  riastrad  * FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
     53  1.1  riastrad  * to optimize internally especially for virtual devices where each framebuffer
     54  1.1  riastrad  * change needs to be transmitted over network, usb, etc.
     55  1.1  riastrad  *
     56  1.1  riastrad  * Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
     57  1.1  riastrad  * ignore damage clips property and in that case driver will do a full plane
     58  1.1  riastrad  * update. In case damage clips are provided then it is guaranteed that the area
     59  1.1  riastrad  * inside damage clips will be updated to plane. For efficiency driver can do
     60  1.1  riastrad  * full update or can update more than specified in damage clips. Since driver
     61  1.1  riastrad  * is free to read more, user-space must always render the entire visible
     62  1.1  riastrad  * framebuffer. Otherwise there can be corruptions. Also, if a user-space
     63  1.1  riastrad  * provides damage clips which doesn't encompass the actual damage to
     64  1.1  riastrad  * framebuffer (since last plane update) can result in incorrect rendering.
     65  1.1  riastrad  *
     66  1.1  riastrad  * FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
     67  1.1  riastrad  * array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
     68  1.1  riastrad  * damage clips are not in 16.16 fixed point. Similar to plane src in
     69  1.1  riastrad  * framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
     70  1.1  riastrad  * inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
     71  1.1  riastrad  * damage clips, it is strongly discouraged.
     72  1.1  riastrad  *
     73  1.1  riastrad  * Drivers that are interested in damage interface for plane should enable
     74  1.1  riastrad  * FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
     75  1.1  riastrad  * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
     76  1.1  riastrad  * drm_atomic_helper_damage_iter_next() helper iterator function to get damage
     77  1.1  riastrad  * rectangles clipped to &drm_plane_state.src.
     78  1.1  riastrad  */
     79  1.1  riastrad 
     80  1.1  riastrad static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
     81  1.1  riastrad 				      struct drm_mode_rect *dest,
     82  1.1  riastrad 				      uint32_t num_clips, uint32_t src_inc)
     83  1.1  riastrad {
     84  1.1  riastrad 	while (num_clips > 0) {
     85  1.1  riastrad 		dest->x1 = src->x1;
     86  1.1  riastrad 		dest->y1 = src->y1;
     87  1.1  riastrad 		dest->x2 = src->x2;
     88  1.1  riastrad 		dest->y2 = src->y2;
     89  1.1  riastrad 		src += src_inc;
     90  1.1  riastrad 		dest++;
     91  1.1  riastrad 		num_clips--;
     92  1.1  riastrad 	}
     93  1.1  riastrad }
     94  1.1  riastrad 
     95  1.1  riastrad /**
     96  1.1  riastrad  * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
     97  1.1  riastrad  * @plane: Plane on which to enable damage clips property.
     98  1.1  riastrad  *
     99  1.1  riastrad  * This function lets driver to enable the damage clips property on a plane.
    100  1.1  riastrad  */
    101  1.1  riastrad void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
    102  1.1  riastrad {
    103  1.1  riastrad 	struct drm_device *dev = plane->dev;
    104  1.1  riastrad 	struct drm_mode_config *config = &dev->mode_config;
    105  1.1  riastrad 
    106  1.1  riastrad 	drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
    107  1.1  riastrad 				   0);
    108  1.1  riastrad }
    109  1.1  riastrad EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
    110  1.1  riastrad 
    111  1.1  riastrad /**
    112  1.1  riastrad  * drm_atomic_helper_check_plane_damage - Verify plane damage on atomic_check.
    113  1.1  riastrad  * @state: The driver state object.
    114  1.1  riastrad  * @plane_state: Plane state for which to verify damage.
    115  1.1  riastrad  *
    116  1.1  riastrad  * This helper function makes sure that damage from plane state is discarded
    117  1.1  riastrad  * for full modeset. If there are more reasons a driver would want to do a full
    118  1.1  riastrad  * plane update rather than processing individual damage regions, then those
    119  1.1  riastrad  * cases should be taken care of here.
    120  1.1  riastrad  *
    121  1.1  riastrad  * Note that &drm_plane_state.fb_damage_clips == NULL in plane state means that
    122  1.1  riastrad  * full plane update should happen. It also ensure helper iterator will return
    123  1.1  riastrad  * &drm_plane_state.src as damage.
    124  1.1  riastrad  */
    125  1.1  riastrad void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state,
    126  1.1  riastrad 					  struct drm_plane_state *plane_state)
    127  1.1  riastrad {
    128  1.1  riastrad 	struct drm_crtc_state *crtc_state;
    129  1.1  riastrad 
    130  1.1  riastrad 	if (plane_state->crtc) {
    131  1.1  riastrad 		crtc_state = drm_atomic_get_new_crtc_state(state,
    132  1.1  riastrad 							   plane_state->crtc);
    133  1.1  riastrad 
    134  1.1  riastrad 		if (WARN_ON(!crtc_state))
    135  1.1  riastrad 			return;
    136  1.1  riastrad 
    137  1.1  riastrad 		if (drm_atomic_crtc_needs_modeset(crtc_state)) {
    138  1.1  riastrad 			drm_property_blob_put(plane_state->fb_damage_clips);
    139  1.1  riastrad 			plane_state->fb_damage_clips = NULL;
    140  1.1  riastrad 		}
    141  1.1  riastrad 	}
    142  1.1  riastrad }
    143  1.1  riastrad EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage);
    144  1.1  riastrad 
    145  1.1  riastrad /**
    146  1.1  riastrad  * drm_atomic_helper_dirtyfb - Helper for dirtyfb.
    147  1.1  riastrad  * @fb: DRM framebuffer.
    148  1.1  riastrad  * @file_priv: Drm file for the ioctl call.
    149  1.1  riastrad  * @flags: Dirty fb annotate flags.
    150  1.1  riastrad  * @color: Color for annotate fill.
    151  1.1  riastrad  * @clips: Dirty region.
    152  1.1  riastrad  * @num_clips: Count of clip in clips.
    153  1.1  riastrad  *
    154  1.1  riastrad  * A helper to implement &drm_framebuffer_funcs.dirty using damage interface
    155  1.1  riastrad  * during plane update. If num_clips is 0 then this helper will do a full plane
    156  1.1  riastrad  * update. This is the same behaviour expected by DIRTFB IOCTL.
    157  1.1  riastrad  *
    158  1.1  riastrad  * Note that this helper is blocking implementation. This is what current
    159  1.1  riastrad  * drivers and userspace expect in their DIRTYFB IOCTL implementation, as a way
    160  1.1  riastrad  * to rate-limit userspace and make sure its rendering doesn't get ahead of
    161  1.1  riastrad  * uploading new data too much.
    162  1.1  riastrad  *
    163  1.1  riastrad  * Return: Zero on success, negative errno on failure.
    164  1.1  riastrad  */
    165  1.1  riastrad int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
    166  1.1  riastrad 			      struct drm_file *file_priv, unsigned int flags,
    167  1.1  riastrad 			      unsigned int color, struct drm_clip_rect *clips,
    168  1.1  riastrad 			      unsigned int num_clips)
    169  1.1  riastrad {
    170  1.1  riastrad 	struct drm_modeset_acquire_ctx ctx;
    171  1.1  riastrad 	struct drm_property_blob *damage = NULL;
    172  1.1  riastrad 	struct drm_mode_rect *rects = NULL;
    173  1.1  riastrad 	struct drm_atomic_state *state;
    174  1.1  riastrad 	struct drm_plane *plane;
    175  1.1  riastrad 	int ret = 0;
    176  1.1  riastrad 
    177  1.1  riastrad 	/*
    178  1.1  riastrad 	 * When called from ioctl, we are interruptable, but not when called
    179  1.1  riastrad 	 * internally (ie. defio worker)
    180  1.1  riastrad 	 */
    181  1.1  riastrad 	drm_modeset_acquire_init(&ctx,
    182  1.1  riastrad 		file_priv ? DRM_MODESET_ACQUIRE_INTERRUPTIBLE : 0);
    183  1.1  riastrad 
    184  1.1  riastrad 	state = drm_atomic_state_alloc(fb->dev);
    185  1.1  riastrad 	if (!state) {
    186  1.1  riastrad 		ret = -ENOMEM;
    187  1.1  riastrad 		goto out_drop_locks;
    188  1.1  riastrad 	}
    189  1.1  riastrad 	state->acquire_ctx = &ctx;
    190  1.1  riastrad 
    191  1.1  riastrad 	if (clips) {
    192  1.1  riastrad 		uint32_t inc = 1;
    193  1.1  riastrad 
    194  1.1  riastrad 		if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
    195  1.1  riastrad 			inc = 2;
    196  1.1  riastrad 			num_clips /= 2;
    197  1.1  riastrad 		}
    198  1.1  riastrad 
    199  1.1  riastrad 		rects = kcalloc(num_clips, sizeof(*rects), GFP_KERNEL);
    200  1.1  riastrad 		if (!rects) {
    201  1.1  riastrad 			ret = -ENOMEM;
    202  1.1  riastrad 			goto out;
    203  1.1  riastrad 		}
    204  1.1  riastrad 
    205  1.1  riastrad 		convert_clip_rect_to_rect(clips, rects, num_clips, inc);
    206  1.1  riastrad 		damage = drm_property_create_blob(fb->dev,
    207  1.1  riastrad 						  num_clips * sizeof(*rects),
    208  1.1  riastrad 						  rects);
    209  1.1  riastrad 		if (IS_ERR(damage)) {
    210  1.1  riastrad 			ret = PTR_ERR(damage);
    211  1.1  riastrad 			damage = NULL;
    212  1.1  riastrad 			goto out;
    213  1.1  riastrad 		}
    214  1.1  riastrad 	}
    215  1.1  riastrad 
    216  1.1  riastrad retry:
    217  1.1  riastrad 	drm_for_each_plane(plane, fb->dev) {
    218  1.1  riastrad 		struct drm_plane_state *plane_state;
    219  1.1  riastrad 
    220  1.1  riastrad 		ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
    221  1.1  riastrad 		if (ret)
    222  1.1  riastrad 			goto out;
    223  1.1  riastrad 
    224  1.1  riastrad 		if (plane->state->fb != fb) {
    225  1.1  riastrad 			drm_modeset_unlock(&plane->mutex);
    226  1.1  riastrad 			continue;
    227  1.1  riastrad 		}
    228  1.1  riastrad 
    229  1.1  riastrad 		plane_state = drm_atomic_get_plane_state(state, plane);
    230  1.1  riastrad 		if (IS_ERR(plane_state)) {
    231  1.1  riastrad 			ret = PTR_ERR(plane_state);
    232  1.1  riastrad 			goto out;
    233  1.1  riastrad 		}
    234  1.1  riastrad 
    235  1.1  riastrad 		drm_property_replace_blob(&plane_state->fb_damage_clips,
    236  1.1  riastrad 					  damage);
    237  1.1  riastrad 	}
    238  1.1  riastrad 
    239  1.1  riastrad 	ret = drm_atomic_commit(state);
    240  1.1  riastrad 
    241  1.1  riastrad out:
    242  1.1  riastrad 	if (ret == -EDEADLK) {
    243  1.1  riastrad 		drm_atomic_state_clear(state);
    244  1.1  riastrad 		ret = drm_modeset_backoff(&ctx);
    245  1.1  riastrad 		if (!ret)
    246  1.1  riastrad 			goto retry;
    247  1.1  riastrad 	}
    248  1.1  riastrad 
    249  1.1  riastrad 	drm_property_blob_put(damage);
    250  1.1  riastrad 	kfree(rects);
    251  1.1  riastrad 	drm_atomic_state_put(state);
    252  1.1  riastrad 
    253  1.1  riastrad out_drop_locks:
    254  1.1  riastrad 	drm_modeset_drop_locks(&ctx);
    255  1.1  riastrad 	drm_modeset_acquire_fini(&ctx);
    256  1.1  riastrad 
    257  1.1  riastrad 	return ret;
    258  1.1  riastrad 
    259  1.1  riastrad }
    260  1.1  riastrad EXPORT_SYMBOL(drm_atomic_helper_dirtyfb);
    261  1.1  riastrad 
    262  1.1  riastrad /**
    263  1.1  riastrad  * drm_atomic_helper_damage_iter_init - Initialize the damage iterator.
    264  1.1  riastrad  * @iter: The iterator to initialize.
    265  1.1  riastrad  * @old_state: Old plane state for validation.
    266  1.1  riastrad  * @state: Plane state from which to iterate the damage clips.
    267  1.1  riastrad  *
    268  1.1  riastrad  * Initialize an iterator, which clips plane damage
    269  1.1  riastrad  * &drm_plane_state.fb_damage_clips to plane &drm_plane_state.src. This iterator
    270  1.1  riastrad  * returns full plane src in case damage is not present because either
    271  1.1  riastrad  * user-space didn't sent or driver discarded it (it want to do full plane
    272  1.1  riastrad  * update). Currently this iterator returns full plane src in case plane src
    273  1.1  riastrad  * changed but that can be changed in future to return damage.
    274  1.1  riastrad  *
    275  1.1  riastrad  * For the case when plane is not visible or plane update should not happen the
    276  1.1  riastrad  * first call to iter_next will return false. Note that this helper use clipped
    277  1.1  riastrad  * &drm_plane_state.src, so driver calling this helper should have called
    278  1.1  riastrad  * drm_atomic_helper_check_plane_state() earlier.
    279  1.1  riastrad  */
    280  1.1  riastrad void
    281  1.1  riastrad drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
    282  1.1  riastrad 				   const struct drm_plane_state *old_state,
    283  1.1  riastrad 				   const struct drm_plane_state *state)
    284  1.1  riastrad {
    285  1.1  riastrad 	memset(iter, 0, sizeof(*iter));
    286  1.1  riastrad 
    287  1.1  riastrad 	if (!state || !state->crtc || !state->fb || !state->visible)
    288  1.1  riastrad 		return;
    289  1.1  riastrad 
    290  1.1  riastrad 	iter->clips = drm_helper_get_plane_damage_clips(state);
    291  1.1  riastrad 	iter->num_clips = drm_plane_get_damage_clips_count(state);
    292  1.1  riastrad 
    293  1.1  riastrad 	/* Round down for x1/y1 and round up for x2/y2 to catch all pixels */
    294  1.1  riastrad 	iter->plane_src.x1 = state->src.x1 >> 16;
    295  1.1  riastrad 	iter->plane_src.y1 = state->src.y1 >> 16;
    296  1.1  riastrad 	iter->plane_src.x2 = (state->src.x2 >> 16) + !!(state->src.x2 & 0xFFFF);
    297  1.1  riastrad 	iter->plane_src.y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF);
    298  1.1  riastrad 
    299  1.1  riastrad 	if (!iter->clips || !drm_rect_equals(&state->src, &old_state->src)) {
    300  1.1  riastrad 		iter->clips = NULL;
    301  1.1  riastrad 		iter->num_clips = 0;
    302  1.1  riastrad 		iter->full_update = true;
    303  1.1  riastrad 	}
    304  1.1  riastrad }
    305  1.1  riastrad EXPORT_SYMBOL(drm_atomic_helper_damage_iter_init);
    306  1.1  riastrad 
    307  1.1  riastrad /**
    308  1.1  riastrad  * drm_atomic_helper_damage_iter_next - Advance the damage iterator.
    309  1.1  riastrad  * @iter: The iterator to advance.
    310  1.1  riastrad  * @rect: Return a rectangle in fb coordinate clipped to plane src.
    311  1.1  riastrad  *
    312  1.1  riastrad  * Since plane src is in 16.16 fixed point and damage clips are whole number,
    313  1.1  riastrad  * this iterator round off clips that intersect with plane src. Round down for
    314  1.1  riastrad  * x1/y1 and round up for x2/y2 for the intersected coordinate. Similar rounding
    315  1.1  riastrad  * off for full plane src, in case it's returned as damage. This iterator will
    316  1.1  riastrad  * skip damage clips outside of plane src.
    317  1.1  riastrad  *
    318  1.1  riastrad  * Return: True if the output is valid, false if reached the end.
    319  1.1  riastrad  *
    320  1.1  riastrad  * If the first call to iterator next returns false then it means no need to
    321  1.1  riastrad  * update the plane.
    322  1.1  riastrad  */
    323  1.1  riastrad bool
    324  1.1  riastrad drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
    325  1.1  riastrad 				   struct drm_rect *rect)
    326  1.1  riastrad {
    327  1.1  riastrad 	bool ret = false;
    328  1.1  riastrad 
    329  1.1  riastrad 	if (iter->full_update) {
    330  1.1  riastrad 		*rect = iter->plane_src;
    331  1.1  riastrad 		iter->full_update = false;
    332  1.1  riastrad 		return true;
    333  1.1  riastrad 	}
    334  1.1  riastrad 
    335  1.1  riastrad 	while (iter->curr_clip < iter->num_clips) {
    336  1.1  riastrad 		*rect = iter->clips[iter->curr_clip];
    337  1.1  riastrad 		iter->curr_clip++;
    338  1.1  riastrad 
    339  1.1  riastrad 		if (drm_rect_intersect(rect, &iter->plane_src)) {
    340  1.1  riastrad 			ret = true;
    341  1.1  riastrad 			break;
    342  1.1  riastrad 		}
    343  1.1  riastrad 	}
    344  1.1  riastrad 
    345  1.1  riastrad 	return ret;
    346  1.1  riastrad }
    347  1.1  riastrad EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
    348  1.1  riastrad 
    349  1.1  riastrad /**
    350  1.1  riastrad  * drm_atomic_helper_damage_merged - Merged plane damage
    351  1.1  riastrad  * @old_state: Old plane state for validation.
    352  1.1  riastrad  * @state: Plane state from which to iterate the damage clips.
    353  1.1  riastrad  * @rect: Returns the merged damage rectangle
    354  1.1  riastrad  *
    355  1.1  riastrad  * This function merges any valid plane damage clips into one rectangle and
    356  1.1  riastrad  * returns it in @rect.
    357  1.1  riastrad  *
    358  1.1  riastrad  * For details see: drm_atomic_helper_damage_iter_init() and
    359  1.1  riastrad  * drm_atomic_helper_damage_iter_next().
    360  1.1  riastrad  *
    361  1.1  riastrad  * Returns:
    362  1.1  riastrad  * True if there is valid plane damage otherwise false.
    363  1.1  riastrad  */
    364  1.1  riastrad bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
    365  1.1  riastrad 				     struct drm_plane_state *state,
    366  1.1  riastrad 				     struct drm_rect *rect)
    367  1.1  riastrad {
    368  1.1  riastrad 	struct drm_atomic_helper_damage_iter iter;
    369  1.1  riastrad 	struct drm_rect clip;
    370  1.1  riastrad 	bool valid = false;
    371  1.1  riastrad 
    372  1.1  riastrad 	rect->x1 = INT_MAX;
    373  1.1  riastrad 	rect->y1 = INT_MAX;
    374  1.1  riastrad 	rect->x2 = 0;
    375  1.1  riastrad 	rect->y2 = 0;
    376  1.1  riastrad 
    377  1.1  riastrad 	drm_atomic_helper_damage_iter_init(&iter, old_state, state);
    378  1.1  riastrad 	drm_atomic_for_each_plane_damage(&iter, &clip) {
    379  1.1  riastrad 		rect->x1 = min(rect->x1, clip.x1);
    380  1.1  riastrad 		rect->y1 = min(rect->y1, clip.y1);
    381  1.1  riastrad 		rect->x2 = max(rect->x2, clip.x2);
    382  1.1  riastrad 		rect->y2 = max(rect->y2, clip.y2);
    383  1.1  riastrad 		valid = true;
    384  1.1  riastrad 	}
    385  1.1  riastrad 
    386  1.1  riastrad 	return valid;
    387  1.1  riastrad }
    388  1.1  riastrad EXPORT_SYMBOL(drm_atomic_helper_damage_merged);
    389