From aef2ec2e7896691552763687f924927cfe5d73b1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Feb 2015 16:59:49 +1000 Subject: [PATCH] renderer: cleanup dangling resources. if a context goes away we should cleanup any resources left in its resource hash table. --- src/vrend_object.c | 19 ++++++++++++++++++- src/vrend_object.h | 1 + src/vrend_renderer.c | 13 ++++++++++--- src/vrend_renderer.h | 4 ++-- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/vrend_object.c b/src/vrend_object.c index 2369b7f..7cb1d78 100644 --- a/src/vrend_object.c +++ b/src/vrend_object.c @@ -32,11 +32,18 @@ struct vrend_object_types { void (*unref)(void *); } obj_types[VIRGL_MAX_OBJECTS]; +static void (*resource_unref)(void *); + void vrend_object_set_destroy_callback(int type, void (*cb)(void *)) { obj_types[type].unref = cb; } +void vrend_resource_set_destroy_callback(void (*cb)(void *)) +{ + resource_unref = cb; +} + static unsigned hash_func(void *key) { @@ -107,10 +114,20 @@ vrend_object_init_resource_table(void) res_hash = util_hash_table_create(hash_func, compare); } +static enum pipe_error free_res_cb(void *key, void *value, void *data) +{ + struct vrend_object *obj = value; + (*resource_unref)(obj->data); + free(obj); + return PIPE_OK; +} + void vrend_object_fini_resource_table(void) { - if (res_hash) + if (res_hash) { + util_hash_table_foreach(res_hash, free_res_cb, NULL); util_hash_table_destroy(res_hash); + } res_hash = NULL; } diff --git a/src/vrend_object.h b/src/vrend_object.h index 60eba96..e2b5e30 100644 --- a/src/vrend_object.h +++ b/src/vrend_object.h @@ -48,4 +48,5 @@ void vrend_resource_remove(uint32_t handle); void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id); void vrend_object_set_destroy_callback(int type, void (*cb)(void *)); +void vrend_resource_set_destroy_callback(void (*cb)(void *)); #endif diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index bd2ae52..4b239c2 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -59,6 +59,7 @@ static void vrend_finish_context_switch(struct vrend_context *ctx); static void vrend_patch_blend_func(struct vrend_context *ctx); static void vrend_update_frontface_state(struct vrend_context *ctx); static void vrender_get_glsl_version(int *glsl_version); +static void vrend_destroy_resource_object(void *obj_ptr); extern int vrend_shader_use_explicit; static int have_invert_mesa = 0; static int use_core_profile = 0; @@ -3150,6 +3151,7 @@ void vrend_renderer_init(struct vrend_if_cbs *cbs) } /* callbacks for when we are cleaning up the object table */ + vrend_resource_set_destroy_callback(vrend_destroy_resource_object); vrend_object_set_destroy_callback(VIRGL_OBJECT_QUERY, vrend_destroy_query_object); vrend_object_set_destroy_callback(VIRGL_OBJECT_SURFACE, vrend_destroy_surface_object); vrend_object_set_destroy_callback(VIRGL_OBJECT_VS, vrend_destroy_shader_object); @@ -3452,13 +3454,13 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a ret = vrend_resource_insert(gr, sizeof(*gr), args->handle); if (ret == 0) { - vrend_renderer_resource_destroy(gr); + vrend_renderer_resource_destroy(gr, true); return ENOMEM; } return 0; } -void vrend_renderer_resource_destroy(struct vrend_resource *res) +void vrend_renderer_resource_destroy(struct vrend_resource *res, bool remove) { // if (res->scannedout) TODO // (*vrend_clicbs->scanout_resource_info)(0, res->id, 0, 0, 0, 0, 0); @@ -3481,11 +3483,16 @@ void vrend_renderer_resource_destroy(struct vrend_resource *res) glDeleteTextures(1, &res->id); } - if (res->handle) + if (res->handle && remove) vrend_resource_remove(res->handle); free(res); } +static void vrend_destroy_resource_object(void *obj_ptr) +{ + struct vrend_resource *res = obj_ptr; + vrend_renderer_resource_destroy(res, false); +} void vrend_renderer_resource_unref(uint32_t res_handle) { diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index ce78fdb..80eae2c 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -327,7 +327,7 @@ int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov, void vrend_renderer_resource_detach_iov(int res_handle, struct iovec **iov_p, int *num_iovs_p); -void vrend_renderer_resource_destroy(struct vrend_resource *res); +void vrend_renderer_resource_destroy(struct vrend_resource *res, bool remove); static INLINE void vrend_resource_reference(struct vrend_resource **ptr, struct vrend_resource *tex) @@ -335,7 +335,7 @@ vrend_resource_reference(struct vrend_resource **ptr, struct vrend_resource *tex struct vrend_resource *old_tex = *ptr; if (pipe_reference(&(*ptr)->base.reference, &tex->base.reference)) - vrend_renderer_resource_destroy(old_tex); + vrend_renderer_resource_destroy(old_tex, true); *ptr = tex; }