Evas filters: OpenGL support part 1.
authorJean-Philippe Andre <jp.andre@samsung.com>
Fri, 17 Jan 2014 02:19:02 +0000 (11:19 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Fri, 7 Feb 2014 08:33:17 +0000 (17:33 +0900)
Quick and dirty solution to support the OpenGL engine:
[1] Allocate CPU buffers
[2] Render text and process all effects to these buffers
[3] Push final image as an OpenGL texture.

This patch implements [1].

src/lib/evas/canvas/evas_object_text.c
src/lib/evas/filters/evas_filter.c
src/lib/evas/filters/evas_filter_bump.c
src/lib/evas/filters/evas_filter_private.h
src/modules/evas/engines/gl_common/evas_gl_image.c

index fff6750..4c48b90 100644 (file)
@@ -10,6 +10,10 @@ EAPI Eo_Op EVAS_OBJ_TEXT_BASE_ID = EO_NOOP;
 
 #define MY_CLASS_NAME "Evas_Text"
 
+#ifdef EVAS_CSERVE2
+# include "evas_cs2_private.h"
+#endif
+
 /* save typing */
 #define ENFN obj->layer->evas->engine.func
 #define ENDT obj->layer->evas->engine.data.output
@@ -2131,6 +2135,13 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
         void *filter_ctx;
         Eina_Bool ok;
 
+        /* NOTE: Font effect rendering is now done ENTIRELY on CPU.
+         * So we rely on cache/cache2 to allocate a real image buffer,
+         * that we can draw to. The OpenGL texture will be created only
+         * after the rendering has been done, as we simply push the output
+         * image to GL.
+         */
+
         W = obj->cur->geometry.w;
         H = obj->cur->geometry.h;
         X = obj->cur->geometry.x;
@@ -2197,16 +2208,13 @@ evas_object_text_render(Evas_Object *eo_obj EINA_UNUSED,
         filter_ctx = ENFN->context_new(ENDT);
         ENFN->context_color_set(ENDT, filter_ctx, 255, 255, 255, 255);
 
-        // Alloc input now
+        // Alloc input now so we can draw text asap
         evas_filter_buffer_data_set(filter, inbuf, NULL, W, H, EINA_TRUE);
         input = evas_filter_buffer_backing_get(filter, inbuf);
 
         // Allocate output so we can keep it around
-        outputimg = ENFN->image_new_from_copied_data
-              (ENDT, W, H, NULL, EINA_TRUE, EVAS_COLORSPACE_ARGB8888);
-        memset(outputimg->image.data, 0, W * H * sizeof(DATA32));
-        evas_filter_buffer_data_set
-              (filter, outbuf, outputimg->image.data, W, H, EINA_FALSE);
+        evas_filter_buffer_data_set(filter, outbuf, NULL, W, H, EINA_FALSE);
+        outputimg = evas_filter_buffer_backing_get(filter, outbuf);
         o->cur.filter.output = outputimg;
 
         // Render text to input buffer
index 8b2481c..05f9db2 100644 (file)
 #include "evas_private.h"
 #include "evas_filter_private.h"
 
+#ifdef EVAS_CSERVE2
+# include "evas_cs2_private.h"
+#endif
+
 static void _buffer_free(Evas_Filter_Buffer *fb);
 static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
 
@@ -43,10 +47,14 @@ evas_filter_context_new(Evas_Public_Data *evas)
 {
    Evas_Filter_Context *ctx;
 
+   EINA_SAFETY_ON_NULL_RETURN_VAL(evas, NULL);
+
    ctx = calloc(1, sizeof(Evas_Filter_Context));
    if (!ctx) return NULL;
 
    ctx->evas = evas;
+   ctx->gl_engine = !!strstr(evas->engine.module->definition->name, "gl");
+
    return ctx;
 }
 
@@ -72,6 +80,31 @@ evas_filter_context_clear(Evas_Filter_Context *ctx)
    // Note: don't reset post_run, as it it set by the client
 }
 
+static void
+_filter_buffer_backing_free(Evas_Filter_Buffer *fb)
+{
+   void *backing;
+   if (!fb) return;
+
+   backing = fb->backing;
+   fb->backing = NULL;
+
+   if (!fb->allocated) return;
+   fb->allocated = EINA_FALSE;
+
+   if (!backing) return;
+
+   if (!fb->ctx->gl_engine)
+     fb->ENFN->image_free(fb->ENDT, backing);
+   else
+     {
+        if (!evas_cserve2_use_get())
+          evas_cache_image_drop(backing);
+        else
+          evas_cache2_image_close(backing);
+     }
+}
+
 /** @hidden private bind proxy to context */
 void
 evas_filter_context_proxy_bind(Evas_Filter_Context *ctx, Evas_Object *eo_proxy,
@@ -209,8 +242,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
           if (source->proxy->surface && !source->proxy->redraw)
             {
                INF("Source already rendered");
-               if (fb->backing && fb->allocated)
-                 fb->ENFN->image_free(fb->ENDT, fb->backing);
+               _filter_buffer_backing_free(fb);
                fb->backing = source->proxy->surface;
                fb->w = source->cur->geometry.w;
                fb->h = source->cur->geometry.h;
@@ -221,8 +253,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj,
             {
                INF("Source needs to be rendered");
                _proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, do_async);
-               if (fb->backing && fb->allocated)
-                 fb->ENFN->image_free(fb->ENDT, fb->backing);
+               _filter_buffer_backing_free(fb);
                fb->backing = source->proxy->surface;
                fb->w = source->cur->geometry.w;
                fb->h = source->cur->geometry.h;
@@ -284,15 +315,42 @@ _rgba_image_alloc(Evas_Filter_Buffer const *fb, void *data)
    size_t sz;
 
    cspace = fb->alpha_only ? EVAS_COLORSPACE_GRY8 : EVAS_COLORSPACE_ARGB8888;
-   if (!data)
+   if (!fb->ctx->gl_engine)
      {
-        image = fb->ENFN->image_new_from_copied_data
-              (fb->ENDT, fb->w, fb->h, NULL, EINA_TRUE, cspace);
+        if (!data)
+          {
+             image = fb->ENFN->image_new_from_copied_data
+                   (fb->ENDT, fb->w, fb->h, NULL, EINA_TRUE, cspace);
+          }
+        else
+          {
+             image = fb->ENFN->image_new_from_data
+                   (fb->ENDT, fb->w, fb->h, data, EINA_TRUE, cspace);
+          }
      }
    else
      {
-        image = fb->ENFN->image_new_from_data
-              (fb->ENDT, fb->w, fb->h, data, EINA_TRUE, cspace);
+        WRN("EXPERIMENTAL OpenGL support. VERY HACKISH!");
+        // FIXME: Directly calling the alloc functions since we want to use sw surfaces.
+
+        if (!data)
+          {
+             if (!evas_cserve2_use_get())
+               image = (RGBA_Image *) evas_cache_image_copied_data
+                     (evas_common_image_cache_get(), fb->w, fb->h, NULL, EINA_TRUE, cspace);
+             else
+                image = (RGBA_Image *) evas_cache2_image_copied_data
+                      (evas_common_image_cache2_get(), fb->w, fb->h, NULL, EINA_TRUE, cspace);
+          }
+        else
+          {
+             if (!evas_cserve2_use_get())
+               image = (RGBA_Image *) evas_cache_image_data
+                     (evas_common_image_cache_get(), fb->w, fb->h, data, EINA_TRUE, cspace);
+             else
+               image = (RGBA_Image *) evas_cache2_image_data
+                     (evas_common_image_cache2_get(), fb->w, fb->h, data, EINA_TRUE, cspace);
+          }
      }
    if (!image) return EINA_FALSE;
 
@@ -323,9 +381,7 @@ evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h)
              //return EINA_FALSE;
              return EINA_TRUE;
           }
-        fb->ENFN->image_free(fb->ENDT, fb->backing);
-        fb->backing = NULL;
-        fb->allocated = EINA_FALSE;
+        _filter_buffer_backing_free(fb);
      }
    if ((fb->w && (fb->w != w)) || (fb->h && (fb->h != h)))
      {
@@ -367,10 +423,7 @@ evas_filter_buffer_data_set(Evas_Filter_Context *ctx, int bufid, void *data,
    fb = _filter_buffer_get(ctx, bufid);
    if (!fb) return EINA_FALSE;
 
-   if (fb->allocated)
-     fb->ENFN->image_free(fb->ENDT, fb->backing);
-   fb->allocated = EINA_FALSE;
-   fb->backing = NULL;
+   _filter_buffer_backing_free(fb);
    if (w <= 0 || h <= 0)
      return EINA_FALSE;
 
@@ -436,9 +489,7 @@ evas_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h,
 static void
 _buffer_free(Evas_Filter_Buffer *fb)
 {
-   if (!fb) return;
-   if (fb->allocated)
-     fb->ENFN->image_free(fb->ENDT, fb->backing);
+   _filter_buffer_backing_free(fb);
    free(fb);
 }
 
@@ -1259,7 +1310,7 @@ _filter_command_run(Evas_Filter_Command *cmd)
    // FIXME: Must call engine function, not CPU directly.
 
    if (strncmp(cmd->ctx->evas->engine.module->definition->name, "software", 8))
-     CRI("Only the software engine is supported for now.");
+     WRN("EXPERIMENTAL OpenGL support! ALL HELL WILL BREAK LOOSE!");
 
    switch (cmd->mode)
      {
index 1d2a042..c03f628 100644 (file)
 #undef ENDT
 #define ENFN cmd->ctx->evas->engine.func
 #define ENDT cmd->ctx->evas->engine.data.output
+
+#ifdef CLAMP
+# undef CLAMP
+#endif
 #define CLAMP(a,b,c) MIN(MAX((b),(a)),(c))
 
 #define DEFAULT_ZANGLE 45.f
index 6c417e3..8f9be80 100644 (file)
@@ -56,6 +56,8 @@ struct _Evas_Filter_Context
       Evas_Filter_Cb cb;
       void *data;
    } post_run;
+
+   Eina_Bool gl_engine : 1;
 };
 
 struct _Evas_Filter_Command
index 169b486..fc70d71 100644 (file)
@@ -328,20 +328,21 @@ evas_gl_common_image_new_from_copied_data(Evas_Engine_GL_Context *gc, unsigned i
    switch (cspace)
      {
       case EVAS_COLORSPACE_ARGB8888:
-       break;
+      case EVAS_COLORSPACE_GRY8:
+        break;
       case EVAS_COLORSPACE_YCBCR422P601_PL:
       case EVAS_COLORSPACE_YCBCR422P709_PL:
         if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE);
         im->tex = NULL;
-       im->cs.no_free = 0;
+        im->cs.no_free = 0;
         if (im->im->cache_entry.h > 0)
           im->cs.data = calloc(1, im->im->cache_entry.h * sizeof(unsigned char *) * 2);
         if ((data) && (im->cs.data))
-         memcpy(im->cs.data, data, im->im->cache_entry.h * sizeof(unsigned char *) * 2);
-       break;
+          memcpy(im->cs.data, data, im->im->cache_entry.h * sizeof(unsigned char *) * 2);
+        break;
       default:
-       abort();
-       break;
+        abort();
+        break;
      }
    return im;
 }