Evas FB: Add support for region push hook.
authorGuilherme Iscaro <iscaro@profusion.mobi>
Mon, 26 Sep 2016 18:43:25 +0000 (15:43 -0300)
committerBruno Dilly <bdilly@profusion.mobi>
Fri, 4 Nov 2016 20:29:42 +0000 (18:29 -0200)
This will be useful to support the Ecore_Evas VNC server
under FB backend.

src/modules/evas/engines/fb/Evas_Engine_FB.h
src/modules/evas/engines/fb/evas_engine.c
src/modules/evas/engines/fb/evas_engine.h
src/modules/evas/engines/fb/evas_outbuf.c

index b548237..12c5067 100644 (file)
@@ -19,6 +19,10 @@ struct _Evas_Engine_Info_FB
 
    /* non-blocking or blocking mode */
    Evas_Engine_Render_Mode render_mode;
+
+   struct {
+      void (*region_push_hook)(Evas *e, int x, int y, int w, int h, const void *pixels);
+   } func;
 };
 #endif
 
index 9457485..3156b95 100644 (file)
@@ -3,8 +3,13 @@
 #include "evas_engine.h"
 #include "Evas_Engine_FB.h"
 
+#include <Ecore.h>
+#include <Eina.h>
+
 int _evas_engine_fb_log_dom = -1;
 
+static Eina_List *_outbufs = NULL;
+
 /* function tables - filled in later (func and parent func) */
 static Evas_Func func, pfunc;
 
@@ -16,17 +21,76 @@ struct _Render_Engine
    Render_Engine_Software_Generic generic;
 };
 
+typedef struct _Region_Push_Hook_Ctx {
+   void *pixels;
+   Outbuf *buf;
+   int x;
+   int y;
+   int w;
+   int h;
+} Region_Push_Hook_Ctx;
+
 /* prototypes we will use here */
-static void *_output_setup(int w, int h, int rot, int vt, int dev, int refresh);
+static void *_output_setup(Evas *eo_e, int w, int h, int rot, int vt, int dev, int refresh,
+                           void (*region_push_hook)(Evas *e, int x, int y, int w, int h,
+                                                    const void *pixels));
 
 static void *eng_info(Evas *eo_e);
 static void eng_info_free(Evas *eo_e, void *info);
 static int eng_setup(Evas *eo_e, void *info);
 static void eng_output_free(void *data);
 
+static void
+_evas_fb_region_push_hook_call(void *data)
+{
+   Region_Push_Hook_Ctx *ctx = data;
+
+
+   if (eina_list_data_find(_outbufs, ctx->buf))
+     {
+        ctx->buf->region_push_hook.cb(ctx->buf->region_push_hook.evas,
+                                      ctx->x, ctx->y, ctx->w, ctx->h,
+                                      ctx->pixels);
+     }
+
+   free(ctx->pixels);
+   free(ctx);
+}
+
+void
+evas_fb_region_push_hook_call(Outbuf *buf, int x, int y, int w, int h,
+                              const void *pixels)
+{
+   Region_Push_Hook_Ctx *ctx;
+   size_t s;
+
+   if (!buf->region_push_hook.cb)
+     return;
+
+   s = w * h * buf->priv.fb.fb->bpp;
+   ctx = malloc(sizeof(Region_Push_Hook_Ctx));
+   EINA_SAFETY_ON_NULL_RETURN(ctx);
+   ctx->pixels = malloc(s);
+   EINA_SAFETY_ON_NULL_GOTO(ctx->pixels, err_pixels);
+   ctx->x = x;
+   ctx->y = y;
+   ctx->w = w;
+   ctx->h = h;
+   ctx->buf = buf;
+   memcpy(ctx->pixels, pixels, s);
+
+   ecore_main_loop_thread_safe_call_async(_evas_fb_region_push_hook_call, ctx);
+   return;
+
+ err_pixels:
+   free(ctx);
+}
+
 /* internal engine routines */
 static void *
-_output_setup(int w, int h, int rot, int vt, int dev, int refresh)
+_output_setup(Evas *eo_e, int w, int h, int rot, int vt, int dev, int refresh,
+              void (*region_push_hook)(Evas *e, int x, int y, int w, int h,
+                                       const void *pixels))
 {
    Render_Engine *re;
    Outbuf *ob;
@@ -43,6 +107,8 @@ _output_setup(int w, int h, int rot, int vt, int dev, int refresh)
    ob = evas_fb_outbuf_fb_setup_fb(w, h, rot, OUTBUF_DEPTH_INHERIT, vt, dev, refresh);
    if (!ob) goto on_error;
 
+   ob->region_push_hook.cb = region_push_hook;
+   ob->region_push_hook.evas = eo_e;
    if (!evas_render_engine_software_generic_init(&re->generic, ob, NULL,
                                                  evas_fb_outbuf_fb_get_rot,
                                                  evas_fb_outbuf_fb_reconfigure,
@@ -61,6 +127,7 @@ _output_setup(int w, int h, int rot, int vt, int dev, int refresh)
 
    /* no backbuf! */
    evas_fb_outbuf_fb_set_have_backbuf(ob, 0);
+   _outbufs = eina_list_append(_outbufs, ob);
    return re;
 
  on_error:
@@ -98,12 +165,12 @@ eng_setup(Evas *eo_e, void *in)
    Evas_Engine_Info_FB *info;
 
    info = (Evas_Engine_Info_FB *)in;
-   re = _output_setup(e->output.w,
+   re = _output_setup(eo_e, e->output.w,
                      e->output.h,
                      info->info.rotation,
                      info->info.virtual_terminal,
                      info->info.device_number,
-                     info->info.refresh);
+                     info->info.refresh, info->func.region_push_hook);
    e->engine.data.output = re;
    if (!e->engine.data.output) return 0;
    e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
@@ -119,6 +186,7 @@ eng_output_free(void *data)
    re = (Render_Engine *)data;
    if (re)
      {
+        _outbufs = eina_list_remove(_outbufs, re->generic.ob);
         evas_render_engine_software_generic_clean(&re->generic);
         free(re);
      }
index 424d47c..44e4991 100644 (file)
@@ -46,6 +46,11 @@ struct _Outbuf
       } mask;
       RGBA_Image  *back_buf;
    } priv;
+
+   struct {
+      void (*cb)(Evas *e, int x, int y, int w, int h, const void *pixels);
+      Evas *evas;
+   } region_push_hook;
 };
 
 /****/
@@ -68,4 +73,6 @@ int          evas_fb_outbuf_fb_get_rot                (Outbuf *buf);
 int          evas_fb_outbuf_fb_get_have_backbuf       (Outbuf *buf);
 void         evas_fb_outbuf_fb_set_have_backbuf       (Outbuf *buf, int have_backbuf);
 
+void evas_fb_region_push_hook_call(Outbuf *buf, int x, int y, int w, int h, const void *pixels);
+
 #endif
index 7727428..46b0441 100644 (file)
@@ -357,6 +357,7 @@ evas_fb_outbuf_fb_push_updated_region(Outbuf *buf, RGBA_Image *update, int x, in
                            h, w,
                            x, y, NULL);
               }
+             evas_fb_region_push_hook_call(buf, x, y, w, h, src_data);
          }
      }
 }