@ -104,13 +104,8 @@ enum buffer_type {
struct rpir_surface {
struct weston_surface * surface ;
/* If link is empty, the surface is guaranteed to not be on screen,
* i . e . updates removing Elements have completed .
*/
struct wl_list link ;
DISPMANX_ELEMENT_HANDLE_T handle ;
int layer ;
struct wl_list views ;
int visible_views ;
int need_swap ;
int single_buffer ;
@ -127,6 +122,20 @@ struct rpir_surface {
enum buffer_type buffer_type ;
} ;
struct rpir_view {
struct rpir_surface * surface ;
struct wl_list surface_link ;
struct weston_view * view ;
/* If link is empty, the view is guaranteed to not be on screen,
* i . e . updates removing Elements have completed .
*/
struct wl_list link ;
DISPMANX_ELEMENT_HANDLE_T handle ;
int layer ;
} ;
struct rpir_output {
DISPMANX_DISPLAY_HANDLE_T display ;
@ -134,10 +143,10 @@ struct rpir_output {
struct weston_matrix matrix ;
/* all Elements currently on screen */
struct wl_list surface _list; /* struct rpir_surface::link */
struct wl_list view _list; /* struct rpir_surface::link */
/* Elements just removed, waiting for update completion */
struct wl_list surface _cleanup_list; /* struct rpir_surface::link */
struct wl_list view _cleanup_list; /* struct rpir_surface::link */
struct rpi_resource capture_buffer ;
uint8_t * capture_data ;
@ -164,6 +173,12 @@ to_rpir_surface(struct weston_surface *surface)
return surface - > renderer_state ;
}
static inline struct rpir_view *
to_rpir_view ( struct weston_view * view )
{
return view - > renderer_state ;
}
static inline struct rpir_output *
to_rpir_output ( struct weston_output * output )
{
@ -356,9 +371,8 @@ rpir_surface_create(struct rpi_renderer *renderer)
if ( ! surface )
return NULL ;
wl_list_init ( & surface - > link ) ;
surface - > visible_views = 0 ;
surface - > single_buffer = renderer - > single_buffer ;
surface - > handle = DISPMANX_NO_HANDLE ;
rpi_resource_init ( & surface - > resources [ 0 ] ) ;
rpi_resource_init ( & surface - > resources [ 1 ] ) ;
surface - > front = & surface - > resources [ 0 ] ;
@ -376,15 +390,18 @@ rpir_surface_create(struct rpi_renderer *renderer)
static void
rpir_surface_destroy ( struct rpir_surface * surface )
{
wl_list_remove ( & surface - > link ) ;
if ( surface - > handle ! = DISPMANX_NO_HANDLE )
if ( surface - > visible_views )
weston_log ( " ERROR rpi: destroying on-screen element \n " ) ;
assert ( wl_list_empty ( & surface - > views ) ) ;
if ( surface - > surface )
surface - > surface - > renderer_state = NULL ;
pixman_region32_fini ( & surface - > prev_damage ) ;
rpi_resource_release ( & surface - > resources [ 0 ] ) ;
rpi_resource_release ( & surface - > resources [ 1 ] ) ;
DBG ( " rpir_surface %p destroyed (%u) \n " , surface , surface - > handle ) ;
DBG ( " rpir_surface %p destroyed (%u) \n " , surface , surface - > visible_views ) ;
if ( surface - > egl_back ! = NULL ) {
weston_buffer_reference ( & surface - > egl_back - > buffer_ref , NULL ) ;
@ -436,6 +453,46 @@ rpir_surface_damage(struct rpir_surface *surface, struct weston_buffer *buffer,
return ret ;
}
static struct rpir_view *
rpir_view_create ( struct rpir_surface * surface )
{
struct rpir_view * view ;
view = calloc ( 1 , sizeof * view ) ;
if ( ! view )
return NULL ;
view - > surface = surface ;
wl_list_insert ( & surface - > views , & view - > surface_link ) ;
wl_list_init ( & view - > link ) ;
view - > handle = DISPMANX_NO_HANDLE ;
return view ;
}
static void
rpir_view_destroy ( struct rpir_view * view )
{
wl_list_remove ( & view - > link ) ;
if ( view - > handle ! = DISPMANX_NO_HANDLE ) {
view - > surface - > visible_views - - ;
weston_log ( " ERROR rpi: destroying on-screen element \n " ) ;
}
if ( view - > view )
view - > view - > renderer_state = NULL ;
wl_list_remove ( & view - > surface_link ) ;
if ( wl_list_empty ( & view - > surface - > views ) & & view - > surface - > surface = = NULL )
rpir_surface_destroy ( view - > surface ) ;
DBG ( " rpir_view %p destroyed (%d) \n " , view , view - > handle ) ;
free ( view ) ;
}
static void
matrix_type_str ( struct weston_matrix * matrix , char * buf , int len )
{
@ -495,13 +552,13 @@ warn_bad_matrix(struct weston_matrix *total, struct weston_matrix *output,
/*#define SURFACE_TRANSFORM */
static int
rpir_surface_compute_rects ( struct rpir_surface * surface ,
rpir_view_compute_rects ( struct rpir_view * view ,
VC_RECT_T * src_rect , VC_RECT_T * dst_rect ,
VC_IMAGE_TRANSFORM_T * flipmask )
{
struct weston_output * output_base = surface - > surface - > output ;
struct weston_output * output_base = view - > view - > surface - > output ;
struct rpir_output * output = to_rpir_output ( output_base ) ;
struct weston_matrix matrix = surface - > surface - > transform . matrix ;
struct weston_matrix matrix = view - > view - > transform . matrix ;
VC_IMAGE_TRANSFORM_T flipt = 0 ;
int src_x , src_y ;
int dst_x , dst_y ;
@ -523,14 +580,15 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
src_x = 0 < < 16 ;
src_y = 0 < < 16 ;
if ( surface - > buffer_type = = BUFFER_TYPE_EGL ) {
struct weston_buffer * buffer = surface - > egl_front - > buffer_ref . buffer ;
if ( view - > surface - > buffer_type = = BUFFER_TYPE_EGL ) {
struct weston_buffer * buffer =
view - > surface - > egl_front - > buffer_ref . buffer ;
src_width = buffer - > width < < 16 ;
src_height = buffer - > height < < 16 ;
} else {
src_width = surface - > front - > width < < 16 ;
src_height = surface - > front - > height < < 16 ;
src_width = view - > surface - > front - > width < < 16 ;
src_height = view - > surface - > front - > height < < 16 ;
}
weston_matrix_multiply ( & matrix , & output - > matrix ) ;
@ -541,7 +599,7 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
if ( matrix . type > = WESTON_MATRIX_TRANSFORM_ROTATE ) {
# endif
warn_bad_matrix ( & matrix , & output - > matrix ,
& surface - > surface - > transform . matrix ) ;
& view - > view - > transform . matrix ) ;
} else {
if ( matrix . type & WESTON_MATRIX_TRANSFORM_ROTATE ) {
if ( fabsf ( matrix . d [ 0 ] ) < 1e-4 f & &
@ -552,13 +610,13 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
/* no transpose */
} else {
warn_bad_matrix ( & matrix , & output - > matrix ,
& surface - > surface - > transform . matrix ) ;
& view - > view - > transform . matrix ) ;
}
}
}
p2 . f [ 0 ] = surface - > surface - > geometry . width ;
p2 . f [ 1 ] = surface - > surface - > geometry . height ;
p2 . f [ 0 ] = view - > view - > geometry . width ;
p2 . f [ 1 ] = view - > view - > geometry . height ;
/* transform top-left and bot-right corner into screen coordinates */
weston_matrix_transform ( & matrix , & p1 ) ;
@ -680,9 +738,9 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
src_width = int_max ( src_width , 0 ) ;
src_height = int_max ( src_height , 0 ) ;
DBG ( " rpir_surface %p %dx%d: p1 %f, %f; p2 %f, %f \n " , surface ,
surface - > surface - > geometry . width ,
surface - > surface - > geometry . height ,
DBG ( " rpir_view %p %dx%d: p1 %f, %f; p2 %f, %f \n " , view ,
view - > view - > geometry . width ,
view - > view - > geometry . height ,
p1 . f [ 0 ] , p1 . f [ 1 ] , p2 . f [ 0 ] , p2 . f [ 1 ] ) ;
DBG ( " src rect %d;%d, %d;%d, %d;%dx%d;%d \n " ,
src_x > > 16 , src_x & 0xffff ,
@ -706,7 +764,7 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
}
/* EGL buffers will be upside-down related to what DispmanX expects */
if ( surface - > buffer_type = = BUFFER_TYPE_EGL )
if ( view - > surface - > buffer_type = = BUFFER_TYPE_EGL )
flipt ^ = TRANSFORM_VFLIP ;
vc_dispmanx_rect_set ( src_rect , src_x , src_y , src_width , src_height ) ;
@ -760,7 +818,7 @@ rpir_surface_get_resource(struct rpir_surface *surface)
}
static int
rpir_surface_dmx_add ( struct rpir_surface * surface , struct rpir_output * output ,
rpir_view_dmx_add ( struct rpir_view * view , struct rpir_output * output ,
DISPMANX_UPDATE_HANDLE_T update , int layer )
{
/* Do not use DISPMANX_FLAGS_ALPHA_PREMULT here.
@ -771,7 +829,7 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
VC_DISPMANX_ALPHA_T alphasetup = {
DISPMANX_FLAGS_ALPHA_FROM_SOURCE |
DISPMANX_FLAGS_ALPHA_MIX ,
float2uint8 ( surface - > surface - > alpha ) , /* opacity 0-255 */
float2uint8 ( view - > view - > alpha ) , /* opacity 0-255 */
0 /* mask resource handle */
} ;
VC_RECT_T dst_rect ;
@ -780,18 +838,17 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
int ret ;
DISPMANX_RESOURCE_HANDLE_T resource_handle ;
resource_handle = rpir_surface_get_resource ( surface ) ;
resource_handle = rpir_surface_get_resource ( view - > surface ) ;
if ( resource_handle = = DISPMANX_NO_HANDLE ) {
weston_log ( " %s: no buffer yet, aborting \n " , __func__ ) ;
return 0 ;
}
ret = rpir_surface_compute_rects ( surface , & src_rect , & dst_rect ,
& flipmask ) ;
ret = rpir_view_compute_rects ( view , & src_rect , & dst_rect , & flipmask ) ;
if ( ret < 0 )
return 0 ;
surface - > handle = vc_dispmanx_element_add (
view - > handle = vc_dispmanx_element_add (
update ,
output - > display ,
layer ,
@ -802,37 +859,42 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
& alphasetup ,
NULL /* clamp */ ,
vc_image2dispmanx_transform ( flipmask ) ) ;
DBG ( " rpir_surface %p add %u, alpha %f resource %d \n " , surface ,
surface - > handle , surface - > surface - > alpha , resource_handle ) ;
DBG ( " rpir_surface %p add %u, alpha %f resource %d \n " , view ,
view - > handle , view - > view - > alpha , resource_handle ) ;
if ( view - > handle = = DISPMANX_NO_HANDLE )
return - 1 ;
view - > surface - > visible_views + + ;
return 1 ;
}
static void
rpir_surface_dmx_swap ( struct rpir_surface * surface ,
rpir_view_dmx_swap ( struct rpir_view * view ,
DISPMANX_UPDATE_HANDLE_T update )
{
VC_RECT_T rect ;
pixman_box32_t * r ;
/* XXX: skip, iff resource was not reallocated, and single-buffering */
vc_dispmanx_element_change_source ( update , surface - > handle ,
surface - > front - > handle ) ;
vc_dispmanx_element_change_source ( update , view - > handle ,
view - > surface - > front - > handle ) ;
/* This is current damage now, after rpir_surface_damage() */
r = pixman_region32_extents ( & surface - > prev_damage ) ;
r = pixman_region32_extents ( & view - > surface - > prev_damage ) ;
vc_dispmanx_rect_set ( & rect , r - > x1 , r - > y1 ,
r - > x2 - r - > x1 , r - > y2 - r - > y1 ) ;
vc_dispmanx_element_modified ( update , surface - > handle , & rect ) ;
DBG ( " rpir_surface %p swap \n " , surface ) ;
vc_dispmanx_element_modified ( update , view - > handle , & rect ) ;
DBG ( " rpir_view %p swap \n " , view ) ;
}
static int
rpir_surface_dmx_move ( struct rpir_surface * surface ,
rpir_view_dmx_move ( struct rpir_view * view ,
DISPMANX_UPDATE_HANDLE_T update , int layer )
{
uint8_t alpha = float2uint8 ( surface - > surface - > alpha ) ;
uint8_t alpha = float2uint8 ( view - > view - > alpha ) ;
VC_RECT_T dst_rect ;
VC_RECT_T src_rect ;
VC_IMAGE_TRANSFORM_T flipmask ;
@ -840,28 +902,27 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
/* XXX: return early, if all attributes stay the same */
if ( surface - > buffer_type = = BUFFER_TYPE_EGL ) {
if ( view - > surface - > buffer_type = = BUFFER_TYPE_EGL ) {
DISPMANX_RESOURCE_HANDLE_T resource_handle ;
resource_handle = rpir_surface_get_resource ( surface ) ;
resource_handle = rpir_surface_get_resource ( view - > surface ) ;
if ( resource_handle = = DISPMANX_NO_HANDLE ) {
weston_log ( " %s: no buffer yet, aborting \n " , __func__ ) ;
return 0 ;
}
vc_dispmanx_element_change_source ( update ,
surface - > handle ,
view - > handle ,
resource_handle ) ;
}
ret = rpir_surface_compute_rects ( surface , & src_rect , & dst_rect ,
& flipmask ) ;
ret = rpir_view_compute_rects ( view , & src_rect , & dst_rect , & flipmask ) ;
if ( ret < 0 )
return 0 ;
ret = vc_dispmanx_element_change_attributes (
update ,
surface - > handle ,
view - > handle ,
ELEMENT_CHANGE_LAYER |
ELEMENT_CHANGE_OPACITY |
ELEMENT_CHANGE_TRANSFORM |
@ -875,7 +936,7 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
/* This really is DISPMANX_TRANSFORM_T, no matter
* what the header says . */
vc_image2dispmanx_transform ( flipmask ) ) ;
DBG ( " rpir_surface %p move \n " , surface ) ;
DBG ( " rpir_view %p move \n " , view ) ;
if ( ret )
return - 1 ;
@ -884,15 +945,16 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
}
static void
rpir_surface_dmx_remove ( struct rpir_surface * surface ,
rpir_view_dmx_remove ( struct rpir_view * view ,
DISPMANX_UPDATE_HANDLE_T update )
{
if ( surface - > handle = = DISPMANX_NO_HANDLE )
if ( view - > handle = = DISPMANX_NO_HANDLE )
return ;
vc_dispmanx_element_remove ( update , surface - > handle ) ;
DBG ( " rpir_surface %p remove %u \n " , surface , surface - > handle ) ;
surface - > handle = DISPMANX_NO_HANDLE ;
vc_dispmanx_element_remove ( update , view - > handle ) ;
DBG ( " rpir_view %p remove %u \n " , view , view - > handle ) ;
view - > handle = DISPMANX_NO_HANDLE ;
view - > surface - > visible_views - - ;
}
static void
@ -900,23 +962,31 @@ rpir_surface_swap_pointers(struct rpir_surface *surface)
{
struct rpi_resource * tmp ;
if ( surface - > buffer_type = = BUFFER_TYPE_EGL ) {
if ( surface - > egl_back ! = NULL ) {
assert ( surface - > egl_old_front = = NULL ) ;
surface - > egl_old_front = surface - > egl_front ;
surface - > egl_front = surface - > egl_back ;
surface - > egl_back = NULL ;
}
} else {
tmp = surface - > front ;
surface - > front = surface - > back ;
surface - > back = tmp ;
surface - > need_swap = 0 ;
}
DBG ( " new back %p, new front %p \n " , surface - > back , surface - > front ) ;
}
static int
is_surface_not_visible ( struct weston_surface * surface )
is_view_not_visible ( struct weston_view * view )
{
/* Return true, if surface is guaranteed to be totally obscured. */
int ret ;
pixman_region32_t unocc ;
pixman_region32_init ( & unocc ) ;
pixman_region32_subtract ( & unocc , & surface - > transform . boundingbox ,
& surface - > clip ) ;
pixman_region32_subtract ( & unocc , & view - > transform . boundingbox ,
& view - > clip ) ;
ret = ! pixman_region32_not_empty ( & unocc ) ;
pixman_region32_fini ( & unocc ) ;
@ -924,81 +994,55 @@ is_surface_not_visible(struct weston_surface *surface)
}
static void
rpir_surface_update ( struct rpir_surface * surface , struct rpir_output * output ,
rpir_view_update ( struct rpir_view * view , struct rpir_output * output ,
DISPMANX_UPDATE_HANDLE_T update , int layer )
{
int need_swap = surface - > need_swap ;
int ret ;
int obscured ;
if ( surface - > buffer_type = = BUFFER_TYPE_EGL ) {
if ( surface - > egl_back ! = NULL ) {
assert ( surface - > egl_old_front = = NULL ) ;
surface - > egl_old_front = surface - > egl_front ;
surface - > egl_front = surface - > egl_back ;
surface - > egl_back = NULL ;
}
if ( surface - > egl_front - > buffer_ref . buffer = = NULL ) {
weston_log ( " warning: client unreffed current front buffer \n " ) ;
wl_list_remove ( & surface - > link ) ;
if ( surface - > handle = = DISPMANX_NO_HANDLE ) {
wl_list_init ( & surface - > link ) ;
} else {
rpir_surface_dmx_remove ( surface , update ) ;
wl_list_insert ( & output - > surface_cleanup_list ,
& surface - > link ) ;
}
goto out ;
}
} else {
if ( need_swap )
rpir_surface_swap_pointers ( surface ) ;
}
obscured = is_surface_not_visible ( surface - > surface ) ;
obscured = is_view_not_visible ( view - > view ) ;
if ( obscured ) {
DBG ( " rpir_surface %p totally obscured. \n " , surface ) ;
DBG ( " rpir_view %p totally obscured. \n " , view ) ;
wl_list_remove ( & surface - > link ) ;
if ( surface - > handle = = DISPMANX_NO_HANDLE ) {
wl_list_init ( & surface - > link ) ;
wl_list_remove ( & view - > link ) ;
if ( view - > handle = = DISPMANX_NO_HANDLE ) {
wl_list_init ( & view - > link ) ;
} else {
rpir_surface_dmx_remove ( surface , update ) ;
wl_list_insert ( & output - > surface _cleanup_list,
& surface - > link ) ;
rpir_view_dmx_remove ( view , update ) ;
wl_list_insert ( & output - > view_cleanup_list ,
& view - > link ) ;
}
goto out ;
}
if ( surface - > handle = = DISPMANX_NO_HANDLE ) {
ret = rpir_surface_dmx_add ( surface , output , update , layer ) ;
if ( view - > handle = = DISPMANX_NO_HANDLE ) {
ret = rpir_view_dmx_add ( view , output , update , layer ) ;
if ( ret = = 0 ) {
wl_list_remove ( & surface - > link ) ;
wl_list_init ( & surface - > link ) ;
wl_list_remove ( & view - > link ) ;
wl_list_init ( & view - > link ) ;
} else if ( ret < 0 ) {
weston_log ( " ERROR rpir_surface _dmx_add() failed. \n " ) ;
weston_log ( " ERROR rpir_view _dmx_add() failed. \n " ) ;
}
} else {
if ( need_swap )
rpir_surface_dmx_swap ( surface , update ) ;
if ( view - > surface - > need_swap )
rpir_view_dmx_swap ( view , update ) ;
ret = rpir_surface_dmx_move ( surface , update , layer ) ;
ret = rpir_view_dmx_move ( view , update , layer ) ;
if ( ret = = 0 ) {
rpir_surface_dmx_remove ( surface , update ) ;
rpir_view_dmx_remove ( view , update ) ;
wl_list_remove ( & surface - > link ) ;
wl_list_insert ( & output - > surface _cleanup_list,
& surface - > link ) ;
wl_list_remove ( & view - > link ) ;
wl_list_insert ( & output - > view _cleanup_list,
& view - > link ) ;
} else if ( ret < 0 ) {
weston_log ( " ERROR rpir_surface _dmx_move() failed. \n " ) ;
weston_log ( " ERROR rpir_view _dmx_move() failed. \n " ) ;
}
}
out :
surface - > layer = layer ;
view - > layer = layer ;
}
static int
@ -1105,15 +1149,15 @@ static void
rpir_output_dmx_remove_all ( struct rpir_output * output ,
DISPMANX_UPDATE_HANDLE_T update )
{
struct rpir_surface * surface ;
struct rpir_view * view ;
while ( ! wl_list_empty ( & output - > surface _list) ) {
surface = container_of ( output - > surface _list. next ,
struct rpir_surface , link ) ;
rpir_surface_dmx_remove ( surface , update ) ;
while ( ! wl_list_empty ( & output - > view _list) ) {
view = container_of ( output - > view _list. next ,
struct rpir_view , link ) ;
rpir_view_dmx_remove ( view , update ) ;
wl_list_remove ( & surface - > link ) ;
wl_list_insert ( & output - > surface_cleanup_list , & surface - > link ) ;
wl_list_remove ( & view - > link ) ;
wl_list_insert ( & output - > view_cleanup_list , & view - > link ) ;
}
}
@ -1186,8 +1230,8 @@ rpi_renderer_repaint_output(struct weston_output *base,
{
struct weston_compositor * compositor = base - > compositor ;
struct rpir_output * output = to_rpir_output ( base ) ;
struct weston_surface * ws ;
struct rpir_surface * surface ;
struct weston_view * wv ;
struct rpir_view * view ;
struct wl_list done_list ;
int layer = 1 ;
@ -1199,27 +1243,59 @@ rpi_renderer_repaint_output(struct weston_output *base,
free ( output - > capture_data ) ;
output - > capture_data = NULL ;
/* Swap resources on surfaces as needed */
wl_list_for_each_reverse ( wv , & compositor - > view_list , link )
wv - > surface - > touched = 0 ;
wl_list_for_each_reverse ( wv , & compositor - > view_list , link ) {
view = to_rpir_view ( wv ) ;
if ( ! wv - > surface - > touched ) {
wv - > surface - > touched = 1 ;
if ( view - > surface - > need_swap )
rpir_surface_swap_pointers ( view - > surface ) ;
}
if ( view - > surface - > egl_front - > buffer_ref . buffer = = NULL ) {
weston_log ( " warning: client unreffed current front buffer \n " ) ;
wl_list_remove ( & view - > link ) ;
if ( view - > handle = = DISPMANX_NO_HANDLE ) {
wl_list_init ( & view - > link ) ;
} else {
rpir_view_dmx_remove ( view , output - > update ) ;
wl_list_insert ( & output - > view_cleanup_list ,
& view - > link ) ;
}
}
}
/* update all renderable surfaces */
wl_list_init ( & done_list ) ;
wl_list_for_each_reverse ( ws , & compositor - > surface_list , link ) {
if ( ws - > plane ! = & compositor - > primary_plane )
wl_list_for_each_reverse ( wv , & compositor - > view _list, link ) {
if ( wv - > plane ! = & compositor - > primary_plane )
continue ;
surface = to_rpir_surface ( ws ) ;
assert ( ! wl_list_empty ( & surface - > link ) | |
surface - > handle = = DISPMANX_NO_HANDLE ) ;
view = to_rpir_view ( wv ) ;
assert ( ! wl_list_empty ( & view - > link ) | |
view - > handle = = DISPMANX_NO_HANDLE ) ;
wl_list_remove ( & surface - > link ) ;
wl_list_insert ( & done_list , & surface - > link ) ;
rpir_surface_update ( surface , output , output - > update , layer + + ) ;
wl_list_remove ( & view - > link ) ;
wl_list_insert ( & done_list , & view - > link ) ;
rpir_view_update ( view , output , output - > update , layer + + ) ;
}
/* Mark all surfaces as swapped */
wl_list_for_each_reverse ( wv , & compositor - > view_list , link )
to_rpir_surface ( wv - > surface ) - > need_swap = 0 ;
/* Remove all surfaces that are still on screen, but were
* not rendered this time .
*/
rpir_output_dmx_remove_all ( output , output - > update ) ;
wl_list_insert_list ( & output - > surface_list , & done_list ) ;
wl_list_insert_list ( & output - > view _list, & done_list ) ;
output - > update = DISPMANX_NO_HANDLE ;
/* The frame_signal is emitted in rpi_renderer_finish_frame(),
@ -1263,7 +1339,7 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
/* XXX: need to check if in middle of update */
rpi_resource_release ( surface - > back ) ;
if ( surface - > handle = = DISPMANX_NO_HANDLE )
if ( ! surface - > visible_views )
/* XXX: cannot do this, if middle of an update */
rpi_resource_release ( surface - > front ) ;
@ -1336,6 +1412,23 @@ rpi_renderer_create_surface(struct weston_surface *base)
return 0 ;
}
static int
rpi_renderer_create_view ( struct weston_view * base )
{
struct rpir_surface * surface = to_rpir_surface ( base - > surface ) ;
struct rpir_view * view ;
assert ( base - > renderer_state = = NULL ) ;
view = rpir_view_create ( surface ) ;
if ( ! view )
return - 1 ;
view - > view = base ;
base - > renderer_state = view ;
return 0 ;
}
static void
rpi_renderer_surface_set_color ( struct weston_surface * base ,
float red , float green , float blue , float alpha )
@ -1390,13 +1483,27 @@ rpi_renderer_destroy_surface(struct weston_surface *base)
surface - > surface = NULL ;
base - > renderer_state = NULL ;
/* If guaranteed to not be on screen, just detroy it. */
if ( wl_list_empty ( & surface - > link ) )
if ( wl_list_empty ( & surface - > views ) )
rpir_surface_destroy ( surface ) ;
}
/* Otherwise, the surface is either on screen and needs
static void
rpi_renderer_destroy_view ( struct weston_view * base )
{
struct rpir_view * view = to_rpir_view ( base ) ;
assert ( view ) ;
assert ( view - > view = = base ) ;
if ( ! view )
return ;
/* If guaranteed to not be on screen, just detroy it. */
if ( wl_list_empty ( & view - > link ) )
rpir_view_destroy ( view ) ;
/* Otherwise, the view is either on screen and needs
* to be removed by a repaint update , or it is in the
* surface_cleanup_list , and will be destroyed by
* view _cleanup_list, and will be destroyed by
* rpi_renderer_finish_frame ( ) .
*/
}
@ -1440,8 +1547,10 @@ rpi_renderer_create(struct weston_compositor *compositor,
renderer - > base . flush_damage = rpi_renderer_flush_damage ;
renderer - > base . attach = rpi_renderer_attach ;
renderer - > base . create_surface = rpi_renderer_create_surface ;
renderer - > base . create_view = rpi_renderer_create_view ;
renderer - > base . surface_set_color = rpi_renderer_surface_set_color ;
renderer - > base . destroy_surface = rpi_renderer_destroy_surface ;
renderer - > base . destroy_view = rpi_renderer_destroy_view ;
renderer - > base . destroy = rpi_renderer_destroy ;
# ifdef ENABLE_EGL
@ -1504,8 +1613,8 @@ rpi_renderer_output_create(struct weston_output *base,
output - > display = display ;
output - > update = DISPMANX_NO_HANDLE ;
wl_list_init ( & output - > surface _list) ;
wl_list_init ( & output - > surface _cleanup_list) ;
wl_list_init ( & output - > view _list) ;
wl_list_init ( & output - > view _cleanup_list) ;
rpi_resource_init ( & output - > capture_buffer ) ;
base - > renderer_state = output ;
@ -1516,7 +1625,7 @@ WL_EXPORT void
rpi_renderer_output_destroy ( struct weston_output * base )
{
struct rpir_output * output = to_rpir_output ( base ) ;
struct rpir_surface * surface ;
struct rpir_view * view ;
DISPMANX_UPDATE_HANDLE_T update ;
rpi_resource_release ( & output - > capture_buffer ) ;
@ -1527,12 +1636,10 @@ rpi_renderer_output_destroy(struct weston_output *base)
rpir_output_dmx_remove_all ( output , update ) ;
vc_dispmanx_update_submit_sync ( update ) ;
while ( ! wl_list_empty ( & output - > surface_cleanup_list ) ) {
surface = container_of ( output - > surface_cleanup_list . next ,
struct rpir_surface , link ) ;
if ( surface - > surface )
surface - > surface - > renderer_state = NULL ;
rpir_surface_destroy ( surface ) ;
while ( ! wl_list_empty ( & output - > view_cleanup_list ) ) {
view = container_of ( output - > view_cleanup_list . next ,
struct rpir_view , link ) ;
rpir_view_destroy ( view ) ;
}
free ( output ) ;
@ -1553,41 +1660,41 @@ rpi_renderer_finish_frame(struct weston_output *base)
{
struct rpir_output * output = to_rpir_output ( base ) ;
struct weston_compositor * compositor = base - > compositor ;
struct weston_surface * ws ;
struct rpir_surface * surface ;
struct weston_view * wv ;
struct rpir_view * view ;
while ( ! wl_list_empty ( & output - > surface _cleanup_list) ) {
surface = container_of ( output - > surface _cleanup_list. next ,
struct rpir_surface , link ) ;
while ( ! wl_list_empty ( & output - > view _cleanup_list) ) {
view = container_of ( output - > view _cleanup_list. next ,
struct rpir_view , link ) ;
if ( surface - > surface ) {
/* The weston_surface still exists, but is
if ( view - > view ) {
/* The weston_view still exists, but is
* temporarily not visible , and hence its Element
* was removed . The current front buffer contents
* must be preserved .
*/
if ( ! surface - > single_buffer )
rpi_resource_release ( surface - > back ) ;
if ( ! view - > surface - > visible_views )
rpi_resource_release ( view - > surface - > back ) ;
wl_list_remove ( & surface - > link ) ;
wl_list_init ( & surface - > link ) ;
wl_list_remove ( & view - > link ) ;
wl_list_init ( & view - > link ) ;
} else {
rpir_surface_destroy ( surface ) ;
rpir_view_destroy ( view ) ;
}
}
wl_list_for_each ( ws , & compositor - > surface _list, link ) {
surface = to_rpir_surface ( ws ) ;
wl_list_for_each ( wv , & compositor - > view _list, link ) {
view = to_rpir_view ( wv ) ;
if ( surface - > buffer_type ! = BUFFER_TYPE_EGL )
if ( view - > surface - > buffer_type ! = BUFFER_TYPE_EGL )
continue ;
if ( surface - > egl_old_front = = NULL )
if ( view - > surface - > egl_old_front = = NULL )
continue ;
weston_buffer_reference ( & surface - > egl_old_front - > buffer_ref , NULL ) ;
free ( surface - > egl_old_front ) ;
surface - > egl_old_front = NULL ;
weston_buffer_reference ( & view - > surface - > egl_old_front - > buffer_ref , NULL ) ;
free ( view - > surface - > egl_old_front ) ;
view - > surface - > egl_old_front = NULL ;
}
wl_signal_emit ( & base - > frame_signal , base ) ;