@ -61,6 +61,7 @@ static int option_current_mode = 0;
static char * output_name ;
static char * output_name ;
static char * output_mode ;
static char * output_mode ;
static char * output_transform ;
static char * output_transform ;
static char * output_scale ;
static struct wl_list configured_output_list ;
static struct wl_list configured_output_list ;
enum output_config {
enum output_config {
@ -76,6 +77,7 @@ struct drm_configured_output {
char * name ;
char * name ;
char * mode ;
char * mode ;
uint32_t transform ;
uint32_t transform ;
int32_t scale ;
int32_t width , height ;
int32_t width , height ;
drmModeModeInfo crtc_mode ;
drmModeModeInfo crtc_mode ;
enum output_config config ;
enum output_config config ;
@ -463,6 +465,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output,
buffer - > width ! = output - > base . current - > width | |
buffer - > width ! = output - > base . current - > width | |
buffer - > height ! = output - > base . current - > height | |
buffer - > height ! = output - > base . current - > height | |
output - > base . transform ! = es - > buffer_transform | |
output - > base . transform ! = es - > buffer_transform | |
output - > base . scale ! = es - > buffer_scale | |
es - > transform . enabled )
es - > transform . enabled )
return NULL ;
return NULL ;
@ -791,6 +794,9 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
if ( es - > buffer_transform ! = output_base - > transform )
if ( es - > buffer_transform ! = output_base - > transform )
return NULL ;
return NULL ;
if ( es - > buffer_scale ! = output_base - > scale )
return NULL ;
if ( c - > sprites_are_broken )
if ( c - > sprites_are_broken )
return NULL ;
return NULL ;
@ -859,7 +865,8 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
tbox = weston_transformed_rect ( output_base - > width ,
tbox = weston_transformed_rect ( output_base - > width ,
output_base - > height ,
output_base - > height ,
output_base - > transform ,
output_base - > transform ,
1 , * box ) ;
output_base - > scale ,
* box ) ;
s - > dest_x = tbox . x1 ;
s - > dest_x = tbox . x1 ;
s - > dest_y = tbox . y1 ;
s - > dest_y = tbox . y1 ;
s - > dest_w = tbox . x2 - tbox . x1 ;
s - > dest_w = tbox . x2 - tbox . x1 ;
@ -896,7 +903,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
tbox = weston_transformed_rect ( wl_fixed_from_int ( es - > geometry . width ) ,
tbox = weston_transformed_rect ( wl_fixed_from_int ( es - > geometry . width ) ,
wl_fixed_from_int ( es - > geometry . height ) ,
wl_fixed_from_int ( es - > geometry . height ) ,
es - > buffer_transform , 1 , tbox ) ;
es - > buffer_transform , es - > buffer_scale , tbox ) ;
s - > src_x = tbox . x1 < < 8 ;
s - > src_x = tbox . x1 < < 8 ;
s - > src_y = tbox . y1 < < 8 ;
s - > src_y = tbox . y1 < < 8 ;
@ -977,8 +984,8 @@ drm_output_set_cursor(struct drm_output *output)
}
}
}
}
x = es - > geometry . x - output - > base . x ;
x = ( es - > geometry . x - output - > base . x ) * output - > base . scale ;
y = es - > geometry . y - output - > base . y ;
y = ( es - > geometry . y - output - > base . y ) * output - > base . scale ;
if ( output - > cursor_plane . x ! = x | | output - > cursor_plane . y ! = y ) {
if ( output - > cursor_plane . x ! = x | | output - > cursor_plane . y ! = y ) {
if ( drmModeMoveCursor ( c - > drm . fd , output - > crtc_id , x , y ) ) {
if ( drmModeMoveCursor ( c - > drm . fd , output - > crtc_id , x , y ) ) {
weston_log ( " failed to move cursor: %m \n " ) ;
weston_log ( " failed to move cursor: %m \n " ) ;
@ -1258,18 +1265,29 @@ init_pixman(struct drm_compositor *ec)
}
}
static struct drm_mode *
static struct drm_mode *
drm_output_add_mode ( struct drm_output * output , drmModeModeInfo * info )
drm_output_add_mode ( struct drm_output * output , drmModeModeInfo * info , struct drm_configured_output * config )
{
{
struct drm_mode * mode ;
struct drm_mode * mode ;
uint64_t refresh ;
uint64_t refresh ;
int scale ;
mode = malloc ( sizeof * mode ) ;
mode = malloc ( sizeof * mode ) ;
if ( mode = = NULL )
if ( mode = = NULL )
return NULL ;
return NULL ;
scale = 1 ;
if ( config )
scale = config - > scale ;
if ( info - > hdisplay % scale ! = 0 | |
info - > vdisplay % scale ) {
weston_log ( " Mode %dx%d not multiple of scale %d \n " , info - > hdisplay , info - > vdisplay , scale ) ;
return NULL ;
}
mode - > base . flags = 0 ;
mode - > base . flags = 0 ;
mode - > base . width = info - > hdisplay ;
mode - > base . width = info - > hdisplay / scale ;
mode - > base . height = info - > vdisplay ;
mode - > base . height = info - > vdisplay / scale ;
/* Calculate higher precision (mHz) refresh rate */
/* Calculate higher precision (mHz) refresh rate */
refresh = ( info - > clock * 1000000LL / info - > htotal +
refresh = ( info - > clock * 1000000LL / info - > htotal +
@ -1285,6 +1303,9 @@ drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
mode - > base . refresh = refresh ;
mode - > base . refresh = refresh ;
mode - > mode_info = * info ;
mode - > mode_info = * info ;
if ( scale ! = 1 )
mode - > base . flags | = WL_OUTPUT_MODE_SCALED ;
if ( info - > type & DRM_MODE_TYPE_PREFERRED )
if ( info - > type & DRM_MODE_TYPE_PREFERRED )
mode - > base . flags | = WL_OUTPUT_MODE_PREFERRED ;
mode - > base . flags | = WL_OUTPUT_MODE_PREFERRED ;
@ -1446,8 +1467,8 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
int i , flags ;
int i , flags ;
output - > surface = gbm_surface_create ( ec - > gbm ,
output - > surface = gbm_surface_create ( ec - > gbm ,
output - > base . current - > width ,
output - > base . current - > width * output - > base . scale ,
output - > base . current - > height ,
output - > base . current - > height * output - > base . scale ,
GBM_FORMAT_XRGB8888 ,
GBM_FORMAT_XRGB8888 ,
GBM_BO_USE_SCANOUT |
GBM_BO_USE_SCANOUT |
GBM_BO_USE_RENDERING ) ;
GBM_BO_USE_RENDERING ) ;
@ -1491,12 +1512,12 @@ drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c)
/* FIXME error checking */
/* FIXME error checking */
for ( i = 0 ; i < ARRAY_LENGTH ( output - > dumb ) ; i + + ) {
for ( i = 0 ; i < ARRAY_LENGTH ( output - > dumb ) ; i + + ) {
output - > dumb [ i ] = drm_fb_create_dumb ( c , w , h ) ;
output - > dumb [ i ] = drm_fb_create_dumb ( c , w * output - > base . scale , h * output - > base . scale ) ;
if ( ! output - > dumb [ i ] )
if ( ! output - > dumb [ i ] )
goto err ;
goto err ;
output - > image [ i ] =
output - > image [ i ] =
pixman_image_create_bits ( PIXMAN_x8r8g8b8 , w , h ,
pixman_image_create_bits ( PIXMAN_x8r8g8b8 , w * output - > base . scale , h * output - > base . scale ,
output - > dumb [ i ] - > map ,
output - > dumb [ i ] - > map ,
output - > dumb [ i ] - > stride ) ;
output - > dumb [ i ] - > stride ) ;
if ( ! output - > image [ i ] )
if ( ! output - > image [ i ] )
@ -1719,6 +1740,16 @@ create_output_for_connector(struct drm_compositor *ec,
snprintf ( name , 32 , " %s%d " , type_name , connector - > connector_type_id ) ;
snprintf ( name , 32 , " %s%d " , type_name , connector - > connector_type_id ) ;
output - > base . name = strdup ( name ) ;
output - > base . name = strdup ( name ) ;
wl_list_for_each ( temp , & configured_output_list , link ) {
if ( strcmp ( temp - > name , output - > base . name ) = = 0 ) {
if ( temp - > mode )
weston_log ( " %s mode \" %s \" in config \n " ,
temp - > name , temp - > mode ) ;
o = temp ;
break ;
}
}
output - > crtc_id = resources - > crtcs [ i ] ;
output - > crtc_id = resources - > crtcs [ i ] ;
output - > pipe = i ;
output - > pipe = i ;
ec - > crtc_allocator | = ( 1 < < output - > crtc_id ) ;
ec - > crtc_allocator | = ( 1 < < output - > crtc_id ) ;
@ -1742,7 +1773,7 @@ create_output_for_connector(struct drm_compositor *ec,
}
}
for ( i = 0 ; i < connector - > count_modes ; i + + ) {
for ( i = 0 ; i < connector - > count_modes ; i + + ) {
drm_mode = drm_output_add_mode ( output , & connector - > modes [ i ] ) ;
drm_mode = drm_output_add_mode ( output , & connector - > modes [ i ] , o ) ;
if ( ! drm_mode )
if ( ! drm_mode )
goto err_free ;
goto err_free ;
}
}
@ -1751,16 +1782,6 @@ create_output_for_connector(struct drm_compositor *ec,
current = NULL ;
current = NULL ;
configured = NULL ;
configured = NULL ;
wl_list_for_each ( temp , & configured_output_list , link ) {
if ( strcmp ( temp - > name , output - > base . name ) = = 0 ) {
if ( temp - > mode )
weston_log ( " %s mode \" %s \" in config \n " ,
temp - > name , temp - > mode ) ;
o = temp ;
break ;
}
}
if ( o & & o - > config = = OUTPUT_CONFIG_OFF ) {
if ( o & & o - > config = = OUTPUT_CONFIG_OFF ) {
weston_log ( " Disabling output %s \n " , o - > name ) ;
weston_log ( " Disabling output %s \n " , o - > name ) ;
@ -1771,8 +1792,8 @@ create_output_for_connector(struct drm_compositor *ec,
wl_list_for_each ( drm_mode , & output - > base . mode_list , base . link ) {
wl_list_for_each ( drm_mode , & output - > base . mode_list , base . link ) {
if ( o & & o - > config = = OUTPUT_CONFIG_MODE & &
if ( o & & o - > config = = OUTPUT_CONFIG_MODE & &
o - > width = = drm_mode - > base . width & &
o - > width = = drm_mode - > base . width * o - > scale & &
o - > height = = drm_mode - > base . height )
o - > height = = drm_mode - > base . height * o - > scale )
configured = drm_mode ;
configured = drm_mode ;
if ( ! memcmp ( & crtc_mode , & drm_mode - > mode_info , sizeof crtc_mode ) )
if ( ! memcmp ( & crtc_mode , & drm_mode - > mode_info , sizeof crtc_mode ) )
current = drm_mode ;
current = drm_mode ;
@ -1781,14 +1802,14 @@ create_output_for_connector(struct drm_compositor *ec,
}
}
if ( o & & o - > config = = OUTPUT_CONFIG_MODELINE ) {
if ( o & & o - > config = = OUTPUT_CONFIG_MODELINE ) {
configured = drm_output_add_mode ( output , & o - > crtc_mode ) ;
configured = drm_output_add_mode ( output , & o - > crtc_mode , 0 ) ;
if ( ! configured )
if ( ! configured )
goto err_free ;
goto err_free ;
current = configured ;
current = configured ;
}
}
if ( current = = NULL & & crtc_mode . clock ! = 0 ) {
if ( current = = NULL & & crtc_mode . clock ! = 0 ) {
current = drm_output_add_mode ( output , & crtc_mode ) ;
current = drm_output_add_mode ( output , & crtc_mode , 0 ) ;
if ( ! current )
if ( ! current )
goto err_free ;
goto err_free ;
}
}
@ -1814,7 +1835,8 @@ create_output_for_connector(struct drm_compositor *ec,
weston_output_init ( & output - > base , & ec - > base , x , y ,
weston_output_init ( & output - > base , & ec - > base , x , y ,
connector - > mmWidth , connector - > mmHeight ,
connector - > mmWidth , connector - > mmHeight ,
o ? o - > transform : WL_OUTPUT_TRANSFORM_NORMAL , 1 ) ;
o ? o - > transform : WL_OUTPUT_TRANSFORM_NORMAL ,
o ? o - > scale : 1 ) ;
if ( ec - > use_pixman ) {
if ( ec - > use_pixman ) {
if ( drm_output_init_pixman ( output , ec ) < 0 ) {
if ( drm_output_init_pixman ( output , ec ) < 0 ) {
@ -2622,14 +2644,16 @@ output_section_done(void *data)
output = malloc ( sizeof * output ) ;
output = malloc ( sizeof * output ) ;
if ( ! output | | ! output_name | | ( output_name [ 0 ] = = ' X ' ) | |
if ( ! output | | ! output_name | | ( output_name [ 0 ] = = ' X ' ) | |
( ! output_mode & & ! output_transform ) ) {
( ! output_mode & & ! output_transform & & ! output_scale ) ) {
free ( output_name ) ;
free ( output_name ) ;
free ( output_mode ) ;
free ( output_mode ) ;
free ( output_transform ) ;
free ( output_transform ) ;
free ( output_scale ) ;
free ( output ) ;
free ( output ) ;
output_name = NULL ;
output_name = NULL ;
output_mode = NULL ;
output_mode = NULL ;
output_transform = NULL ;
output_transform = NULL ;
output_scale = NULL ;
return ;
return ;
}
}
@ -2658,11 +2682,17 @@ output_section_done(void *data)
drm_output_set_transform ( output ) ;
drm_output_set_transform ( output ) ;
if ( ! output_scale | | sscanf ( output_scale , " %d " , & output - > scale ) ! = 1 )
output - > scale = 1 ;
wl_list_insert ( & configured_output_list , & output - > link ) ;
wl_list_insert ( & configured_output_list , & output - > link ) ;
if ( output_transform )
if ( output_transform )
free ( output_transform ) ;
free ( output_transform ) ;
output_transform = NULL ;
output_transform = NULL ;
if ( output_scale )
free ( output_scale ) ;
output_scale = NULL ;
}
}
WL_EXPORT struct weston_compositor *
WL_EXPORT struct weston_compositor *
@ -2688,6 +2718,7 @@ backend_init(struct wl_display *display, int *argc, char *argv[],
{ " name " , CONFIG_KEY_STRING , & output_name } ,
{ " name " , CONFIG_KEY_STRING , & output_name } ,
{ " mode " , CONFIG_KEY_STRING , & output_mode } ,
{ " mode " , CONFIG_KEY_STRING , & output_mode } ,
{ " transform " , CONFIG_KEY_STRING , & output_transform } ,
{ " transform " , CONFIG_KEY_STRING , & output_transform } ,
{ " scale " , CONFIG_KEY_STRING , & output_scale } ,
} ;
} ;
const struct config_section config_section [ ] = {
const struct config_section config_section [ ] = {