YaGL: Handle non-shareable OpenGL objects properly 34/13134/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Wed, 30 Oct 2013 13:24:47 +0000 (17:24 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Wed, 30 Oct 2013 13:24:47 +0000 (17:24 +0400)
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

13 files changed:
hw/yagl_apis/egl/yagl_host_egl_calls.c
hw/yagl_apis/gles/yagl_gles_api_ts.c
hw/yagl_apis/gles/yagl_host_gles_calls.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_context.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_display.c
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c
hw/yagl_egl_interface.h
hw/yagl_gles_driver.c
hw/yagl_gles_driver.h

index 515ddd8..8484acd 100644 (file)
@@ -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;
 
     /*
index dc84bf9..64af4a7 100644 (file)
@@ -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);
index c79e609..9c5a9f9 100644 (file)
@@ -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);
 }
 
index 40d0366..0cf16a7 100644 (file)
@@ -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)
index 880cedb..480871f 100644 (file)
@@ -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,
index 094a824..0b0ec35 100644 (file)
@@ -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;
 
index 342c96e..2f93941 100644 (file)
@@ -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)
index a7ad48d..b505e46 100644 (file)
@@ -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)
index 2715909..2cd89b9 100644 (file)
@@ -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
index 1f10101..6c3c34d 100644 (file)
@@ -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);
index f4c7665..340ab66 100644 (file)
@@ -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
index 79601bd..e1d3871 100644 (file)
@@ -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);
 }
index 507c57b..895d81b 100644 (file)
@@ -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);
 
 /*
  * @}