@ -162,6 +162,50 @@ struct drm_edid {
char serial_number [ 13 ] ;
} ;
/**
* A plane represents one buffer , positioned within a CRTC , and stacked
* relative to other planes on the same CRTC .
*
* Each CRTC has a ' primary plane ' , which use used to display the classic
* framebuffer contents , as accessed through the legacy drmModeSetCrtc
* call ( which combines setting the CRTC ' s actual physical mode , and the
* properties of the primary plane ) .
*
* The cursor plane also has its own alternate legacy API .
*
* Other planes are used opportunistically to display content we do not
* wish to blit into the primary plane . These non - primary / cursor planes
* are referred to as ' sprites ' .
*/
struct drm_plane {
struct wl_list link ;
struct weston_plane base ;
struct drm_output * output ;
struct drm_backend * backend ;
uint32_t possible_crtcs ;
uint32_t plane_id ;
uint32_t count_formats ;
/* The last framebuffer submitted to the kernel for this plane. */
struct drm_fb * fb_current ;
/* The previously-submitted framebuffer, where the hardware has not
* yet acknowledged display of fb_current . */
struct drm_fb * fb_last ;
/* Framebuffer we are going to submit to the kernel when the current
* repaint is flushed . */
struct drm_fb * fb_pending ;
int32_t src_x , src_y ;
uint32_t src_w , src_h ;
uint32_t dest_x , dest_y ;
uint32_t dest_w , dest_h ;
uint32_t formats [ ] ;
} ;
struct drm_output {
struct weston_output base ;
drmModeConnector * connector ;
@ -211,39 +255,6 @@ struct drm_output {
struct wl_event_source * pageflip_timer ;
} ;
/*
* An output has a primary display plane plus zero or more sprites for
* blending display contents .
*/
struct drm_sprite {
struct wl_list link ;
struct weston_plane plane ;
struct drm_output * output ;
struct drm_backend * backend ;
uint32_t possible_crtcs ;
uint32_t plane_id ;
uint32_t count_formats ;
/* The last framebuffer submitted to the kernel for this plane. */
struct drm_fb * fb_current ;
/* The previously-submitted framebuffer, where the hardware has not
* yet acknowledged display of fb_current . */
struct drm_fb * fb_last ;
/* Framebuffer we are going to submit to the kernel when the current
* repaint is flushed . */
struct drm_fb * fb_pending ;
int32_t src_x , src_y ;
uint32_t src_w , src_h ;
uint32_t dest_x , dest_y ;
uint32_t dest_w , dest_h ;
uint32_t formats [ ] ;
} ;
static struct gl_renderer_interface * gl_renderer ;
static const char default_seat [ ] = " seat0 " ;
@ -306,9 +317,9 @@ static void
drm_output_update_msc ( struct drm_output * output , unsigned int seq ) ;
static int
drm_sprit e_crtc_supported ( struct drm_output * output , struct drm_sprite * sprit e )
drm_plan e_crtc_supported ( struct drm_output * output , struct drm_plane * plan e )
{
return ! ! ( sprit e- > possible_crtcs & ( 1 < < output - > pipe ) ) ;
return ! ! ( plan e- > possible_crtcs & ( 1 < < output - > pipe ) ) ;
}
static struct drm_output *
@ -845,7 +856,7 @@ drm_output_repaint(struct weston_output *output_base,
struct drm_output * output = to_drm_output ( output_base ) ;
struct drm_backend * backend =
to_drm_backend ( output - > base . compositor ) ;
struct drm_sprit e * s ;
struct drm_plan e * s ;
struct drm_mode * mode ;
int ret = 0 ;
@ -905,7 +916,7 @@ drm_output_repaint(struct weston_output *output_base,
/* XXX: Set output much earlier, so we don't attempt to place
* planes on entirely the wrong output . */
if ( ( ! s - > fb_current & & ! s - > fb_pending ) | |
! drm_sprit e_crtc_supported ( output , s ) )
! drm_plan e_crtc_supported ( output , s ) )
continue ;
if ( s - > fb_pending & & ! backend - > sprites_hidden )
@ -1048,7 +1059,7 @@ static void
vblank_handler ( int fd , unsigned int frame , unsigned int sec , unsigned int usec ,
void * data )
{
struct drm_sprit e * s = ( struct drm_sprit e * ) data ;
struct drm_plan e * s = ( struct drm_plan e * ) data ;
struct drm_output * output = s - > output ;
struct timespec ts ;
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
@ -1115,7 +1126,7 @@ page_flip_handler(int fd, unsigned int frame,
}
static uint32_t
drm_output_check_sprite_format ( struct drm_sprite * s ,
drm_output_check_plane_format ( struct drm_plane * p ,
struct weston_view * ev , struct gbm_bo * bo )
{
uint32_t i , format ;
@ -1136,8 +1147,8 @@ drm_output_check_sprite_format(struct drm_sprite *s,
pixman_region32_fini ( & r ) ;
}
for ( i = 0 ; i < s - > count_formats ; i + + )
if ( s - > formats [ i ] = = format )
for ( i = 0 ; i < p - > count_formats ; i + + )
if ( p - > formats [ i ] = = format )
return format ;
return 0 ;
@ -1151,7 +1162,7 @@ drm_output_prepare_overlay_view(struct drm_output *output,
struct drm_backend * b = to_drm_backend ( ec ) ;
struct weston_buffer_viewport * viewport = & ev - > surface - > buffer_viewport ;
struct wl_resource * buffer_resource ;
struct drm_sprite * s ;
struct drm_plane * p ;
struct linux_dmabuf_buffer * dmabuf ;
int found = 0 ;
struct gbm_bo * bo ;
@ -1187,11 +1198,11 @@ drm_output_prepare_overlay_view(struct drm_output *output,
if ( ev - > alpha ! = 1.0f )
return NULL ;
wl_list_for_each ( s , & b - > sprite_list , link ) {
if ( ! drm_sprit e_crtc_supported ( output , s ) )
wl_list_for_each ( p , & b - > sprite_list , link ) {
if ( ! drm_plan e_crtc_supported ( output , p ) )
continue ;
if ( ! s - > fb_pending ) {
if ( ! p - > fb_pending ) {
found = 1 ;
break ;
}
@ -1244,23 +1255,23 @@ drm_output_prepare_overlay_view(struct drm_output *output,
if ( ! bo )
return NULL ;
format = drm_output_check_sprite_format ( s , ev , bo ) ;
format = drm_output_check_plane_format ( p , ev , bo ) ;
if ( format = = 0 ) {
gbm_bo_destroy ( bo ) ;
return NULL ;
}
s - > fb_pending = drm_fb_get_from_bo ( bo , b , format , BUFFER_CLIENT ) ;
if ( ! s - > fb_pending ) {
p - > fb_pending = drm_fb_get_from_bo ( bo , b , format , BUFFER_CLIENT ) ;
if ( ! p - > fb_pending ) {
gbm_bo_destroy ( bo ) ;
return NULL ;
}
drm_fb_set_buffer ( s - > fb_pending , ev - > surface - > buffer_ref . buffer ) ;
drm_fb_set_buffer ( p - > fb_pending , ev - > surface - > buffer_ref . buffer ) ;
box = pixman_region32_extents ( & ev - > transform . boundingbox ) ;
s - > plan e. x = box - > x1 ;
s - > plan e. y = box - > y1 ;
p - > bas e. x = box - > x1 ;
p - > bas e. y = box - > y1 ;
/*
* Calculate the source & dest rects properly based on actual
@ -1277,10 +1288,10 @@ drm_output_prepare_overlay_view(struct drm_output *output,
output - > base . transform ,
output - > base . current_scale ,
* box ) ;
s - > dest_x = tbox . x1 ;
s - > dest_y = tbox . y1 ;
s - > dest_w = tbox . x2 - tbox . x1 ;
s - > dest_h = tbox . y2 - tbox . y1 ;
p - > dest_x = tbox . x1 ;
p - > dest_y = tbox . y1 ;
p - > dest_w = tbox . x2 - tbox . x1 ;
p - > dest_h = tbox . y2 - tbox . y1 ;
pixman_region32_fini ( & dest_rect ) ;
pixman_region32_init ( & src_rect ) ;
@ -1317,13 +1328,13 @@ drm_output_prepare_overlay_view(struct drm_output *output,
viewport - > buffer . scale ,
tbox ) ;
s - > src_x = tbox . x1 < < 8 ;
s - > src_y = tbox . y1 < < 8 ;
s - > src_w = ( tbox . x2 - tbox . x1 ) < < 8 ;
s - > src_h = ( tbox . y2 - tbox . y1 ) < < 8 ;
p - > src_x = tbox . x1 < < 8 ;
p - > src_y = tbox . y1 < < 8 ;
p - > src_w = ( tbox . x2 - tbox . x1 ) < < 8 ;
p - > src_h = ( tbox . y2 - tbox . y1 ) < < 8 ;
pixman_region32_fini ( & src_rect ) ;
return & s - > plan e;
return & p - > bas e;
}
static struct weston_plane *
@ -2832,71 +2843,71 @@ err:
static void
create_sprites ( struct drm_backend * b )
{
struct drm_sprite * sprit e ;
drmModePlaneRes * plane_res ;
drmModePlane * plane ;
struct drm_plane * plan e ;
drmModePlaneRes * k plane_res;
drmModePlane * k plane;
uint32_t i ;
plane_res = drmModeGetPlaneResources ( b - > drm . fd ) ;
if ( ! plane_res ) {
k plane_res = drmModeGetPlaneResources ( b - > drm . fd ) ;
if ( ! k plane_res) {
weston_log ( " failed to get plane resources: %s \n " ,
strerror ( errno ) ) ;
return ;
}
for ( i = 0 ; i < plane_res - > count_planes ; i + + ) {
plane = drmModeGetPlane ( b - > drm . fd , plane_res - > planes [ i ] ) ;
if ( ! plane )
for ( i = 0 ; i < k plane_res- > count_planes ; i + + ) {
k plane = drmModeGetPlane ( b - > drm . fd , k plane_res- > planes [ i ] ) ;
if ( ! k plane)
continue ;
sprit e = zalloc ( sizeof ( * sprit e) + ( ( sizeof ( uint32_t ) ) *
plane - > count_formats ) ) ;
if ( ! sprit e) {
plan e = zalloc ( sizeof ( * plan e) + ( ( sizeof ( uint32_t ) ) *
k plane- > count_formats ) ) ;
if ( ! plan e) {
weston_log ( " %s: out of memory \n " ,
__func__ ) ;
drmModeFreePlane ( plane ) ;
drmModeFreePlane ( k plane) ;
continue ;
}
sprit e- > possible_crtcs = plane - > possible_crtcs ;
sprit e- > plane_id = plane - > plane_id ;
sprit e- > fb_last = NULL ;
sprit e- > fb_current = NULL ;
sprit e- > fb_pending = NULL ;
sprit e- > backend = b ;
sprit e- > count_formats = plane - > count_formats ;
memcpy ( sprit e- > formats , plane - > formats ,
plane - > count_formats * sizeof ( plane - > formats [ 0 ] ) ) ;
drmModeFreePlane ( plane ) ;
weston_plane_init ( & sprite - > plan e, b - > compositor , 0 , 0 ) ;
weston_compositor_stack_plane ( b - > compositor , & sprite - > plan e,
plan e- > possible_crtcs = k plane- > possible_crtcs ;
plan e- > plane_id = k plane- > plane_id ;
plan e- > fb_last = NULL ;
plan e- > fb_current = NULL ;
plan e- > fb_pending = NULL ;
plan e- > backend = b ;
plan e- > count_formats = k plane- > count_formats ;
memcpy ( plan e- > formats , k plane- > formats ,
k plane- > count_formats * sizeof ( k plane- > formats [ 0 ] ) ) ;
drmModeFreePlane ( k plane) ;
weston_plane_init ( & plane - > bas e, b - > compositor , 0 , 0 ) ;
weston_compositor_stack_plane ( b - > compositor , & plane - > bas e,
& b - > compositor - > primary_plane ) ;
wl_list_insert ( & b - > sprite_list , & sprit e- > link ) ;
wl_list_insert ( & b - > sprite_list , & plan e- > link ) ;
}
drmModeFreePlaneResources ( plane_res ) ;
drmModeFreePlaneResources ( k plane_res) ;
}
static void
destroy_sprites ( struct drm_backend * backend )
{
struct drm_sprite * sprit e , * next ;
struct drm_plane * plan e , * next ;
struct drm_output * output ;
output = container_of ( backend - > compositor - > output_list . next ,
struct drm_output , base . link ) ;
wl_list_for_each_safe ( sprit e, next , & backend - > sprite_list , link ) {
wl_list_for_each_safe ( plan e, next , & backend - > sprite_list , link ) {
drmModeSetPlane ( backend - > drm . fd ,
sprit e- > plane_id ,
plan e- > plane_id ,
output - > crtc_id , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
assert ( ! sprit e- > fb_last ) ;
assert ( ! sprit e- > fb_pending ) ;
drm_fb_unref ( sprit e- > fb_current ) ;
weston_plane_release ( & sprite - > plan e) ;
free ( sprit e) ;
assert ( ! plan e- > fb_last ) ;
assert ( ! plan e- > fb_pending ) ;
drm_fb_unref ( plan e- > fb_current ) ;
weston_plane_release ( & plane - > bas e) ;
free ( plan e) ;
}
}
@ -3102,7 +3113,7 @@ session_notify(struct wl_listener *listener, void *data)
{
struct weston_compositor * compositor = data ;
struct drm_backend * b = to_drm_backend ( compositor ) ;
struct drm_sprit e * sprite ;
struct drm_plan e * sprite ;
struct drm_output * output ;
if ( compositor - > session_active ) {