From: Stanislav Vorobiov Date: Wed, 30 Oct 2013 13:24:47 +0000 (+0400) Subject: YaGL: Handle non-shareable OpenGL objects properly X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.1~475^2~50 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7cf9d43380fd2ec089f2879a0ae976cabf0b6ed6;p=sdk%2Femulator%2Fqemu.git YaGL: Handle non-shareable OpenGL objects properly In OpenGL 3.1 core profile framebuffers and vertex arrays are non-shareable between contexts, this means that it's not safe to delete these types of objects like we did before. We now keep context id together with framebuffers and vertex arrays and check it on object deletion, if current context is different from the one in which the object was created then "ensure" context is selected and delete operation is performed there. This makes sure that the object will get deleted in case if OpenGL 2.1 is used and that the delete operation is a no-op in case of OpenGL 3.1 core profile. In case of OpenGL 3.1 the object will eventually be deleted once context is deleted Change-Id: I4929a0590d96ae00e46d04a49b9b387a6673330b --- diff --git a/hw/yagl_apis/egl/yagl_host_egl_calls.c b/hw/yagl_apis/egl/yagl_host_egl_calls.c index 515ddd875b..8484acd2cb 100644 --- a/hw/yagl_apis/egl/yagl_host_egl_calls.c +++ b/hw/yagl_apis/egl/yagl_host_egl_calls.c @@ -40,19 +40,36 @@ struct yagl_egl_interface_impl struct yagl_egl_backend *backend; }; -static void yagl_egl_ensure_current(struct yagl_egl_interface *iface) +static YAGL_DEFINE_TLS(struct yagl_egl_api_ts*, egl_api_ts); + +static uint32_t yagl_egl_get_ctx_id(struct yagl_egl_interface *iface) { - struct yagl_egl_interface_impl *egl_iface = (struct yagl_egl_interface_impl*)iface; - egl_iface->backend->ensure_current(egl_iface->backend); + if (egl_api_ts) { + return egl_api_ts->context ? egl_api_ts->context->res.handle : 0; + } else { + return 0; + } } -static void yagl_egl_unensure_current(struct yagl_egl_interface *iface) +static void yagl_egl_ensure_ctx(struct yagl_egl_interface *iface, uint32_t ctx_id) { struct yagl_egl_interface_impl *egl_iface = (struct yagl_egl_interface_impl*)iface; - egl_iface->backend->unensure_current(egl_iface->backend); + uint32_t current_ctx_id = yagl_egl_get_ctx_id(iface); + + if (!current_ctx_id || (ctx_id && (current_ctx_id != ctx_id))) { + egl_iface->backend->ensure_current(egl_iface->backend); + } } -static YAGL_DEFINE_TLS(struct yagl_egl_api_ts*, egl_api_ts); +static void yagl_egl_unensure_ctx(struct yagl_egl_interface *iface, uint32_t ctx_id) +{ + struct yagl_egl_interface_impl *egl_iface = (struct yagl_egl_interface_impl*)iface; + uint32_t current_ctx_id = yagl_egl_get_ctx_id(iface); + + if (!current_ctx_id || (ctx_id && (current_ctx_id != ctx_id))) { + egl_iface->backend->unensure_current(egl_iface->backend); + } +} static __inline bool yagl_validate_display(yagl_host_handle dpy_, struct yagl_egl_display **dpy, @@ -239,8 +256,9 @@ struct yagl_api_ps *yagl_host_egl_process_init(struct yagl_api *api) egl_iface = g_malloc0(sizeof(*egl_iface)); - egl_iface->base.ensure_ctx = &yagl_egl_ensure_current; - egl_iface->base.unensure_ctx = &yagl_egl_unensure_current; + egl_iface->base.get_ctx_id = &yagl_egl_get_ctx_id; + egl_iface->base.ensure_ctx = &yagl_egl_ensure_ctx; + egl_iface->base.unensure_ctx = &yagl_egl_unensure_ctx; egl_iface->backend = egl_api->backend; /* diff --git a/hw/yagl_apis/gles/yagl_gles_api_ts.c b/hw/yagl_apis/gles/yagl_gles_api_ts.c index dc84bf9d9a..64af4a7b88 100644 --- a/hw/yagl_apis/gles/yagl_gles_api_ts.c +++ b/hw/yagl_apis/gles/yagl_gles_api_ts.c @@ -15,10 +15,10 @@ void yagl_gles_api_ts_init(struct yagl_gles_api_ts *gles_api_ts, void yagl_gles_api_ts_cleanup(struct yagl_gles_api_ts *gles_api_ts) { if (gles_api_ts->num_arrays > 0) { - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_api_ts->driver->DeleteBuffers(gles_api_ts->num_arrays, gles_api_ts->arrays); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); } g_free(gles_api_ts->arrays); diff --git a/hw/yagl_apis/gles/yagl_host_gles_calls.c b/hw/yagl_apis/gles/yagl_host_gles_calls.c index c79e609dce..9c5a9f9634 100644 --- a/hw/yagl_apis/gles/yagl_host_gles_calls.c +++ b/hw/yagl_apis/gles/yagl_host_gles_calls.c @@ -18,6 +18,8 @@ struct yagl_gles_object struct yagl_object base; struct yagl_gles_driver *driver; + + uint32_t ctx_id; }; typedef enum @@ -176,6 +178,7 @@ static bool yagl_gles_get_array_param_count(GLenum pname, int *count) static void yagl_gles_object_add(GLuint local_name, GLuint global_name, + uint32_t ctx_id, void (*destroy_func)(struct yagl_object */*obj*/)) { struct yagl_gles_object *obj; @@ -185,6 +188,7 @@ static void yagl_gles_object_add(GLuint local_name, obj->base.global_name = global_name; obj->base.destroy = destroy_func; obj->driver = gles_api_ts->driver; + obj->ctx_id = ctx_id; yagl_object_map_add(cur_ts->ps->object_map, local_name, @@ -197,9 +201,9 @@ static void yagl_gles_buffer_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_buffer_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_obj->driver->DeleteBuffers(1, &obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); g_free(gles_obj); @@ -212,9 +216,9 @@ static void yagl_gles_texture_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_texture_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_obj->driver->DeleteTextures(1, &obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); g_free(gles_obj); @@ -227,9 +231,9 @@ static void yagl_gles_framebuffer_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_framebuffer_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(gles_obj->ctx_id); gles_obj->driver->DeleteFramebuffers(1, &obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(gles_obj->ctx_id); g_free(gles_obj); @@ -242,9 +246,9 @@ static void yagl_gles_renderbuffer_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_renderbuffer_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_obj->driver->DeleteRenderbuffers(1, &obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); g_free(gles_obj); @@ -257,9 +261,9 @@ static void yagl_gles_program_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_program_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_obj->driver->DeleteProgram(obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); g_free(gles_obj); @@ -272,9 +276,9 @@ static void yagl_gles_shader_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_shader_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_obj->driver->DeleteShader(obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); g_free(gles_obj); @@ -287,9 +291,9 @@ static void yagl_gles_vertex_array_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_gles_vertex_array_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(gles_obj->ctx_id); gles_obj->driver->DeleteVertexArrays(1, &obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(gles_obj->ctx_id); g_free(gles_obj); @@ -453,6 +457,7 @@ void yagl_host_glGenVertexArrays(const GLuint *arrays, int32_t arrays_count) yagl_gles_object_add(arrays[i], global_name, + yagl_get_ctx_id(), &yagl_gles_vertex_array_destroy); } } @@ -618,6 +623,7 @@ void yagl_host_glGenBuffers(const GLuint *buffers, int32_t buffers_count) yagl_gles_object_add(buffers[i], global_name, + 0, &yagl_gles_buffer_destroy); } } @@ -654,12 +660,13 @@ void yagl_host_glGenTextures(const GLuint *textures, int32_t textures_count) * might be called without an active context, but * which needs to create a texture. */ - yagl_ensure_ctx(); + yagl_ensure_ctx(0); gles_api_ts->driver->GenTextures(1, &global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); yagl_gles_object_add(textures[i], global_name, + 0, &yagl_gles_texture_destroy); } } @@ -940,6 +947,7 @@ void yagl_host_glGenFramebuffers(const GLuint *framebuffers, int32_t framebuffer yagl_gles_object_add(framebuffers[i], global_name, + yagl_get_ctx_id(), &yagl_gles_framebuffer_destroy); } } @@ -985,6 +993,7 @@ void yagl_host_glGenRenderbuffers(const GLuint *renderbuffers, int32_t renderbuf yagl_gles_object_add(renderbuffers[i], global_name, + 0, &yagl_gles_renderbuffer_destroy); } } @@ -1025,6 +1034,7 @@ void yagl_host_glCreateProgram(GLuint program) yagl_gles_object_add(program, global_name, + 0, &yagl_gles_program_destroy); } @@ -1035,6 +1045,7 @@ void yagl_host_glCreateShader(GLuint shader, yagl_gles_object_add(shader, global_name, + 0, &yagl_gles_shader_destroy); } diff --git a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen.c b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen.c index 40d0366ac8..0cf16a7e0f 100644 --- a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen.c +++ b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen.c @@ -148,10 +148,6 @@ static void yagl_egl_offscreen_ensure_current(struct yagl_egl_backend *backend) { struct yagl_egl_offscreen *egl_offscreen = (struct yagl_egl_offscreen*)backend; - if (egl_offscreen_ts && egl_offscreen_ts->dpy) { - return; - } - egl_offscreen->egl_driver->make_current(egl_offscreen->egl_driver, egl_offscreen->ensure_dpy, egl_offscreen->ensure_sfc, @@ -164,14 +160,18 @@ static void yagl_egl_offscreen_unensure_current(struct yagl_egl_backend *backend struct yagl_egl_offscreen *egl_offscreen = (struct yagl_egl_offscreen*)backend; if (egl_offscreen_ts && egl_offscreen_ts->dpy) { - return; + egl_offscreen->egl_driver->make_current(egl_offscreen->egl_driver, + egl_offscreen_ts->dpy->native_dpy, + egl_offscreen_ts->sfc_draw, + egl_offscreen_ts->sfc_read, + egl_offscreen_ts->ctx->native_ctx); + } else { + egl_offscreen->egl_driver->make_current(egl_offscreen->egl_driver, + egl_offscreen->ensure_dpy, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); } - - egl_offscreen->egl_driver->make_current(egl_offscreen->egl_driver, - egl_offscreen->ensure_dpy, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT); } static void yagl_egl_offscreen_destroy(struct yagl_egl_backend *backend) diff --git a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_context.c b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_context.c index 880cedbc4f..480871f18d 100644 --- a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_context.c +++ b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_context.c @@ -21,9 +21,9 @@ static void yagl_egl_offscreen_context_destroy(struct yagl_eglb_context *ctx) YAGL_LOG_FUNC_ENTER(yagl_egl_offscreen_context_destroy, NULL); if (egl_offscreen_ctx->rp_pbo) { - yagl_ensure_ctx(); + yagl_ensure_ctx(0); egl_offscreen->gles_driver->DeleteBuffers(1, &egl_offscreen_ctx->rp_pbo); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); } egl_offscreen->egl_driver->context_destroy(egl_offscreen->egl_driver, diff --git a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_display.c b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_display.c index 094a824780..0b0ec35017 100644 --- a/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_display.c +++ b/hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_display.c @@ -24,9 +24,9 @@ static void yagl_egl_offscreen_image_destroy(struct yagl_object *obj) YAGL_LOG_FUNC_ENTER(yagl_egl_offscreen_image_destroy, "%u", obj->global_name); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); image->driver->DeleteTextures(1, &obj->global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); g_free(image); @@ -125,9 +125,9 @@ static struct yagl_object *yagl_egl_offscreen_display_create_image(struct yagl_e image = g_malloc(sizeof(*image)); - yagl_ensure_ctx(); + yagl_ensure_ctx(0); egl_offscreen->gles_driver->GenTextures(1, &image->base.global_name); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); image->base.destroy = &yagl_egl_offscreen_image_destroy; image->driver = egl_offscreen->gles_driver; diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c index 342c96e891..2f93941b14 100644 --- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c +++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c @@ -230,10 +230,6 @@ static void yagl_egl_onscreen_ensure_current(struct yagl_egl_backend *backend) { struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend; - if (egl_onscreen_ts && egl_onscreen_ts->dpy) { - return; - } - egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver, egl_onscreen->ensure_dpy, egl_onscreen->ensure_sfc, @@ -246,14 +242,26 @@ static void yagl_egl_onscreen_unensure_current(struct yagl_egl_backend *backend) struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend; if (egl_onscreen_ts && egl_onscreen_ts->dpy) { - return; + if (egl_onscreen_ts->sfc_draw && egl_onscreen_ts->sfc_read) { + egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver, + egl_onscreen_ts->dpy->native_dpy, + egl_onscreen_ts->sfc_draw->dummy_native_sfc, + egl_onscreen_ts->sfc_read->dummy_native_sfc, + egl_onscreen_ts->ctx->native_ctx); + } else { + egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver, + egl_onscreen_ts->dpy->native_dpy, + egl_onscreen_ts->ctx->null_sfc, + egl_onscreen_ts->ctx->null_sfc, + egl_onscreen_ts->ctx->native_ctx); + } + } else { + egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver, + egl_onscreen->ensure_dpy, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); } - - egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver, - egl_onscreen->ensure_dpy, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT); } static void yagl_egl_onscreen_destroy(struct yagl_egl_backend *backend) diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c index a7ad48d61c..b505e465cd 100644 --- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c +++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c @@ -21,9 +21,9 @@ static void yagl_egl_onscreen_context_destroy(struct yagl_eglb_context *ctx) YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_context_destroy, NULL); if (egl_onscreen_ctx->fb) { - yagl_ensure_ctx(); + yagl_ensure_ctx(egl_onscreen_ctx->fb_ctx_id); egl_onscreen->gles_driver->DeleteFramebuffers(1, &egl_onscreen_ctx->fb); - yagl_unensure_ctx(); + yagl_unensure_ctx(egl_onscreen_ctx->fb_ctx_id); } if (egl_onscreen_ctx->null_sfc != EGL_NO_SURFACE) { @@ -98,6 +98,7 @@ void yagl_egl_onscreen_context_setup(struct yagl_egl_onscreen_context *ctx) } egl_onscreen->gles_driver->GenFramebuffers(1, &ctx->fb); + ctx->fb_ctx_id = yagl_get_ctx_id(); } bool yagl_egl_onscreen_context_setup_surfaceless(struct yagl_egl_onscreen_context *ctx) diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h index 2715909799..2cd89b972a 100644 --- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h +++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h @@ -21,6 +21,7 @@ struct yagl_egl_onscreen_context * Onscreen GLES API redirects framebuffer zero to this framebuffer. */ GLuint fb; + uint32_t fb_ctx_id; /* * Config with which this context was created, used diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c index 1f10101357..6c3c34dccc 100644 --- a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c +++ b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c @@ -40,9 +40,9 @@ static void yagl_egl_onscreen_surface_invalidate(struct yagl_eglb_surface *sfc, if (((osfc->ws_sfc->base.width != ws_sfc->base.width) || (osfc->ws_sfc->base.height != ws_sfc->base.height)) && osfc->rb) { - yagl_ensure_ctx(); + yagl_ensure_ctx(0); egl_onscreen->gles_driver->DeleteRenderbuffers(1, &osfc->rb); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); osfc->rb = 0; } @@ -131,9 +131,9 @@ static void yagl_egl_onscreen_surface_destroy(struct yagl_eglb_surface *sfc) } if (osfc->rb) { - yagl_ensure_ctx(); + yagl_ensure_ctx(0); egl_onscreen->gles_driver->DeleteRenderbuffers(1, &osfc->rb); - yagl_unensure_ctx(); + yagl_unensure_ctx(0); } yagl_eglb_surface_cleanup(sfc); diff --git a/hw/yagl_egl_interface.h b/hw/yagl_egl_interface.h index f4c76656f9..340ab66ea8 100644 --- a/hw/yagl_egl_interface.h +++ b/hw/yagl_egl_interface.h @@ -5,9 +5,11 @@ struct yagl_egl_interface { - void (*ensure_ctx)(struct yagl_egl_interface */*iface*/); + uint32_t (*get_ctx_id)(struct yagl_egl_interface */*iface*/); - void (*unensure_ctx)(struct yagl_egl_interface */*iface*/); + void (*ensure_ctx)(struct yagl_egl_interface */*iface*/, uint32_t /*ctx_id*/); + + void (*unensure_ctx)(struct yagl_egl_interface */*iface*/, uint32_t /*ctx_id*/); }; #endif diff --git a/hw/yagl_gles_driver.c b/hw/yagl_gles_driver.c index 79601bde69..e1d3871d2d 100644 --- a/hw/yagl_gles_driver.c +++ b/hw/yagl_gles_driver.c @@ -14,14 +14,20 @@ void yagl_gles_driver_cleanup(struct yagl_gles_driver *driver) { } -void yagl_ensure_ctx(void) +uint32_t yagl_get_ctx_id(void) { assert(cur_ts); - cur_ts->ps->egl_iface->ensure_ctx(cur_ts->ps->egl_iface); + return cur_ts->ps->egl_iface->get_ctx_id(cur_ts->ps->egl_iface); } -void yagl_unensure_ctx(void) +void yagl_ensure_ctx(uint32_t ctx_id) { assert(cur_ts); - cur_ts->ps->egl_iface->unensure_ctx(cur_ts->ps->egl_iface); + cur_ts->ps->egl_iface->ensure_ctx(cur_ts->ps->egl_iface, ctx_id); +} + +void yagl_unensure_ctx(uint32_t ctx_id) +{ + assert(cur_ts); + cur_ts->ps->egl_iface->unensure_ctx(cur_ts->ps->egl_iface, ctx_id); } diff --git a/hw/yagl_gles_driver.h b/hw/yagl_gles_driver.h index 507c57bbd6..895d81be6f 100644 --- a/hw/yagl_gles_driver.h +++ b/hw/yagl_gles_driver.h @@ -283,8 +283,9 @@ void yagl_gles_driver_cleanup(struct yagl_gles_driver *driver); * @{ */ -void yagl_ensure_ctx(void); -void yagl_unensure_ctx(void); +uint32_t yagl_get_ctx_id(void); +void yagl_ensure_ctx(uint32_t ctx_id); +void yagl_unensure_ctx(uint32_t ctx_id); /* * @}