@@ -4869,6 +4869,35 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
48694869 return 0 ;
48704870}
48714871
4872+ static inline void fill_dc_dirty_rect (struct drm_plane * plane ,
4873+ struct rect * dirty_rect , int32_t x ,
4874+ int32_t y , int32_t width , int32_t height ,
4875+ int * i , bool ffu )
4876+ {
4877+ if (* i > DC_MAX_DIRTY_RECTS )
4878+ return ;
4879+
4880+ if (* i == DC_MAX_DIRTY_RECTS )
4881+ goto out ;
4882+
4883+ dirty_rect -> x = x ;
4884+ dirty_rect -> y = y ;
4885+ dirty_rect -> width = width ;
4886+ dirty_rect -> height = height ;
4887+
4888+ if (ffu )
4889+ drm_dbg (plane -> dev ,
4890+ "[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n" ,
4891+ plane -> base .id , width , height );
4892+ else
4893+ drm_dbg (plane -> dev ,
4894+ "[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)" ,
4895+ plane -> base .id , x , y , width , height );
4896+
4897+ out :
4898+ (* i )++ ;
4899+ }
4900+
48724901/**
48734902 * fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
48744903 *
@@ -4889,10 +4918,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
48894918 * addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
48904919 * implicitly provide damage clips without any client support via the plane
48914920 * bounds.
4892- *
4893- * Today, amdgpu_dm only supports the MPO and cursor usecase.
4894- *
4895- * TODO: Also enable for FB_DAMAGE_CLIPS
48964921 */
48974922static void fill_dc_dirty_rects (struct drm_plane * plane ,
48984923 struct drm_plane_state * old_plane_state ,
@@ -4903,33 +4928,32 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
49034928 struct dm_crtc_state * dm_crtc_state = to_dm_crtc_state (crtc_state );
49044929 struct rect * dirty_rects = flip_addrs -> dirty_rects ;
49054930 uint32_t num_clips ;
4931+ struct drm_mode_rect * clips ;
49064932 bool bb_changed ;
49074933 bool fb_changed ;
49084934 uint32_t i = 0 ;
49094935
4910- flip_addrs -> dirty_rect_count = 0 ;
4911-
49124936 /*
49134937 * Cursor plane has it's own dirty rect update interface. See
49144938 * dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
49154939 */
49164940 if (plane -> type == DRM_PLANE_TYPE_CURSOR )
49174941 return ;
49184942
4919- /*
4920- * Today, we only consider MPO use-case for PSR SU. If MPO not
4921- * requested, and there is a plane update, do FFU.
4922- */
4943+ num_clips = drm_plane_get_damage_clips_count (new_plane_state );
4944+ clips = drm_plane_get_damage_clips (new_plane_state );
4945+
49234946 if (!dm_crtc_state -> mpo_requested ) {
4924- dirty_rects [0 ].x = 0 ;
4925- dirty_rects [0 ].y = 0 ;
4926- dirty_rects [0 ].width = dm_crtc_state -> base .mode .crtc_hdisplay ;
4927- dirty_rects [0 ].height = dm_crtc_state -> base .mode .crtc_vdisplay ;
4928- flip_addrs -> dirty_rect_count = 1 ;
4929- DRM_DEBUG_DRIVER ("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n" ,
4930- new_plane_state -> plane -> base .id ,
4931- dm_crtc_state -> base .mode .crtc_hdisplay ,
4932- dm_crtc_state -> base .mode .crtc_vdisplay );
4947+ if (!num_clips || num_clips > DC_MAX_DIRTY_RECTS )
4948+ goto ffu ;
4949+
4950+ for (; flip_addrs -> dirty_rect_count < num_clips ; clips ++ )
4951+ fill_dc_dirty_rect (new_plane_state -> plane ,
4952+ & dirty_rects [i ], clips -> x1 ,
4953+ clips -> y1 , clips -> x2 - clips -> x1 ,
4954+ clips -> y2 - clips -> y1 ,
4955+ & flip_addrs -> dirty_rect_count ,
4956+ false);
49334957 return ;
49344958 }
49354959
@@ -4940,44 +4964,58 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
49404964 * If plane is moved or resized, also add old bounding box to dirty
49414965 * rects.
49424966 */
4943- num_clips = drm_plane_get_damage_clips_count (new_plane_state );
49444967 fb_changed = old_plane_state -> fb -> base .id !=
49454968 new_plane_state -> fb -> base .id ;
49464969 bb_changed = (old_plane_state -> crtc_x != new_plane_state -> crtc_x ||
49474970 old_plane_state -> crtc_y != new_plane_state -> crtc_y ||
49484971 old_plane_state -> crtc_w != new_plane_state -> crtc_w ||
49494972 old_plane_state -> crtc_h != new_plane_state -> crtc_h );
49504973
4951- DRM_DEBUG_DRIVER ("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n" ,
4952- new_plane_state -> plane -> base .id ,
4953- bb_changed , fb_changed , num_clips );
4954-
4955- if (num_clips || fb_changed || bb_changed ) {
4956- dirty_rects [i ].x = new_plane_state -> crtc_x ;
4957- dirty_rects [i ].y = new_plane_state -> crtc_y ;
4958- dirty_rects [i ].width = new_plane_state -> crtc_w ;
4959- dirty_rects [i ].height = new_plane_state -> crtc_h ;
4960- DRM_DEBUG_DRIVER ("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n" ,
4961- new_plane_state -> plane -> base .id ,
4962- dirty_rects [i ].x , dirty_rects [i ].y ,
4963- dirty_rects [i ].width , dirty_rects [i ].height );
4964- i += 1 ;
4965- }
4974+ drm_dbg (plane -> dev ,
4975+ "[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n" ,
4976+ new_plane_state -> plane -> base .id ,
4977+ bb_changed , fb_changed , num_clips );
49664978
4967- /* Add old plane bounding-box if plane is moved or resized */
49684979 if (bb_changed ) {
4969- dirty_rects [i ].x = old_plane_state -> crtc_x ;
4970- dirty_rects [i ].y = old_plane_state -> crtc_y ;
4971- dirty_rects [i ].width = old_plane_state -> crtc_w ;
4972- dirty_rects [i ].height = old_plane_state -> crtc_h ;
4973- DRM_DEBUG_DRIVER ("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n" ,
4974- old_plane_state -> plane -> base .id ,
4975- dirty_rects [i ].x , dirty_rects [i ].y ,
4976- dirty_rects [i ].width , dirty_rects [i ].height );
4977- i += 1 ;
4978- }
4980+ fill_dc_dirty_rect (new_plane_state -> plane , & dirty_rects [i ],
4981+ new_plane_state -> crtc_x ,
4982+ new_plane_state -> crtc_y ,
4983+ new_plane_state -> crtc_w ,
4984+ new_plane_state -> crtc_h , & i , false);
4985+
4986+ /* Add old plane bounding-box if plane is moved or resized */
4987+ fill_dc_dirty_rect (new_plane_state -> plane , & dirty_rects [i ],
4988+ old_plane_state -> crtc_x ,
4989+ old_plane_state -> crtc_y ,
4990+ old_plane_state -> crtc_w ,
4991+ old_plane_state -> crtc_h , & i , false);
4992+ }
4993+
4994+ if (num_clips ) {
4995+ for (; i < num_clips ; clips ++ )
4996+ fill_dc_dirty_rect (new_plane_state -> plane ,
4997+ & dirty_rects [i ], clips -> x1 ,
4998+ clips -> y1 , clips -> x2 - clips -> x1 ,
4999+ clips -> y2 - clips -> y1 , & i , false);
5000+ } else if (fb_changed && !bb_changed ) {
5001+ fill_dc_dirty_rect (new_plane_state -> plane , & dirty_rects [i ],
5002+ new_plane_state -> crtc_x ,
5003+ new_plane_state -> crtc_y ,
5004+ new_plane_state -> crtc_w ,
5005+ new_plane_state -> crtc_h , & i , false);
5006+ }
5007+
5008+ if (i > DC_MAX_DIRTY_RECTS )
5009+ goto ffu ;
49795010
49805011 flip_addrs -> dirty_rect_count = i ;
5012+ return ;
5013+
5014+ ffu :
5015+ fill_dc_dirty_rect (new_plane_state -> plane , & dirty_rects [0 ], 0 , 0 ,
5016+ dm_crtc_state -> base .mode .crtc_hdisplay ,
5017+ dm_crtc_state -> base .mode .crtc_vdisplay ,
5018+ & flip_addrs -> dirty_rect_count , true);
49815019}
49825020
49835021static void update_stream_scaling_settings (const struct drm_display_mode * mode ,
0 commit comments