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 515ddd875b8d286450a893c98609e2334384d511..8484acd2cbfe334f445f7495e455f1f0a3f62f1e 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 dc84bf9d9acc9541c35113a87391ed0d6f3ad212..64af4a7b88cfb18756a7811cce54be9fb954e439 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 c79e609dce512a89918bc905310fc48135f6b5c0..9c5a9f9634c8f74146e9691c98b7d6a429a5bdf6 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 40d0366ac85e7db4068ab38ab20dc1e6846cb401..0cf16a7e0f7e1c8ff56bf344e139e509dcada16b 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 880cedbc4fbd5e846b76b4500228d70146afd1e2..480871f18d777989e537ee2938c8bf634099c05e 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 094a8247800bd560ade9e7696fd63627ea685748..0b0ec35017b2575aa4f720edad8e3fe8a78b1ada 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 342c96e8916594c083308c9cbaed63a93b4ecf1a..2f93941b149fc48910df9c379922def0813bb453 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 a7ad48d61cfc7f72c229f37641e9a30a6f1567e3..b505e465cdc0cc8c625271a0a04d07b458bd2d10 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 271590979937e957c99ca3f2397e3814a88d6912..2cd89b972ae99e1f4f231aca64d25bde1a99ec9d 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 1f10101357d44f5c794c5aa08063639e6ae6fa6b..6c3c34dccce95f1c1b0763ee3a10a5fb14bb2879 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 f4c76656f9d5f465fe83b5867978e45cb29a5cb8..340ab66ea8c8720090d0b37c20ae4d24e55bf365 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 79601bde698abcdf29b96384dc9e3cd957cc5ecb..e1d3871d2dc7eca9de5f563f3c2dac60981b3faa 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 507c57bbd6fc2c08f71b69cb8562efec34f4ae58..895d81be6f8fbcfcccac75feac4fcbda27edb71e 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);
 
 /*
  * @}