2018-10-16 13:46:08 -07:00
// SPDX-License-Identifier: GPL-2.0
2018-05-03 13:22:17 +02:00
/*
2018-10-16 13:46:08 -07:00
* Test cases for the drm_plane_helper functions
2022-07-08 17:30:48 -03:00
*
* Copyright ( c ) 2022 Maíra Canal < mairacanal @ riseup . net >
2018-05-03 13:22:17 +02:00
*/
2022-07-08 17:30:48 -03:00
# include <kunit/test.h>
2018-05-03 13:22:17 +02:00
# include <drm/drm_atomic_helper.h>
2022-06-14 12:54:49 +03:00
# include <drm/drm_framebuffer.h>
2018-05-03 13:22:17 +02:00
# include <drm/drm_modes.h>
2022-10-20 10:21:34 +02:00
# include <drm/drm_rect.h>
2018-05-03 13:22:17 +02:00
2022-10-20 10:21:35 +02:00
static const struct drm_crtc_state crtc_state = {
. crtc = ZERO_SIZE_PTR ,
. enable = true ,
. active = true ,
. mode = {
DRM_MODE ( " 1024x768 " , 0 , 65000 , 1024 , 1048 ,
1184 , 1344 , 0 , 768 , 771 , 777 , 806 , 0 ,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC )
} ,
} ;
struct drm_check_plane_state_test {
const char * name ;
const char * msg ;
struct {
unsigned int x ;
unsigned int y ;
unsigned int w ;
unsigned int h ;
} src , src_expected ;
struct {
int x ;
int y ;
unsigned int w ;
unsigned int h ;
} crtc , crtc_expected ;
unsigned int rotation ;
int min_scale ;
int max_scale ;
bool can_position ;
} ;
static int drm_plane_helper_init ( struct kunit * test )
2018-05-03 13:22:17 +02:00
{
2022-10-20 10:21:35 +02:00
const struct drm_check_plane_state_test * params = test - > param_value ;
struct drm_plane * plane ;
struct drm_framebuffer * fb ;
struct drm_plane_state * mock ;
plane = kunit_kzalloc ( test , sizeof ( * plane ) , GFP_KERNEL ) ;
KUNIT_ASSERT_NOT_NULL ( test , plane ) ;
fb = kunit_kzalloc ( test , sizeof ( * fb ) , GFP_KERNEL ) ;
KUNIT_ASSERT_NOT_NULL ( test , fb ) ;
fb - > width = 2048 ;
fb - > height = 2048 ;
mock = kunit_kzalloc ( test , sizeof ( * mock ) , GFP_KERNEL ) ;
KUNIT_ASSERT_NOT_NULL ( test , mock ) ;
mock - > plane = plane ;
mock - > crtc = ZERO_SIZE_PTR ;
mock - > fb = fb ;
mock - > rotation = params - > rotation ;
mock - > src_x = params - > src . x ;
mock - > src_y = params - > src . y ;
mock - > src_w = params - > src . w ;
mock - > src_h = params - > src . h ;
mock - > crtc_x = params - > crtc . x ;
mock - > crtc_y = params - > crtc . y ;
mock - > crtc_w = params - > crtc . w ;
mock - > crtc_h = params - > crtc . h ;
test - > priv = mock ;
return 0 ;
2018-05-03 13:22:17 +02:00
}
2022-10-20 10:21:35 +02:00
static void check_src_eq ( struct kunit * test , struct drm_plane_state * plane_state ,
2022-07-08 17:30:48 -03:00
unsigned int src_x , unsigned int src_y ,
unsigned int src_w , unsigned int src_h )
2018-05-03 13:22:17 +02:00
{
2022-10-20 10:21:34 +02:00
struct drm_rect expected = DRM_RECT_INIT ( src_x , src_y , src_w , src_h ) ;
2022-10-20 10:21:35 +02:00
KUNIT_ASSERT_GE_MSG ( test , plane_state - > src . x1 , 0 ,
" src x coordinate %x should never be below 0, src: " DRM_RECT_FP_FMT ,
plane_state - > src . x1 , DRM_RECT_FP_ARG ( & plane_state - > src ) ) ;
2018-05-03 13:22:17 +02:00
2022-10-20 10:21:35 +02:00
KUNIT_ASSERT_GE_MSG ( test , plane_state - > src . y1 , 0 ,
" src y coordinate %x should never be below 0, src: " DRM_RECT_FP_FMT ,
plane_state - > src . y1 , DRM_RECT_FP_ARG ( & plane_state - > src ) ) ;
KUNIT_EXPECT_TRUE_MSG ( test , drm_rect_equals ( & plane_state - > src , & expected ) ,
" dst: " DRM_RECT_FP_FMT " , expected: " DRM_RECT_FP_FMT ,
DRM_RECT_FP_ARG ( & plane_state - > src ) , DRM_RECT_FP_ARG ( & expected ) ) ;
2018-05-03 13:22:17 +02:00
}
2022-10-20 10:21:35 +02:00
static void check_crtc_eq ( struct kunit * test , struct drm_plane_state * plane_state ,
2018-05-03 13:22:17 +02:00
int crtc_x , int crtc_y ,
2022-07-08 17:30:48 -03:00
unsigned int crtc_w , unsigned int crtc_h )
2018-05-03 13:22:17 +02:00
{
2022-10-20 10:21:34 +02:00
struct drm_rect expected = DRM_RECT_INIT ( crtc_x , crtc_y , crtc_w , crtc_h ) ;
2022-10-20 10:21:35 +02:00
KUNIT_EXPECT_TRUE_MSG ( test , drm_rect_equals ( & plane_state - > dst , & expected ) ,
" dst: " DRM_RECT_FMT " , expected: " DRM_RECT_FMT ,
DRM_RECT_ARG ( & plane_state - > dst ) , DRM_RECT_ARG ( & expected ) ) ;
}
static void drm_test_check_plane_state ( struct kunit * test )
{
const struct drm_check_plane_state_test * params = test - > param_value ;
struct drm_plane_state * plane_state = test - > priv ;
2018-05-03 13:22:17 +02:00
2022-10-20 10:21:35 +02:00
KUNIT_ASSERT_EQ_MSG ( test ,
drm_atomic_helper_check_plane_state ( plane_state , & crtc_state ,
params - > min_scale ,
params - > max_scale ,
params - > can_position , false ) ,
0 , params - > msg ) ;
KUNIT_EXPECT_TRUE ( test , plane_state - > visible ) ;
check_src_eq ( test , plane_state , params - > src_expected . x , params - > src_expected . y ,
params - > src_expected . w , params - > src_expected . h ) ;
check_crtc_eq ( test , plane_state , params - > crtc_expected . x , params - > crtc_expected . y ,
params - > crtc_expected . w , params - > crtc_expected . h ) ;
}
2018-05-03 13:22:17 +02:00
2022-10-20 10:21:35 +02:00
static void drm_check_plane_state_desc ( const struct drm_check_plane_state_test * t ,
char * desc )
{
sprintf ( desc , " %s " , t - > name ) ;
2018-05-03 13:22:17 +02:00
}
2022-10-20 10:21:35 +02:00
static const struct drm_check_plane_state_test drm_check_plane_state_tests [ ] = {
{
. name = " clipping_simple " ,
. msg = " Simple clipping check should pass " ,
. src = { 0 , 0 ,
2048 < < 16 ,
2048 < < 16 } ,
. crtc = { 0 , 0 , 2048 , 2048 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = false ,
. src_expected = { 0 , 0 , 1024 < < 16 , 768 < < 16 } ,
. crtc_expected = { 0 , 0 , 1024 , 768 } ,
} ,
{
. name = " clipping_rotate_reflect " ,
. msg = " Rotated clipping check should pass " ,
. src = { 0 , 0 ,
2048 < < 16 ,
2048 < < 16 } ,
. crtc = { 0 , 0 , 2048 , 2048 } ,
. rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = false ,
. src_expected = { 0 , 0 , 768 < < 16 , 1024 < < 16 } ,
. crtc_expected = { 0 , 0 , 1024 , 768 } ,
} ,
{
. name = " positioning_simple " ,
. msg = " Simple positioning should work " ,
. src = { 0 , 0 , 1023 < < 16 , 767 < < 16 } ,
. crtc = { 0 , 0 , 1023 , 767 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = true ,
. src_expected = { 0 , 0 , 1023 < < 16 , 767 < < 16 } ,
. crtc_expected = { 0 , 0 , 1023 , 767 } ,
} ,
{
. name = " upscaling " ,
. msg = " Upscaling exactly 2x should work " ,
. src = { 0 , 0 , 512 < < 16 , 384 < < 16 } ,
. crtc = { 0 , 0 , 1024 , 768 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = 0x8000 ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = false ,
. src_expected = { 0 , 0 , 512 < < 16 , 384 < < 16 } ,
. crtc_expected = { 0 , 0 , 1024 , 768 } ,
} ,
{
. name = " downscaling " ,
. msg = " Should succeed with exact scaling limit " ,
. src = { 0 , 0 , 2048 < < 16 , 1536 < < 16 } ,
. crtc = { 0 , 0 , 1024 , 768 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = 0x20000 ,
. can_position = false ,
. src_expected = { 0 , 0 , 2048 < < 16 , 1536 < < 16 } ,
. crtc_expected = { 0 , 0 , 1024 , 768 } ,
} ,
{
. name = " rounding1 " ,
. msg = " Should succeed by clipping to exact multiple " ,
. src = { 0 , 0 , 0x40001 , 0x40001 } ,
. crtc = { 1022 , 766 , 4 , 4 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = 0x10001 ,
. can_position = true ,
. src_expected = { 0 , 0 , 2 < < 16 , 2 < < 16 } ,
. crtc_expected = { 1022 , 766 , 2 , 2 } ,
} ,
{
. name = " rounding2 " ,
. msg = " Should succeed by clipping to exact multiple " ,
. src = { 0x20001 , 0x20001 , 0x4040001 , 0x3040001 } ,
. crtc = { - 2 , - 2 , 1028 , 772 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = 0x10001 ,
. can_position = false ,
. src_expected = { 0x40002 , 0x40002 , 1024 < < 16 , 768 < < 16 } ,
. crtc_expected = { 0 , 0 , 1024 , 768 } ,
} ,
{
. name = " rounding3 " ,
. msg = " Should succeed by clipping to exact multiple " ,
. src = { 0 , 0 , 0x3ffff , 0x3ffff } ,
. crtc = { 1022 , 766 , 4 , 4 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = 0xffff ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = true ,
/* Should not be rounded to 0x20001, which would be upscaling. */
. src_expected = { 0 , 0 , 2 < < 16 , 2 < < 16 } ,
. crtc_expected = { 1022 , 766 , 2 , 2 } ,
} ,
{
. name = " rounding4 " ,
. msg = " Should succeed by clipping to exact multiple " ,
. src = { 0x1ffff , 0x1ffff , 0x403ffff , 0x303ffff } ,
. crtc = { - 2 , - 2 , 1028 , 772 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = 0xffff ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = false ,
. src_expected = { 0x3fffe , 0x3fffe , 1024 < < 16 , 768 < < 16 } ,
. crtc_expected = { 0 , 0 , 1024 , 768 } ,
} ,
} ;
KUNIT_ARRAY_PARAM ( drm_check_plane_state , drm_check_plane_state_tests , drm_check_plane_state_desc ) ;
static void drm_test_check_invalid_plane_state ( struct kunit * test )
2018-05-03 13:22:17 +02:00
{
2022-10-20 10:21:35 +02:00
const struct drm_check_plane_state_test * params = test - > param_value ;
struct drm_plane_state * plane_state = test - > priv ;
KUNIT_ASSERT_LT_MSG ( test ,
drm_atomic_helper_check_plane_state ( plane_state , & crtc_state ,
params - > min_scale ,
params - > max_scale ,
params - > can_position , false ) ,
0 , params - > msg ) ;
2018-05-03 13:22:17 +02:00
}
2022-07-08 17:30:48 -03:00
2022-10-20 10:21:35 +02:00
static const struct drm_check_plane_state_test drm_check_invalid_plane_state_tests [ ] = {
{
. name = " positioning_invalid " ,
. msg = " Should not be able to position on the crtc with can_position=false " ,
. src = { 0 , 0 , 1023 < < 16 , 767 < < 16 } ,
. crtc = { 0 , 0 , 1023 , 767 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = false ,
} ,
{
. name = " upscaling_invalid " ,
. msg = " Upscaling out of range should fail " ,
. src = { 0 , 0 , 512 < < 16 , 384 < < 16 } ,
. crtc = { 0 , 0 , 1024 , 768 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = 0x8001 ,
. max_scale = DRM_PLANE_NO_SCALING ,
. can_position = false ,
} ,
{
. name = " downscaling_invalid " ,
. msg = " Downscaling out of range should fail " ,
. src = { 0 , 0 , 2048 < < 16 , 1536 < < 16 } ,
. crtc = { 0 , 0 , 1024 , 768 } ,
. rotation = DRM_MODE_ROTATE_0 ,
. min_scale = DRM_PLANE_NO_SCALING ,
. max_scale = 0x1ffff ,
. can_position = false ,
} ,
} ;
KUNIT_ARRAY_PARAM ( drm_check_invalid_plane_state , drm_check_invalid_plane_state_tests ,
drm_check_plane_state_desc ) ;
2022-07-08 17:30:48 -03:00
static struct kunit_case drm_plane_helper_test [ ] = {
2022-10-20 10:21:35 +02:00
KUNIT_CASE_PARAM ( drm_test_check_plane_state , drm_check_plane_state_gen_params ) ,
KUNIT_CASE_PARAM ( drm_test_check_invalid_plane_state ,
drm_check_invalid_plane_state_gen_params ) ,
2022-07-08 17:30:48 -03:00
{ }
} ;
static struct kunit_suite drm_plane_helper_test_suite = {
. name = " drm_plane_helper " ,
2022-10-20 10:21:35 +02:00
. init = drm_plane_helper_init ,
2022-07-08 17:30:48 -03:00
. test_cases = drm_plane_helper_test ,
} ;
kunit_test_suite ( drm_plane_helper_test_suite ) ;
MODULE_LICENSE ( " GPL " ) ;