@ -86,6 +86,7 @@ struct vrend_fence {
* valid .
*/
struct vrend_context * ctx ;
uint32_t flags ;
void * fence_cookie ;
union {
@ -739,6 +740,9 @@ struct vrend_context {
struct vrend_shader_cfg shader_cfg ;
unsigned debug_flags ;
vrend_context_fence_retire fence_retire ;
void * fence_retire_data ;
} ;
static struct vrend_resource * vrend_renderer_ctx_res_lookup ( struct vrend_context * ctx , int res_handle ) ;
@ -6420,6 +6424,9 @@ struct vrend_context *vrend_create_context(int id, uint32_t nlen, const char *de
vrender_get_glsl_version ( & grctx - > shader_cfg . glsl_version ) ;
if ( ! grctx - > ctx_id )
grctx - > fence_retire = vrend_clicbs - > ctx0_fence_retire ;
return grctx ;
}
@ -9158,7 +9165,18 @@ void vrend_renderer_blit(struct vrend_context *ctx,
vrend_pause_render_condition ( ctx , false ) ;
}
int vrend_renderer_create_fence ( struct vrend_context * ctx , void * fence_cookie )
void vrend_renderer_set_fence_retire ( struct vrend_context * ctx ,
vrend_context_fence_retire retire ,
void * retire_data )
{
assert ( ctx - > ctx_id ) ;
ctx - > fence_retire = retire ;
ctx - > fence_retire_data = retire_data ;
}
int vrend_renderer_create_fence ( struct vrend_context * ctx ,
uint32_t flags ,
void * fence_cookie )
{
struct vrend_fence * fence ;
@ -9170,6 +9188,7 @@ int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie)
return ENOMEM ;
fence - > ctx = ctx ;
fence - > flags = flags ;
fence - > fence_cookie = fence_cookie ;
# ifdef HAVE_EPOXY_EGL_H
@ -9202,19 +9221,47 @@ int vrend_renderer_create_fence(struct vrend_context *ctx, void *fence_cookie)
static void vrend_renderer_check_queries ( void ) ;
static bool need_fence_retire_signal_locked ( struct vrend_fence * fence )
{
struct vrend_fence * next ;
/* last fence */
if ( fence - > fences . next = = & vrend_state . fence_list )
return true ;
/* next fence belongs to a different context */
next = LIST_ENTRY ( struct vrend_fence , fence - > fences . next , fences ) ;
if ( next - > ctx ! = fence - > ctx )
return true ;
return false ;
}
void vrend_renderer_check_fences ( void )
{
struct list_head retired_fences ;
struct vrend_fence * fence , * stor ;
bool fence_cookie_valid = false ;
void * fence_cookie ;
list_inithead ( & retired_fences ) ;
if ( vrend_state . sync_thread ) {
flush_eventfd ( vrend_state . eventfd ) ;
pipe_mutex_lock ( vrend_state . fence_mutex ) ;
LIST_FOR_EACH_ENTRY_SAFE ( fence , stor , & vrend_state . fence_list , fences ) {
fence_cookie_valid = true ;
fence_cookie = fence - > fence_cookie ;
/* vrend_free_fences_for_context might have marked the fence invalid
* by setting fence - > ctx to NULL
*/
if ( ! fence - > ctx ) {
free_fence_locked ( fence ) ;
continue ;
}
if ( need_fence_retire_signal_locked ( fence ) ) {
list_del ( & fence - > fences ) ;
list_addtail ( & fence - > fences , & retired_fences ) ;
} else {
free_fence_locked ( fence ) ;
}
}
pipe_mutex_unlock ( vrend_state . fence_mutex ) ;
} else {
@ -9222,9 +9269,12 @@ void vrend_renderer_check_fences(void)
LIST_FOR_EACH_ENTRY_SAFE ( fence , stor , & vrend_state . fence_list , fences ) {
if ( do_wait ( fence , /* can_block */ false ) ) {
fence_cookie_valid = true ;
fence_cookie = fence - > fence_cookie ;
if ( need_fence_retire_signal_locked ( fence ) ) {
list_del ( & fence - > fences ) ;
list_addtail ( & fence - > fences , & retired_fences ) ;
} else {
free_fence_locked ( fence ) ;
}
} else {
/* don't bother checking any subsequent ones */
break ;
@ -9232,12 +9282,17 @@ void vrend_renderer_check_fences(void)
}
}
if ( ! fence_cookie_valid )
if ( LIST_IS_EMPTY ( & retired_fences ) )
return ;
vrend_renderer_check_queries ( ) ;
vrend_clicbs - > write_fence ( ( uint32_t ) ( uintptr_t ) fence_cookie ) ;
LIST_FOR_EACH_ENTRY_SAFE ( fence , stor , & retired_fences , fences ) {
struct vrend_context * ctx = fence - > ctx ;
ctx - > fence_retire ( fence - > fence_cookie , ctx - > fence_retire_data ) ;
free_fence_locked ( fence ) ;
}
}
static bool vrend_get_one_query_result ( GLuint query_id , bool use_64 , uint64_t * result )
@ -10963,7 +11018,34 @@ int vrend_renderer_resource_unmap(struct pipe_resource *pres)
int vrend_renderer_create_ctx0_fence ( uint32_t fence_id )
{
void * fence_cookie = ( void * ) ( uintptr_t ) fence_id ;
return vrend_renderer_create_fence ( vrend_state . ctx0 , fence_cookie ) ;
return vrend_renderer_create_fence ( vrend_state . ctx0 , 0 , fence_cookie ) ;
}
static bool find_ctx0_fence_locked ( struct list_head * fence_list ,
void * fence_cookie ,
bool * seen_first ,
struct vrend_fence * * fence )
{
struct vrend_fence * iter ;
LIST_FOR_EACH_ENTRY ( iter , fence_list , fences ) {
/* only consider ctx0 fences */
if ( iter - > ctx ! = vrend_state . ctx0 )
continue ;
if ( iter - > fence_cookie = = fence_cookie ) {
* fence = iter ;
return true ;
}
if ( ! * seen_first ) {
if ( fence_cookie < iter - > fence_cookie )
return true ;
* seen_first = true ;
}
}
return false ;
}
int vrend_renderer_export_ctx0_fence ( uint32_t fence_id , int * out_fd ) {
@ -10976,45 +11058,30 @@ int vrend_renderer_export_ctx0_fence(uint32_t fence_id, int* out_fd) {
pipe_mutex_lock ( vrend_state . fence_mutex ) ;
void * fence_cookie = ( void * ) ( uintptr_t ) fence_id ;
bool seen_first = false ;
struct vrend_fence * fence = NULL ;
struct vrend_fence * iter ;
uint32_t min_fence_id = UINT_MAX ;
if ( ! LIST_IS_EMPTY ( & vrend_state . fence_list ) ) {
iter = LIST_ENTRY ( struct vrend_fence , vrend_state . fence_list . next , fences ) ;
min_fence_id = ( uint32_t ) ( uintptr_t ) iter - > fence_cookie ;
} else if ( ! LIST_IS_EMPTY ( & vrend_state . fence_wait_list ) ) {
iter = LIST_ENTRY ( struct vrend_fence , vrend_state . fence_wait_list . next , fences ) ;
min_fence_id = ( uint32_t ) ( uintptr_t ) iter - > fence_cookie ;
}
if ( fence_id < min_fence_id ) {
if ( vrend_state . sync_thread )
pipe_mutex_unlock ( vrend_state . fence_mutex ) ;
return virgl_egl_export_signaled_fence ( egl , out_fd ) ? 0 : - EINVAL ;
}
LIST_FOR_EACH_ENTRY ( iter , & vrend_state . fence_list , fences ) {
if ( iter - > fence_cookie = = fence_cookie ) {
fence = iter ;
break ;
}
}
if ( ! fence ) {
LIST_FOR_EACH_ENTRY ( iter , & vrend_state . fence_wait_list , fences ) {
if ( iter - > fence_cookie = = fence_cookie ) {
fence = iter ;
break ;
}
}
bool found = find_ctx0_fence_locked ( & vrend_state . fence_list ,
fence_cookie ,
& seen_first ,
& fence ) ;
if ( ! found ) {
found = find_ctx0_fence_locked ( & vrend_state . fence_wait_list ,
fence_cookie ,
& seen_first ,
& fence ) ;
/* consider signaled when no active ctx0 fence at all */
if ( ! found & & ! seen_first )
found = true ;
}
if ( vrend_state . sync_thread )
pipe_mutex_unlock ( vrend_state . fence_mutex ) ;
if ( fence & & virgl_egl_export_fence ( egl , fence - > eglsyncobj , out_fd ) ) {
return 0 ;
if ( found ) {
if ( fence )
return virgl_egl_export_fence ( egl , fence - > eglsyncobj , out_fd ) ? 0 : - EINVAL ;
else
return virgl_egl_export_signaled_fence ( egl , out_fd ) ? 0 : - EINVAL ;
}
# endif
return - EINVAL ;