@ -362,17 +362,8 @@ struct drm_output {
struct gbm_surface * gbm_surface ;
struct gbm_surface * gbm_surface ;
uint32_t gbm_format ;
uint32_t gbm_format ;
/* Plane for a fullscreen direct scanout view */
/* Plane being displayed directly on the CRTC */
struct weston_plane scanout_plane ;
struct drm_plane * scanout_plane ;
/* The last framebuffer submitted to the kernel for this CRTC. */
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 ;
/* The last state submitted to the kernel for this CRTC. */
/* The last state submitted to the kernel for this CRTC. */
struct drm_output_state * state_cur ;
struct drm_output_state * state_cur ;
@ -1369,6 +1360,8 @@ drm_output_assign_state(struct drm_output_state *state,
if ( plane - > type = = WDRM_PLANE_TYPE_OVERLAY )
if ( plane - > type = = WDRM_PLANE_TYPE_OVERLAY )
output - > vblank_pending + + ;
output - > vblank_pending + + ;
else if ( plane - > type = = WDRM_PLANE_TYPE_PRIMARY )
output - > page_flip_pending = 1 ;
}
}
}
}
@ -1416,6 +1409,8 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
{
{
struct drm_output * output = output_state - > output ;
struct drm_output * output = output_state - > output ;
struct drm_backend * b = to_drm_backend ( output - > base . compositor ) ;
struct drm_backend * b = to_drm_backend ( output - > base . compositor ) ;
struct drm_plane * scanout_plane = output - > scanout_plane ;
struct drm_plane_state * state ;
struct weston_buffer * buffer = ev - > surface - > buffer_ref . buffer ;
struct weston_buffer * buffer = ev - > surface - > buffer_ref . buffer ;
struct weston_buffer_viewport * viewport = & ev - > surface - > buffer_viewport ;
struct weston_buffer_viewport * viewport = & ev - > surface - > buffer_viewport ;
struct gbm_bo * bo ;
struct gbm_bo * bo ;
@ -1456,6 +1451,15 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
if ( ev - > alpha ! = 1.0f )
if ( ev - > alpha ! = 1.0f )
return NULL ;
return NULL ;
state = drm_output_state_get_plane ( output_state , scanout_plane ) ;
if ( state - > fb ) {
/* If there is already a framebuffer on the scanout plane,
* a client view has already been placed on the scanout
* view . In that case , do not free or put back the state ,
* but just leave it in place and quietly exit . */
return NULL ;
}
bo = gbm_bo_import ( b - > gbm , GBM_BO_IMPORT_WL_BUFFER ,
bo = gbm_bo_import ( b - > gbm , GBM_BO_IMPORT_WL_BUFFER ,
buffer - > resource , GBM_BO_USE_SCANOUT ) ;
buffer - > resource , GBM_BO_USE_SCANOUT ) ;
@ -1465,19 +1469,33 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
format = drm_output_check_scanout_format ( output , ev - > surface , bo ) ;
format = drm_output_check_scanout_format ( output , ev - > surface , bo ) ;
if ( format = = 0 ) {
if ( format = = 0 ) {
drm_plane_state_put_back ( state ) ;
gbm_bo_destroy ( bo ) ;
gbm_bo_destroy ( bo ) ;
return NULL ;
return NULL ;
}
}
output - > fb_pending = drm_fb_get_from_bo ( bo , b , format , BUFFER_CLIENT ) ;
state - > fb = drm_fb_get_from_bo ( bo , b , format , BUFFER_CLIENT ) ;
if ( ! output - > fb_pending ) {
if ( ! state - > fb ) {
drm_plane_state_put_back ( state ) ;
gbm_bo_destroy ( bo ) ;
gbm_bo_destroy ( bo ) ;
return NULL ;
return NULL ;
}
}
drm_fb_set_buffer ( output - > fb_pending , buffer ) ;
drm_fb_set_buffer ( state - > fb , buffer ) ;
return & output - > scanout_plane ;
state - > output = output ;
state - > src_x = 0 ;
state - > src_y = 0 ;
state - > src_w = state - > fb - > width < < 16 ;
state - > src_h = state - > fb - > height < < 16 ;
state - > dest_x = 0 ;
state - > dest_y = 0 ;
state - > dest_w = output - > base . current_mode - > width ;
state - > dest_h = output - > base . current_mode - > height ;
return & scanout_plane - > base ;
}
}
static struct drm_fb *
static struct drm_fb *
@ -1542,12 +1560,15 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
{
{
struct drm_output * output = state - > output ;
struct drm_output * output = state - > output ;
struct weston_compositor * c = output - > base . compositor ;
struct weston_compositor * c = output - > base . compositor ;
struct drm_plane_state * scanout_state ;
struct drm_backend * b = to_drm_backend ( c ) ;
struct drm_backend * b = to_drm_backend ( c ) ;
struct drm_fb * fb ;
struct drm_fb * fb ;
/* If we already have a client buffer promoted to scanout, then we don't
/* If we already have a client buffer promoted to scanout, then we don't
* want to render . */
* want to render . */
if ( output - > fb_pending )
scanout_state = drm_output_state_get_plane ( state ,
output - > scanout_plane ) ;
if ( scanout_state - > fb )
return ;
return ;
if ( b - > use_pixman )
if ( b - > use_pixman )
@ -1555,9 +1576,24 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
else
else
fb = drm_output_render_gl ( state , damage ) ;
fb = drm_output_render_gl ( state , damage ) ;
if ( ! fb )
if ( ! fb ) {
drm_plane_state_put_back ( scanout_state ) ;
return ;
return ;
output - > fb_pending = fb ;
}
scanout_state - > fb = fb ;
scanout_state - > output = output ;
scanout_state - > src_x = 0 ;
scanout_state - > src_y = 0 ;
scanout_state - > src_w = output - > base . current_mode - > width < < 16 ;
scanout_state - > src_h = output - > base . current_mode - > height < < 16 ;
scanout_state - > dest_x = 0 ;
scanout_state - > dest_y = 0 ;
scanout_state - > dest_w = scanout_state - > src_w > > 16 ;
scanout_state - > dest_h = scanout_state - > src_h > > 16 ;
pixman_region32_subtract ( & c - > primary_plane . damage ,
pixman_region32_subtract ( & c - > primary_plane . damage ,
& c - > primary_plane . damage , damage ) ;
& c - > primary_plane . damage , damage ) ;
@ -1620,6 +1656,8 @@ drm_output_repaint(struct weston_output *output_base,
struct drm_output * output = to_drm_output ( output_base ) ;
struct drm_output * output = to_drm_output ( output_base ) ;
struct drm_backend * backend =
struct drm_backend * backend =
to_drm_backend ( output - > base . compositor ) ;
to_drm_backend ( output - > base . compositor ) ;
struct drm_plane * scanout_plane = output - > scanout_plane ;
struct drm_plane_state * scanout_state ;
struct drm_plane_state * ps ;
struct drm_plane_state * ps ;
struct drm_plane * p ;
struct drm_plane * p ;
struct drm_mode * mode ;
struct drm_mode * mode ;
@ -1639,7 +1677,6 @@ drm_output_repaint(struct weston_output *output_base,
pending_state ,
pending_state ,
DRM_OUTPUT_STATE_CLEAR_PLANES ) ;
DRM_OUTPUT_STATE_CLEAR_PLANES ) ;
assert ( ! output - > fb_last ) ;
/* If disable_planes is set then assign_planes() wasn't
/* If disable_planes is set then assign_planes() wasn't
* called for this render , so we could still have a stale
* called for this render , so we could still have a stale
@ -1652,14 +1689,29 @@ drm_output_repaint(struct weston_output *output_base,
}
}
drm_output_render ( state , damage ) ;
drm_output_render ( state , damage ) ;
if ( ! output - > fb_pending )
scanout_state = drm_output_state_get_plane ( state , scanout_plane ) ;
if ( ! scanout_state | | ! scanout_state - > fb )
goto err ;
goto err ;
/* The legacy SetCrtc API doesn't allow us to do scaling, and the
* legacy PageFlip API doesn ' t allow us to do clipping either . */
assert ( scanout_state - > src_x = = 0 ) ;
assert ( scanout_state - > src_y = = 0 ) ;
assert ( scanout_state - > src_w = =
( unsigned ) ( output - > base . current_mode - > width < < 16 ) ) ;
assert ( scanout_state - > src_h = =
( unsigned ) ( output - > base . current_mode - > height < < 16 ) ) ;
assert ( scanout_state - > dest_x = = 0 ) ;
assert ( scanout_state - > dest_y = = 0 ) ;
assert ( scanout_state - > dest_w = = scanout_state - > src_w > > 16 ) ;
assert ( scanout_state - > dest_h = = scanout_state - > src_h > > 16 ) ;
mode = container_of ( output - > base . current_mode , struct drm_mode , base ) ;
mode = container_of ( output - > base . current_mode , struct drm_mode , base ) ;
if ( output - > state_invalid | | ! output - > fb_current | |
if ( output - > state_invalid | | ! scanout_plane - > state_cur - > fb | |
output - > fb_current - > stride ! = output - > fb_pending - > stride ) {
scanout_plane - > state_cur - > fb - > stride ! = scanout_state - > fb - > stride ) {
ret = drmModeSetCrtc ( backend - > drm . fd , output - > crtc_id ,
ret = drmModeSetCrtc ( backend - > drm . fd , output - > crtc_id ,
output - > fb_pending - > fb_id , 0 , 0 ,
scanout_state - > fb - > fb_id ,
0 , 0 ,
& output - > connector_id , 1 ,
& output - > connector_id , 1 ,
& mode - > mode_info ) ;
& mode - > mode_info ) ;
if ( ret ) {
if ( ret ) {
@ -1672,18 +1724,13 @@ drm_output_repaint(struct weston_output *output_base,
}
}
if ( drmModePageFlip ( backend - > drm . fd , output - > crtc_id ,
if ( drmModePageFlip ( backend - > drm . fd , output - > crtc_id ,
output - > fb_pending - > fb_id ,
scanout_state - > fb - > fb_id ,
DRM_MODE_PAGE_FLIP_EVENT , output ) < 0 ) {
DRM_MODE_PAGE_FLIP_EVENT , output ) < 0 ) {
weston_log ( " queueing pageflip failed: %m \n " ) ;
weston_log ( " queueing pageflip failed: %m \n " ) ;
goto err ;
goto err ;
}
}
output - > fb_last = output - > fb_current ;
output - > fb_current = output - > fb_pending ;
output - > fb_pending = NULL ;
assert ( ! output - > page_flip_pending ) ;
assert ( ! output - > page_flip_pending ) ;
output - > page_flip_pending = 1 ;
if ( output - > pageflip_timer )
if ( output - > pageflip_timer )
wl_event_source_timer_update ( output - > pageflip_timer ,
wl_event_source_timer_update ( output - > pageflip_timer ,
@ -1743,10 +1790,7 @@ drm_output_repaint(struct weston_output *output_base,
err :
err :
output - > cursor_view = NULL ;
output - > cursor_view = NULL ;
if ( output - > fb_pending ) {
drm_fb_unref ( output - > fb_pending ) ;
output - > fb_pending = NULL ;
}
drm_output_state_free ( state ) ;
drm_output_state_free ( state ) ;
return - 1 ;
return - 1 ;
@ -1759,6 +1803,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
struct drm_pending_state * pending_state = NULL ;
struct drm_pending_state * pending_state = NULL ;
struct drm_output_state * state ;
struct drm_output_state * state ;
struct drm_plane_state * plane_state ;
struct drm_plane_state * plane_state ;
struct drm_plane * scanout_plane = output - > scanout_plane ;
struct drm_backend * backend =
struct drm_backend * backend =
to_drm_backend ( output_base - > compositor ) ;
to_drm_backend ( output_base - > compositor ) ;
uint32_t fb_id ;
uint32_t fb_id ;
@ -1775,7 +1820,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
if ( output - > disable_pending | | output - > destroy_pending )
if ( output - > disable_pending | | output - > destroy_pending )
return ;
return ;
if ( ! output - > fb_current ) {
if ( ! output - > scanout_plane - > state_cur - > fb ) {
/* We can't page flip if there's no mode set */
/* We can't page flip if there's no mode set */
goto finish_frame ;
goto finish_frame ;
}
}
@ -1786,6 +1831,8 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
if ( output - > state_invalid )
if ( output - > state_invalid )
goto finish_frame ;
goto finish_frame ;
assert ( scanout_plane - > state_cur - > output = = output ) ;
/* Try to get current msc and timestamp via instant query */
/* Try to get current msc and timestamp via instant query */
vbl . request . type | = drm_waitvblank_pipe ( output ) ;
vbl . request . type | = drm_waitvblank_pipe ( output ) ;
ret = drmWaitVBlank ( backend - > drm . fd , & vbl ) ;
ret = drmWaitVBlank ( backend - > drm . fd , & vbl ) ;
@ -1815,10 +1862,9 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
/* Immediate query didn't provide valid timestamp.
/* Immediate query didn't provide valid timestamp.
* Use pageflip fallback .
* Use pageflip fallback .
*/
*/
fb_id = output - > fb_current - > fb_id ;
fb_id = scanout_plane - > state_cur - > fb - > fb_id ;
assert ( ! output - > page_flip_pending ) ;
assert ( ! output - > page_flip_pending ) ;
assert ( ! output - > fb_last ) ;
assert ( ! output - > state_last ) ;
assert ( ! output - > state_last ) ;
pending_state = drm_pending_state_alloc ( backend ) ;
pending_state = drm_pending_state_alloc ( backend ) ;
@ -1835,9 +1881,6 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
wl_event_source_timer_update ( output - > pageflip_timer ,
wl_event_source_timer_update ( output - > pageflip_timer ,
backend - > pageflip_timeout ) ;
backend - > pageflip_timeout ) ;
output - > fb_last = drm_fb_ref ( output - > fb_current ) ;
output - > page_flip_pending = 1 ;
wl_list_for_each ( plane_state , & state - > plane_list , link ) {
wl_list_for_each ( plane_state , & state - > plane_list , link ) {
if ( plane_state - > plane - > type ! = WDRM_PLANE_TYPE_OVERLAY )
if ( plane_state - > plane - > type ! = WDRM_PLANE_TYPE_OVERLAY )
continue ;
continue ;
@ -1909,9 +1952,6 @@ page_flip_handler(int fd, unsigned int frame,
assert ( output - > page_flip_pending ) ;
assert ( output - > page_flip_pending ) ;
output - > page_flip_pending = 0 ;
output - > page_flip_pending = 0 ;
drm_fb_unref ( output - > fb_last ) ;
output - > fb_last = NULL ;
if ( output - > vblank_pending )
if ( output - > vblank_pending )
return ;
return ;
@ -2591,10 +2631,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
* sledgehammer modeswitch first , and only later showing new
* sledgehammer modeswitch first , and only later showing new
* content .
* content .
*/
*/
drm_fb_unref ( output - > fb_current ) ;
output - > state_invalid = true ;
assert ( ! output - > fb_last ) ;
assert ( ! output - > fb_pending ) ;
output - > fb_last = output - > fb_current = NULL ;
if ( b - > use_pixman ) {
if ( b - > use_pixman ) {
drm_output_fini_pixman ( output ) ;
drm_output_fini_pixman ( output ) ;
@ -2917,6 +2954,13 @@ drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output,
case WDRM_PLANE_TYPE_CURSOR :
case WDRM_PLANE_TYPE_CURSOR :
format = GBM_FORMAT_ARGB8888 ;
format = GBM_FORMAT_ARGB8888 ;
break ;
break ;
case WDRM_PLANE_TYPE_PRIMARY :
/* We don't know what formats the primary plane supports
* before universal planes , so we just assume that the
* GBM format works ; however , this isn ' t set until after
* the output is created . */
format = 0 ;
break ;
default :
default :
assert ( ! " invalid type in drm_output_find_special_plane " ) ;
assert ( ! " invalid type in drm_output_find_special_plane " ) ;
break ;
break ;
@ -2939,14 +2983,16 @@ drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output,
* same plane for two outputs . */
* same plane for two outputs . */
wl_list_for_each ( tmp , & b - > compositor - > pending_output_list ,
wl_list_for_each ( tmp , & b - > compositor - > pending_output_list ,
base . link ) {
base . link ) {
if ( tmp - > cursor_plane = = plane ) {
if ( tmp - > cursor_plane = = plane | |
tmp - > scanout_plane = = plane ) {
found_elsewhere = true ;
found_elsewhere = true ;
break ;
break ;
}
}
}
}
wl_list_for_each ( tmp , & b - > compositor - > output_list ,
wl_list_for_each ( tmp , & b - > compositor - > output_list ,
base . link ) {
base . link ) {
if ( tmp - > cursor_plane = = plane ) {
if ( tmp - > cursor_plane = = plane | |
tmp - > scanout_plane = = plane ) {
found_elsewhere = true ;
found_elsewhere = true ;
break ;
break ;
}
}
@ -3352,6 +3398,19 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
static void
static void
drm_output_fini_egl ( struct drm_output * output )
drm_output_fini_egl ( struct drm_output * output )
{
{
struct drm_backend * b = to_drm_backend ( output - > base . compositor ) ;
/* Destroying the GBM surface will destroy all our GBM buffers,
* regardless of refcount . Ensure we destroy them here . */
if ( ! b - > shutting_down & &
output - > scanout_plane - > state_cur - > fb & &
output - > scanout_plane - > state_cur - > fb - > type = = BUFFER_GBM_SURFACE ) {
drm_plane_state_free ( output - > scanout_plane - > state_cur , true ) ;
output - > scanout_plane - > state_cur =
drm_plane_state_alloc ( NULL , output - > scanout_plane ) ;
output - > scanout_plane - > state_cur - > complete = true ;
}
gl_renderer - > output_destroy ( & output - > base ) ;
gl_renderer - > output_destroy ( & output - > base ) ;
gbm_surface_destroy ( output - > gbm_surface ) ;
gbm_surface_destroy ( output - > gbm_surface ) ;
drm_output_fini_cursor_egl ( output ) ;
drm_output_fini_cursor_egl ( output ) ;
@ -3417,8 +3476,20 @@ err:
static void
static void
drm_output_fini_pixman ( struct drm_output * output )
drm_output_fini_pixman ( struct drm_output * output )
{
{
struct drm_backend * b = to_drm_backend ( output - > base . compositor ) ;
unsigned int i ;
unsigned int i ;
/* Destroying the Pixman surface will destroy all our buffers,
* regardless of refcount . Ensure we destroy them here . */
if ( ! b - > shutting_down & &
output - > scanout_plane - > state_cur - > fb & &
output - > scanout_plane - > state_cur - > fb - > type = = BUFFER_PIXMAN_DUMB ) {
drm_plane_state_free ( output - > scanout_plane - > state_cur , true ) ;
output - > scanout_plane - > state_cur =
drm_plane_state_alloc ( NULL , output - > scanout_plane ) ;
output - > scanout_plane - > state_cur - > complete = true ;
}
pixman_renderer_output_destroy ( & output - > base ) ;
pixman_renderer_output_destroy ( & output - > base ) ;
pixman_region32_fini ( & output - > previous_damage ) ;
pixman_region32_fini ( & output - > previous_damage ) ;
@ -3821,6 +3892,12 @@ drm_output_set_gbm_format(struct weston_output *base,
if ( parse_gbm_format ( gbm_format , b - > gbm_format , & output - > gbm_format ) = = - 1 )
if ( parse_gbm_format ( gbm_format , b - > gbm_format , & output - > gbm_format ) = = - 1 )
output - > gbm_format = b - > gbm_format ;
output - > gbm_format = b - > gbm_format ;
/* Without universal planes, we can't discover which formats are
* supported by the primary plane ; we just hope that the GBM format
* works . */
if ( ! b - > universal_planes )
output - > scanout_plane - > formats [ 0 ] = output - > gbm_format ;
}
}
static void
static void
@ -3872,8 +3949,6 @@ drm_output_enable(struct weston_output *base)
output - > base . gamma_size = output - > original_crtc - > gamma_size ;
output - > base . gamma_size = output - > original_crtc - > gamma_size ;
output - > base . set_gamma = drm_output_set_gamma ;
output - > base . set_gamma = drm_output_set_gamma ;
weston_plane_init ( & output - > scanout_plane , b - > compositor , 0 , 0 ) ;
if ( output - > cursor_plane )
if ( output - > cursor_plane )
weston_compositor_stack_plane ( b - > compositor ,
weston_compositor_stack_plane ( b - > compositor ,
& output - > cursor_plane - > base ,
& output - > cursor_plane - > base ,
@ -3881,7 +3956,8 @@ drm_output_enable(struct weston_output *base)
else
else
b - > cursors_are_broken = 1 ;
b - > cursors_are_broken = 1 ;
weston_compositor_stack_plane ( b - > compositor , & output - > scanout_plane ,
weston_compositor_stack_plane ( b - > compositor ,
& output - > scanout_plane - > base ,
& b - > compositor - > primary_plane ) ;
& b - > compositor - > primary_plane ) ;
weston_log ( " Output %s, (connector %d, crtc %d) \n " ,
weston_log ( " Output %s, (connector %d, crtc %d) \n " ,
@ -3910,29 +3986,25 @@ drm_output_deinit(struct weston_output *base)
struct drm_output * output = to_drm_output ( base ) ;
struct drm_output * output = to_drm_output ( base ) ;
struct drm_backend * b = to_drm_backend ( base - > compositor ) ;
struct drm_backend * b = to_drm_backend ( base - > compositor ) ;
/* output->fb_last and output->fb_pending must not be set here;
* destroy_pending / disable_pending exist to guarantee exactly this . */
assert ( ! output - > fb_last ) ;
assert ( ! output - > fb_pending ) ;
drm_fb_unref ( output - > fb_current ) ;
output - > fb_current = NULL ;
if ( b - > use_pixman )
if ( b - > use_pixman )
drm_output_fini_pixman ( output ) ;
drm_output_fini_pixman ( output ) ;
else
else
drm_output_fini_egl ( output ) ;
drm_output_fini_egl ( output ) ;
weston_plane_release ( & output - > scanout_plane ) ;
/* Since our planes are no longer in use anywhere, remove their base
/* Since our planes are no longer in use anywhere, remove their base
* weston_plane ' s link from the plane stacking list , unless we ' re
* weston_plane ' s link from the plane stacking list , unless we ' re
* shutting down , in which case the plane has already been
* shutting down , in which case the plane has already been
* destroyed . */
* destroyed . */
if ( output - > cursor_plane & & ! b - > shutting_down ) {
if ( ! b - > shutting_down ) {
wl_list_remove ( & output - > cursor_plane - > base . link ) ;
wl_list_remove ( & output - > scanout_plane - > base . link ) ;
wl_list_init ( & output - > cursor_plane - > base . link ) ;
wl_list_init ( & output - > scanout_plane - > base . link ) ;
/* Turn off hardware cursor */
drmModeSetCursor ( b - > drm . fd , output - > crtc_id , 0 , 0 , 0 ) ;
if ( output - > cursor_plane ) {
wl_list_remove ( & output - > cursor_plane - > base . link ) ;
wl_list_init ( & output - > cursor_plane - > base . link ) ;
/* Turn off hardware cursor */
drmModeSetCursor ( b - > drm . fd , output - > crtc_id , 0 , 0 , 0 ) ;
}
}
}
}
}
@ -3968,6 +4040,7 @@ drm_output_destroy(struct weston_output *base)
*/
*/
if ( output - > cursor_plane )
if ( output - > cursor_plane )
drm_plane_destroy ( output - > cursor_plane ) ;
drm_plane_destroy ( output - > cursor_plane ) ;
drm_plane_destroy ( output - > scanout_plane ) ;
}
}
wl_list_for_each_safe ( drm_mode , next , & output - > base . mode_list ,
wl_list_for_each_safe ( drm_mode , next , & output - > base . mode_list ,
@ -4016,10 +4089,6 @@ drm_output_disable(struct weston_output *base)
if ( output - > base . enabled )
if ( output - > base . enabled )
drm_output_deinit ( & output - > base ) ;
drm_output_deinit ( & output - > base ) ;
assert ( ! output - > fb_last ) ;
assert ( ! output - > fb_current ) ;
assert ( ! output - > fb_pending ) ;
output - > disable_pending = 0 ;
output - > disable_pending = 0 ;
weston_log ( " Disabling output %s \n " , output - > base . name ) ;
weston_log ( " Disabling output %s \n " , output - > base . name ) ;
@ -4130,6 +4199,16 @@ create_output_for_connector(struct drm_backend *b,
}
}
}
}
output - > scanout_plane =
drm_output_find_special_plane ( b , output ,
WDRM_PLANE_TYPE_PRIMARY ) ;
if ( ! output - > scanout_plane ) {
weston_log ( " Failed to find primary plane for output %s \n " ,
output - > base . name ) ;
drm_output_destroy ( & output - > base ) ;
return - 1 ;
}
/* Failing to find a cursor plane is not fatal, as we'll fall back
/* Failing to find a cursor plane is not fatal, as we'll fall back
* to software cursor . */
* to software cursor . */
output - > cursor_plane =
output - > cursor_plane =
@ -4610,7 +4689,8 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
if ( ! output - > recorder )
if ( ! output - > recorder )
return ;
return ;
ret = drmPrimeHandleToFD ( b - > drm . fd , output - > fb_current - > handle ,
ret = drmPrimeHandleToFD ( b - > drm . fd ,
output - > scanout_plane - > state_cur - > fb - > handle ,
DRM_CLOEXEC , & fd ) ;
DRM_CLOEXEC , & fd ) ;
if ( ret ) {
if ( ret ) {
weston_log ( " [libva recorder] "
weston_log ( " [libva recorder] "
@ -4619,7 +4699,7 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
}
}
ret = vaapi_recorder_frame ( output - > recorder , fd ,
ret = vaapi_recorder_frame ( output - > recorder , fd ,
output - > fb_current - > stride ) ;
output - > scanout_plane - > state_cur - > fb - > stride ) ;
if ( ret < 0 ) {
if ( ret < 0 ) {
weston_log ( " [libva recorder] aborted: %m \n " ) ;
weston_log ( " [libva recorder] aborted: %m \n " ) ;
recorder_destroy ( output ) ;
recorder_destroy ( output ) ;