@@ -4869,6 +4869,35 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
4869
4869
return 0 ;
4870
4870
}
4871
4871
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
+
4872
4901
/**
4873
4902
* fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
4874
4903
*
@@ -4889,10 +4918,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
4889
4918
* addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
4890
4919
* implicitly provide damage clips without any client support via the plane
4891
4920
* bounds.
4892
- *
4893
- * Today, amdgpu_dm only supports the MPO and cursor usecase.
4894
- *
4895
- * TODO: Also enable for FB_DAMAGE_CLIPS
4896
4921
*/
4897
4922
static void fill_dc_dirty_rects (struct drm_plane * plane ,
4898
4923
struct drm_plane_state * old_plane_state ,
@@ -4903,33 +4928,32 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
4903
4928
struct dm_crtc_state * dm_crtc_state = to_dm_crtc_state (crtc_state );
4904
4929
struct rect * dirty_rects = flip_addrs -> dirty_rects ;
4905
4930
uint32_t num_clips ;
4931
+ struct drm_mode_rect * clips ;
4906
4932
bool bb_changed ;
4907
4933
bool fb_changed ;
4908
4934
uint32_t i = 0 ;
4909
4935
4910
- flip_addrs -> dirty_rect_count = 0 ;
4911
-
4912
4936
/*
4913
4937
* Cursor plane has it's own dirty rect update interface. See
4914
4938
* dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
4915
4939
*/
4916
4940
if (plane -> type == DRM_PLANE_TYPE_CURSOR )
4917
4941
return ;
4918
4942
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
+
4923
4946
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);
4933
4957
return ;
4934
4958
}
4935
4959
@@ -4940,44 +4964,58 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
4940
4964
* If plane is moved or resized, also add old bounding box to dirty
4941
4965
* rects.
4942
4966
*/
4943
- num_clips = drm_plane_get_damage_clips_count (new_plane_state );
4944
4967
fb_changed = old_plane_state -> fb -> base .id !=
4945
4968
new_plane_state -> fb -> base .id ;
4946
4969
bb_changed = (old_plane_state -> crtc_x != new_plane_state -> crtc_x ||
4947
4970
old_plane_state -> crtc_y != new_plane_state -> crtc_y ||
4948
4971
old_plane_state -> crtc_w != new_plane_state -> crtc_w ||
4949
4972
old_plane_state -> crtc_h != new_plane_state -> crtc_h );
4950
4973
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 );
4966
4978
4967
- /* Add old plane bounding-box if plane is moved or resized */
4968
4979
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 ;
4979
5010
4980
5011
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);
4981
5019
}
4982
5020
4983
5021
static void update_stream_scaling_settings (const struct drm_display_mode * mode ,
0 commit comments