Evas GL: Add new API to get current Evas GL
authorJean-Philippe Andre <jp.andre@samsung.com>
Fri, 2 Oct 2015 06:15:40 +0000 (15:15 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Fri, 2 Oct 2015 07:56:38 +0000 (16:56 +0900)
While this seems to go against the rest of the API (because we
always pass in the Evas GL object), there is no way right now
fully restore a context if there are multiple Evas GL objects.

For instance, an app can use Evas GL from an Elm GLView, and also
use Cairo with another Evas GL at the same time. In that case Cairo
needs to restore the previous Evas GL but the library had no way
of getting the current Evas GL. This is the equivalent of
eglGetCurrentDisplay().

@feature

src/lib/evas/Evas_GL.h
src/lib/evas/canvas/evas_gl.c

index a032eaf..0a4aa70 100644 (file)
@@ -847,7 +847,7 @@ EAPI Evas_GL_Context         *evas_gl_current_context_get (Evas_GL *evas_gl) EIN
 /**
  * @brief Returns the Evas GL surface object in use or set by @ref evas_gl_make_current
  *
- * @param evas_gl The given Evas_GL object
+ * @param[in] evas_gl The given Evas_GL object
  *
  * @return The current surface for the calling thread, or @c NULL in case of
  *         failure and when there is no current surface in this thread.
@@ -862,6 +862,23 @@ EAPI Evas_GL_Context         *evas_gl_current_context_get (Evas_GL *evas_gl) EIN
  */
 EAPI Evas_GL_Surface         *evas_gl_current_surface_get (Evas_GL *evas_gl) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
 
+/**
+ * @brief Get current Evas GL
+ *
+ * @param[out] context  Optional return value for the current context
+ * @param[out] surface  Optional return value for the current surface
+ *
+ * @return The current Evas GL, ie. the last Evas GL passed to evas_gl_make_current
+ *
+ * @see evas_gl_make_current
+ *
+ * @note This can be used to restore a previous context, for instance if you
+ *       are writing a library that needs to work transparently with Evas GL,
+ *       and may not have control over the other Evas GL objects.
+ *
+ * @since 1.16
+ */
+EAPI Evas_GL                 *evas_gl_current_evas_gl_get (Evas_GL_Context **context, Evas_GL_Surface **surface) EINA_WARN_UNUSED_RESULT;
 
 
 /*-------------------------------------------------------------------------
index 5b539e4..7e9c4e7 100644 (file)
@@ -5,6 +5,9 @@
 
 typedef struct _Evas_GL_TLS_data Evas_GL_TLS_data;
 
+/* since 1.16: store current evas gl - this TLS is never destroyed */
+static Eina_TLS _current_evas_gl_key = 0;
+
 struct _Evas_GL
 {
    DATA32      magic;
@@ -126,6 +129,16 @@ evas_gl_new(Evas *e)
    return NULL;
    MAGIC_CHECK_END();
 
+   if (!_current_evas_gl_key)
+     {
+        if (!eina_tls_new(&_current_evas_gl_key))
+          {
+             ERR("Error creating tls key for current Evas GL");
+             return NULL;
+          }
+        eina_tls_set(_current_evas_gl_key, NULL);
+     }
+
    evas_gl = calloc(1, sizeof(Evas_GL));
    if (!evas_gl) return NULL;
 
@@ -136,6 +149,7 @@ evas_gl_new(Evas *e)
    if (!evas_gl->evas->engine.func->gl_context_create)
      {
         ERR("Evas GL engine not available.");
+        eo_data_unref(e, evas_gl->evas);
         free(evas_gl);
         return NULL;
      }
@@ -144,6 +158,7 @@ evas_gl_new(Evas *e)
    if (eina_tls_new(&(evas_gl->resource_key)) == EINA_FALSE)
      {
         ERR("Error creating tls key");
+        eo_data_unref(e, evas_gl->evas);
         free(evas_gl);
         return NULL;
      }
@@ -167,9 +182,13 @@ evas_gl_free(Evas_GL *evas_gl)
    while (evas_gl->contexts)
      evas_gl_context_destroy(evas_gl, evas_gl->contexts->data);
 
-   // Destroy tls
+   // Destroy private tls
    _evas_gl_internal_tls_destroy(evas_gl);
 
+   // Reset current evas gl tls
+   if (_current_evas_gl_key && (evas_gl == eina_tls_get(_current_evas_gl_key)))
+     eina_tls_set(_current_evas_gl_key, NULL);
+
    eo_data_unref(evas_gl->evas->evas, evas_gl->evas);
    evas_gl->magic = 0;
    LKD(evas_gl->lck);
@@ -452,6 +471,9 @@ evas_gl_make_current(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_GL_Context *c
         return EINA_FALSE;
      }
 
+   if (_current_evas_gl_key)
+     eina_tls_set(_current_evas_gl_key, evas_gl);
+
    return ret;
 }
 
@@ -531,6 +553,26 @@ evas_gl_current_surface_get(Evas_GL *evas_gl)
    return NULL;
 }
 
+EAPI Evas_GL *
+evas_gl_current_evas_gl_get(Evas_GL_Context **context, Evas_GL_Surface **surface)
+{
+   Evas_GL *evasgl = NULL;
+
+   if (_current_evas_gl_key)
+     evasgl = eina_tls_get(_current_evas_gl_key);
+
+   if (!evasgl)
+     {
+        if (context) *context = NULL;
+        if (surface) *surface = NULL;
+        return NULL;
+     }
+
+   if (context) *context = evas_gl_current_context_get(evasgl);
+   if (surface) *surface = evas_gl_current_surface_get(evasgl);
+   return evasgl;
+}
+
 EAPI const char *
 evas_gl_string_query(Evas_GL *evas_gl, int name)
 {