software-tbm: redesign for evas-drm 91/94791/3
authorSangjin Lee <lsj119@samsung.com>
Mon, 31 Oct 2016 01:08:55 +0000 (10:08 +0900)
committerSangjin Lee <lsj119@samsung.com>
Mon, 7 Nov 2016 00:33:35 +0000 (16:33 -0800)
- Add wayland-buffer for native surface
- Use cserve2
- use libtbm directly

Change-Id: I2c480ad255c23e4ae863f283b91288700106fd81

src/Makefile_Ecore_Evas.am
src/Makefile_Evas.am
src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
src/modules/evas/engines/software_tbm/Evas_Engine_Software_Tbm.h
src/modules/evas/engines/software_tbm/evas_engine.c
src/modules/evas/engines/software_tbm/evas_engine.h
src/modules/evas/engines/software_tbm/evas_outbuf.c

index f43b667..37ca261 100755 (executable)
@@ -288,10 +288,13 @@ modules_ecore_evas_engines_drm_module_la_SOURCES = $(DRMSOURCES)
 modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 @ECORE_EVAS_CFLAGS@ \
 @ECORE_DRM_CFLAGS@ \
+@TBM_CFLAGS@ \
 -I$(top_srcdir)/src/modules/evas/engines/drm \
 -I$(top_srcdir)/src/modules/evas/engines/gl_drm \
+-I$(top_srcdir)/src/modules/evas/engines/software_tbm \
 @ecore_evas_engines_gl_drm_cflags@
 modules_ecore_evas_engines_drm_module_la_LIBADD = @USE_ECORE_EVAS_LIBS@ \
+@TBM_LIBS@ \
 @ecore_evas_engines_gl_drm_libs@
 modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = @USE_ECORE_EVAS_INTERNAL_LIBS@
 modules_ecore_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
index 356c765..e4f18c4 100755 (executable)
@@ -1328,11 +1328,14 @@ modules_evas_engines_software_tbm_module_la_SOURCES = $(SOFTWARE_TBM_SOURCES)
 modules_evas_engines_software_tbm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas/include \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
+-I$(top_srcdir)/src/modules/evas/engines/software_generic \
 -I$(top_srcdir)/src/modules/evas/engines/software_tbm \
 @EVAS_CFLAGS@ \
+@TBM_CFLAGS@\
 @evas_engine_software_tbm_cflags@
 modules_evas_engines_software_tbm_module_la_LIBADD = \
 @USE_EVAS_LIBS@ \
+@TBM_LIBS@\
 @evas_engine_software_tbm_libs@
 modules_evas_engines_software_tbm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
 modules_evas_engines_software_tbm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
index dd2fa32..ac20f8b 100755 (executable)
 #include <Ecore_Drm.h>
 #include <Evas_Engine_Drm.h>
 
+#include <Evas_Engine_Software_Tbm.h>
+#include <tbm_bufmgr.h>
+#include <tbm_surface_queue.h>
+
 #ifdef BUILD_ECORE_EVAS_GL_DRM
 # include <Evas_Engine_GL_Drm.h>
 # include <gbm.h>
@@ -180,16 +184,32 @@ EAPI Ecore_Evas *
 ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h)
 {
    Ecore_Evas *ee;
-   Evas_Engine_Info_Drm *einfo;
    Ecore_Evas_Interface_Drm *iface;
    Ecore_Evas_Engine_Drm_Data *edata;
    int method;
+   Eina_Bool use_software_tbm = EINA_FALSE;
+
+   if (getenv("USE_EVAS_SOFTWARE_TBM_ENGINE"))
+     {
+        use_software_tbm = EINA_TRUE;
+     }
 
    /* try to find the evas drm engine */
-   if (!(method = evas_render_method_lookup("drm")))
+   if (use_software_tbm)
      {
-        ERR("Render method lookup failed for Drm");
-        return NULL;
+       if (!(method = evas_render_method_lookup("software_tbm")))
+         {
+            ERR("Render method lookup failed for software_tbm");
+            return NULL;
+         }
+     }
+   else
+     {
+       if (!(method = evas_render_method_lookup("drm")))
+         {
+            ERR("Render method lookup failed for Drm");
+            return NULL;
+         }
      }
 
    /* try to init drm */
@@ -225,8 +245,8 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED,
    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
 
    /* set some engine properties */
-   ee->driver = "drm";
-   if (device) ee->name = strdup(device);
+   if (device) 
+     ee->name = strdup(device);
    else
      ee->name = strdup(ecore_drm_device_name_get(dev));
 
@@ -270,48 +290,78 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED,
      evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
                              _ecore_evas_drm_render_updates, ee);
 
-   if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas)))
+   if (use_software_tbm)
      {
-        Ecore_Drm_Output *output;
-        char *num;
-
-        einfo->info.depth = 32; // FIXME
-        einfo->info.destination_alpha = ee->alpha;
-        einfo->info.rotation = ee->rotation;
-
-        if ((num = getenv("EVAS_DRM_VSYNC")))
+        Evas_Engine_Info_Software_Tbm *einfo;
+        if ((einfo = (Evas_Engine_Info_Software_Tbm *)evas_engine_info_get(ee->evas)))
           {
-             if (!atoi(num))
-               einfo->info.vsync = EINA_FALSE;
-             else
-               einfo->info.vsync = EINA_TRUE;
+             einfo->info.depth = 32; // FIXME
+             einfo->info.destination_alpha = ee->alpha;
+             einfo->info.rotation = ee->rotation;
+             einfo->info.tbm_queue = (void*)tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+
+             if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+               {
+                  ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                  goto eng_err;
+               }
           }
         else
-          einfo->info.vsync = EINA_TRUE;
-
-        einfo->info.use_hw_accel = EINA_FALSE;
-        einfo->info.dev = dev;
-
-        if ((output = ecore_drm_device_output_find(dev, x, y)))
           {
-             einfo->info.conn_id = ecore_drm_output_connector_id_get(output);
-             einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output);
-             einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output);
-          }
-
-        if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
-          {
-             ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+             ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
              goto eng_err;
           }
+
+        ee->driver = "drm_tbm";
+        ee->prop.window = (Ecore_Window)einfo->info.tbm_queue;
      }
    else
      {
-        ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
-        goto eng_err;
-     }
+        Evas_Engine_Info_Drm *einfo;
+        if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas)))
+          {
+             Ecore_Drm_Output *output;
+             char *num;
+
+             einfo->info.depth = 32; // FIXME
+             einfo->info.destination_alpha = ee->alpha;
+             einfo->info.rotation = ee->rotation;
+
+             if ((num = getenv("EVAS_DRM_VSYNC")))
+               {
+                  if (!atoi(num))
+                    einfo->info.vsync = EINA_FALSE;
+                  else
+                    einfo->info.vsync = EINA_TRUE;
+               }
+             else
+               einfo->info.vsync = EINA_TRUE;
 
-   ee->prop.window = einfo->info.buffer_id;
+             einfo->info.use_hw_accel = EINA_FALSE;
+             einfo->info.dev = dev;
+
+             if ((output = ecore_drm_device_output_find(dev, x, y)))
+               {
+                  einfo->info.conn_id = ecore_drm_output_connector_id_get(output);
+                  einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output);
+                  einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output);
+               }
+
+             if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+               {
+                  ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                  goto eng_err;
+               }
+          }
+        else
+          {
+             ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
+             goto eng_err;
+          }
+
+        ee->driver = "drm";
+        ee->prop.window = einfo->info.buffer_id;
+     }
 
    _ecore_evas_register(ee);
 #if 0
index 01fda78..21d2a38 100755 (executable)
@@ -1,5 +1,5 @@
 #ifndef _EVAS_ENGINE_SOFTWARE_TBM_H
-# define _EVAS_ENGINE_SOFTWARE_TBM_H
+#define _EVAS_ENGINE_SOFTWARE_TBM_H
 
 typedef struct _Evas_Engine_Info_Software_Tbm Evas_Engine_Info_Software_Tbm;
 
index cdcf89a..2b02eae 100755 (executable)
@@ -1,11 +1,11 @@
 #include "evas_common_private.h"
 #include "evas_private.h"
 #ifdef EVAS_CSERVE2
-# include "evas_cs2_private.h"
+#include "evas_cs2_private.h"
 #endif
-
 #include "evas_engine.h"
-#include "../software_generic/evas_native_common.h"
+#include "evas_native_common.h"
+#include <tbm_surface.h>
 
 #ifdef HAVE_DLSYM
 # include <dlfcn.h>
@@ -17,7 +17,9 @@ int _evas_engine_software_tbm_log_dom = -1;
 /* evas function tables - filled in later (func and parent func) */
 static Evas_Func func, pfunc;
 
-Evas_Native_Tbm_Surface_Image_Set_Call  glsym_evas_native_tbm_surface_image_set = NULL;
+/* For wl_buffer's native set */
+static void *tbm_server_lib = NULL;
+static tbm_surface_h (*glsym_wayland_tbm_server_get_surface) (struct wayland_tbm_server *tbm_srv, struct wl_resource *wl_buffer) = NULL;
 
 /* engine structure data */
 typedef struct _Render_Engine Render_Engine;
@@ -29,56 +31,40 @@ struct _Render_Engine
 };
 
 /* LOCAL FUNCTIONS */
-Render_Engine *
-_render_engine_swapbuf_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha, void *tbm_queue)
+static Render_Engine *
+_render_engine_ouput_setup(Evas_Engine_Info_Software_Tbm *info, int w, int h)
 {
-   Render_Engine *re;
+   Render_Engine *re = NULL;
    Outbuf *ob;
-   Render_Engine_Merge_Mode merge_mode = MERGE_SMART;
-   const char *s;
 
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* try to allocate space for our render engine structure */
+   if (!(re = calloc(1, sizeof(Render_Engine))))
+     goto on_error;
 
-   /* try to allocate space for new render engine */
-   if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
-
-   ob = _evas_software_tbm_outbuf_setup(w, h, rotation, depth, alpha, tbm_queue);
-   if (!ob) goto err;
+   /* try to create new outbuf */
+   if (!(ob = evas_outbuf_setup(info, w, h)))
+     goto on_error;
 
    if (!evas_render_engine_software_generic_init(&re->generic, ob,
-                                                 _evas_software_tbm_outbuf_swap_mode_get,
-                                                 _evas_software_tbm_outbuf_rotation_get,
-                                                 NULL,
-                                                 NULL,
-                                                 _evas_software_tbm_outbuf_update_region_new,
-                                                 _evas_software_tbm_outbuf_update_region_push,
-                                                 _evas_software_tbm_outbuf_update_region_free,
-                                                 _evas_software_tbm_outbuf_idle_flush,
-                                                 _evas_software_tbm_outbuf_flush,
-                                                 _evas_software_tbm_outbuf_free,
-                                                 w, h))
-     goto err;
-
-   re->outbuf_reconfigure = _evas_software_tbm_outbuf_reconfigure;
-
-   s = getenv("EVAS_SOFTWARE_TBM_PARTIAL_MERGE");
-   if (s)
-     {
-        if ((!strcmp(s, "bounding")) || (!strcmp(s, "b")))
-          merge_mode = MERGE_BOUNDING;
-        else if ((!strcmp(s, "full")) || (!strcmp(s, "f")))
-          merge_mode = MERGE_FULL;
-        else if ((!strcmp(s, "smart")) || (!strcmp(s, "s")))
-          merge_mode = MERGE_SMART;
-     }
-
-   evas_render_engine_software_generic_merge_mode_set(&re->generic, merge_mode);
-
-   /* return allocated render engine */
+                                                 evas_outbuf_swap_mode_get,
+                                                 evas_outbuf_rot_get,
+                                                 evas_outbuf_reconfigure,
+                                                 evas_outbuf_update_region_first_rect,
+                                                 evas_outbuf_update_region_new,
+                                                 evas_outbuf_update_region_push,
+                                                 evas_outbuf_update_region_free,
+                                                 evas_output_idle_flush,
+                                                 evas_outbuf_flush,
+                                                 evas_outbuf_free, 
+                                                 ob->w, ob->h))
+     goto on_error;
+
+   /* return the allocated render_engine structure */
    return re;
 
-err:
-   if (ob) _evas_software_tbm_outbuf_free(ob);
+ on_error:
+   if (re) evas_render_engine_software_generic_clean(&re->generic);
+
    free(re);
    return NULL;
 }
@@ -87,20 +73,32 @@ static void
 _symbols(void)
 {
    static int done = 0;
+   int fail = 0;
+   const char *wayland_tbm_server_lib = "libwayland-tbm-server.so.0";
 
    if (done) return;
 
 #define LINK2GENERIC(sym) \
    glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
 
-   // Get function pointer to native_common that is now provided through the link of SW_Generic.
-   LINK2GENERIC(evas_native_tbm_surface_image_set);
+   tbm_server_lib = dlopen(wayland_tbm_server_lib, RTLD_LOCAL | RTLD_LAZY);
+   if (tbm_server_lib)
+     {
+        LINK2GENERIC(wayland_tbm_server_get_surface);
+        if (fail == 1)
+          {
+             ERR("fail to dlsym about wayland_tbm_server_get_surface symbol");
+             dlclose(tbm_server_lib);
+             tbm_server_lib = NULL;
+             return;
+          }
+     }
+   else
+     return;
 
    done = 1;
 }
 
-
-
 /* ENGINE API FUNCTIONS WE PROVIDE */
 static void *
 eng_info(Evas *eo_evas EINA_UNUSED)
@@ -155,11 +153,7 @@ eng_setup(Evas *eo_evas, void *info)
         /* if we have no engine data, assume we have not initialized yet */
         evas_common_init();
 
-        re = _render_engine_swapbuf_setup(epd->output.w, epd->output.h,
-                                          einfo->info.rotation,
-                                          einfo->info.depth,
-                                          einfo->info.destination_alpha,
-                                          einfo->info.tbm_queue);
+        re = _render_engine_ouput_setup(einfo, epd->output.w, epd->output.h);
 
         if (re)
           re->generic.ob->info = einfo;
@@ -170,17 +164,16 @@ eng_setup(Evas *eo_evas, void *info)
      {
         Outbuf *ob;
 
-        ob = _evas_software_tbm_outbuf_setup(epd->output.w, epd->output.h,
-                                einfo->info.rotation, einfo->info.depth,
-                                einfo->info.destination_alpha,
-                                einfo->info.tbm_queue);
-        if (ob)
+        ob = evas_outbuf_setup(einfo, epd->output.w, epd->output.h);
+        if (!ob)
           {
-             ob->info = einfo;
-             evas_render_engine_software_generic_update(&re->generic, ob,
-                                                        epd->output.w,
-                                                        epd->output.h);
+             ERR("Failed to evas_outbuf_setup");
+             return 0;
           }
+
+        evas_render_engine_software_generic_update(&re->generic, ob,
+                                                   epd->output.w,
+                                                   epd->output.h);
      }
 
    epd->engine.data.output = re;
@@ -214,50 +207,13 @@ eng_output_free(void *data)
         free(re);
      }
 
-   evas_common_shutdown();
-}
-
-static void
-eng_output_resize(void *data, int w, int h)
-{
-   Render_Engine *re;
-   Evas_Engine_Info_Software_Tbm *einfo;
-   int dx = 0, dy = 0;
-   Eina_Bool resize = EINA_FALSE;
-
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
-   if (!(re = (Render_Engine *)data)) return;
-   if (!(einfo = re->generic.ob->info)) return;
-
-   if (einfo->info.edges & 4) // resize from left
+   if (tbm_server_lib)
      {
-        if ((einfo->info.rotation == 90) || (einfo->info.rotation == 270))
-          dx = re->generic.ob->h - h;
-        else
-          dx = re->generic.ob->w - w;
+       dlclose(tbm_server_lib);
+       tbm_server_lib = NULL;
      }
 
-   if (einfo->info.edges & 1) // resize from top
-     {
-        if ((einfo->info.rotation == 90) || (einfo->info.rotation == 270))
-          dy = re->generic.ob->w - w;
-        else
-          dy = re->generic.ob->h - h;
-     }
-
-   if (einfo->info.edges) resize = EINA_TRUE;
-
-   re->outbuf_reconfigure(re->generic.ob, dx, dy, w, h,
-                          einfo->info.rotation, einfo->info.depth,
-                          einfo->info.destination_alpha, resize);
-
-   evas_common_tilebuf_free(re->generic.tb);
-   if ((re->generic.tb = evas_common_tilebuf_new(w, h)))
-     evas_common_tilebuf_set_tile_size(re->generic.tb, TILESIZE, TILESIZE);
-
-   re->generic.w = w;
-   re->generic.h = h;
+   evas_common_shutdown();
 }
 
 static void *
@@ -281,15 +237,19 @@ eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
                 return im;
           }
       }
+   else if (ns->type == EVAS_NATIVE_SURFACE_WL)
+     {
+        if (im->native.data)
+          {
+             Evas_Native_Surface *ens;
 
-   if ((ns->type == EVAS_NATIVE_SURFACE_OPENGL) &&
-       (ns->version == EVAS_NATIVE_SURFACE_VERSION))
-     im2 = evas_cache_image_data(evas_common_image_cache_get(),
-                                 ie->w, ie->h,
-                                 ns->data.x11.visual, 1,
-                                 EVAS_COLORSPACE_ARGB8888);
-   else
-     im2 = evas_cache_image_data(evas_common_image_cache_get(),
+             ens = im->native.data;
+             if (ens->data.wl.legacy_buffer == ns->data.wl.legacy_buffer)
+               return im;
+          }
+     }
+
+   im2 = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
                                  ie->w, ie->h,
                                  NULL, 1,
                                  EVAS_COLORSPACE_ARGB8888);
@@ -305,11 +265,34 @@ eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
      evas_cache2_image_close(ie);
    else
 #endif
-   evas_cache_image_drop(ie);
+     evas_cache_image_drop(ie);
+
    im = im2;
 
    if (ns->type == EVAS_NATIVE_SURFACE_TBM)
-      return glsym_evas_native_tbm_surface_image_set(NULL, im, ns);
+     {
+          return evas_native_tbm_surface_image_set(NULL, im, ns);
+     }
+   else if (ns->type == EVAS_NATIVE_SURFACE_WL)
+     {
+       // TODO  : need the code for all wl_buffer type
+       // For TBM surface
+       if (glsym_wayland_tbm_server_get_surface)
+         {
+            tbm_surface_h _tbm_surface;
+            tbm_surface_info_s info;
+
+            _tbm_surface = glsym_wayland_tbm_server_get_surface(NULL,ns->data.wl.legacy_buffer);
+
+            tbm_surface_get_info(_tbm_surface, &info);
+
+            return evas_native_tbm_surface_image_set(_tbm_surface, im, ns);
+         }
+       else
+         {
+            return NULL;
+         }
+     }
 
    return im;
 }
@@ -354,7 +337,6 @@ module_open(Evas_Module *em)
    ORD(info_free);
    ORD(setup);
    ORD(output_free);
-   ORD(output_resize);
    ORD(image_native_set);
    ORD(image_native_get);
 
index c4d89fb..88c027f 100755 (executable)
@@ -1,6 +1,13 @@
 #ifndef EVAS_ENGINE_H
 # define EVAS_ENGINE_H
 
+# include "evas_common_private.h"
+# include "evas_macros.h"
+# include "evas_private.h"
+# include "Evas.h"
+# include "Evas_Engine_Software_Tbm.h"
+# include "Evas_Engine_Software_Generic.h"
+
 # ifdef LOGFNS
 #  include <stdio.h>
 #  define LOGFN(fl, ln, fn) printf("-EVAS-TBM: %25s: %5i - %s\n", fl, ln, fn);
@@ -35,48 +42,6 @@ extern int _evas_engine_software_tbm_log_dom;
 # endif
 # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_software_tbm_log_dom, __VA_ARGS__)
 
-# include <wayland-client.h>
-# include "../software_generic/Evas_Engine_Software_Generic.h"
-# include "Evas_Engine_Software_Tbm.h"
-
-#define TBM_SURF_PLANE_MAX 4 /**< maximum number of the planes  */
-/* option to map the tbm_surface */
-#define TBM_SURF_OPTION_READ      (1 << 0) /**< access option to read  */
-#define TBM_SURF_OPTION_WRITE     (1 << 1) /**< access option to write */
-
-typedef struct _tbm_surface * tbm_surface_h;
-typedef uint32_t tbm_format;
-
-typedef struct _tbm_surface_plane
-{
-    unsigned char *ptr;   /**< Plane pointer */
-    uint32_t size;        /**< Plane size */
-    uint32_t offset;      /**< Plane offset */
-    uint32_t stride;      /**< Plane stride */
-
-    void *reserved1;      /**< Reserved pointer1 */
-    void *reserved2;      /**< Reserved pointer2 */
-    void *reserved3;      /**< Reserved pointer3 */
-} tbm_surface_plane_s;
-
-typedef struct _tbm_surface_info
-{
-    uint32_t width;      /**< TBM surface width */
-    uint32_t height;     /**< TBM surface height */
-    tbm_format format;   /**< TBM surface format*/
-    uint32_t bpp;        /**< TBM surface bbp */
-    uint32_t size;       /**< TBM surface size */
-
-    uint32_t num_planes;                            /**< The number of planes */
-    tbm_surface_plane_s planes[TBM_SURF_PLANE_MAX]; /**< Array of planes */
-
-    void *reserved4;   /**< Reserved pointer4 */
-    void *reserved5;   /**< Reserved pointer5 */
-    void *reserved6;   /**< Reserved pointer6 */
-} tbm_surface_info_s;
-
-/* returns 0 on success */
-
 struct _Outbuf
 {
    int w, h;
@@ -89,7 +54,7 @@ struct _Outbuf
    void *tbm_queue;
    Eina_Bool ext_tbm_queue;
 
-   tbm_surface_h surface;
+   void* surface;
 
    struct
    {
@@ -105,10 +70,18 @@ struct _Outbuf
 
       /* Eina_Bool redraw : 1; */
       Eina_Bool destination_alpha : 1;
+
+      /*New Struct*/
+      void *tbm_queue;
+      Eina_Bool queue_need_destroy;
+      Eina_Bool queue_reset;
+      unsigned int frame_age;
+      void *ebuf_info;
    } priv;
 };
 
-
+#if 0
+/*OLD*/
 Outbuf *_evas_software_tbm_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, void *tbm_queue);
 void _evas_software_tbm_outbuf_free(Outbuf *ob);
 void _evas_software_tbm_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
@@ -120,7 +93,19 @@ void _evas_software_tbm_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int
 void *_evas_software_tbm_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
 void _evas_software_tbm_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
 void _evas_software_tbm_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
+#endif
 
-
+/*New*/
+Outbuf *evas_outbuf_setup(Evas_Engine_Info_Software_Tbm *info, int w, int h);
+void evas_outbuf_free(Outbuf *ob);
+void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
+Render_Engine_Swap_Mode evas_outbuf_swap_mode_get(Outbuf *ob);
+int evas_outbuf_rot_get(Outbuf *ob);
+Eina_Bool evas_outbuf_update_region_first_rect(Outbuf *ob);
+void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
+void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
+void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
+void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
+void evas_output_idle_flush(Outbuf *ob);
 
 #endif
index 3bd22e8..d806e8e 100644 (file)
-#include "evas_common_private.h"
-#include "evas_private.h"
+#include "evas_engine.h"
 #ifdef EVAS_CSERVE2
-# include "evas_cs2_private.h"
-#endif
-#ifdef HAVE_DLSYM
-# include <dlfcn.h>
+#include "evas_cs2_private.h"
 #endif
-#include "evas_engine.h"
 
-#define RED_MASK 0xff0000
-#define GREEN_MASK 0x00ff00
-#define BLUE_MASK 0x0000ff
+#include <tbm_surface.h>
+#include <tbm_surface_queue.h>
+#include <tbm_surface_internal.h>
+
+static const int key_evas_buffer;
+#define KEY_EVAS_BUFFER ((unsigned long)&key_evas_buffer)
 
-static void *tbm_lib = NULL;
-static int   tbm_ref = 0;
+typedef struct {
+   RGBA_Image *im;
+   unsigned int age;
+   tbm_surface_h tbm_surface;
+}evas_buffer_info;
 
-static int (*sym_tbm_surface_map) (tbm_surface_h surface, int opt, tbm_surface_info_s *info) = NULL;
-static int (*sym_tbm_surface_unmap) (tbm_surface_h surface) = NULL;
-static int (*sym_tbm_surface_queue_can_dequeue) (void *tbm_queue, int value) = NULL;
-static int (*sym_tbm_surface_queue_dequeue) (void *tbm_queue, tbm_surface_h *surface) = NULL;
-static int (*sym_tbm_surface_queue_enqueue) (void *tbm_queue, tbm_surface_h surface) = NULL;
-static int (*sym_tbm_surface_get_width) (tbm_surface_h surface) = NULL;
-static int (*sym_tbm_surface_get_height) (tbm_surface_h surface) = NULL;
+//#define ENG_DEBUG
 
-static Eina_Bool
-tbm_init(void)
+static void
+_tbm_surface_evas_buffer_info_free(void *data)
 {
-   if (tbm_lib)
-     {
-        tbm_ref++;
-        return EINA_TRUE;
-     }
+   evas_buffer_info* ebuf_info = data;
 
-   const char *tbm_libs[] =
-   {
-      "libtbm.so.1",
-      "libtbm.so.0",
-      NULL,
-   };
-   int i, fail;
-#define SYM(lib, xx)                            \
-  do {                                          \
-       sym_ ## xx = dlsym(lib, #xx);            \
-       if (!(sym_ ## xx)) {                     \
-            ERR("%s", dlerror());               \
-            fail = 1;                           \
-         }                                      \
-    } while (0)
-
-   for (i = 0; tbm_libs[i]; i++)
-     {
-        tbm_lib = dlopen(tbm_libs[i], RTLD_LOCAL | RTLD_LAZY);
-        if (tbm_lib)
-          {
-             fail = 0;
-             SYM(tbm_lib, tbm_surface_map);
-             SYM(tbm_lib, tbm_surface_unmap);
-             SYM(tbm_lib, tbm_surface_queue_can_dequeue);
-             SYM(tbm_lib, tbm_surface_queue_dequeue);
-             SYM(tbm_lib, tbm_surface_queue_enqueue);
-             SYM(tbm_lib, tbm_surface_get_width);
-             SYM(tbm_lib, tbm_surface_get_height);
-             if (fail)
-               {
-                  dlclose(tbm_lib);
-                  tbm_lib = NULL;
-               }
-             else break;
-          }
-     }
-   if (!tbm_lib) return EINA_FALSE;
+#ifdef EVAS_CSERVE2
+   if (evas_cserve2_use_get())
+      evas_cache2_image_close(&ebuf_info->im->cache_entry);
+   else
+#endif
+      evas_cache_image_drop(&ebuf_info->im->cache_entry);
 
-   tbm_ref++;
-   return EINA_TRUE;
+   free(data);
 }
 
-static void
-tbm_shutdown(void)
+static evas_buffer_info *
+_tbm_surface_evas_buffer_info_get(tbm_surface_h surface, Eina_Bool *is_first)
 {
-   if (tbm_ref > 0)
+   tbm_surface_info_s tbm_info;
+   evas_buffer_info *ebuf_info = NULL;
+   RGBA_Image *img = NULL;
+
+   if(!tbm_surface_internal_get_user_data(surface, KEY_EVAS_BUFFER, (void**)&ebuf_info))
      {
-        tbm_ref--;
+        tbm_surface_internal_add_user_data(surface, KEY_EVAS_BUFFER,
+                                       _tbm_surface_evas_buffer_info_free);
+        tbm_surface_get_info(surface, &tbm_info);
 
-        if (tbm_ref == 0)
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          {
+             img = (RGBA_Image *)
+               evas_cache2_image_data(evas_common_image_cache2_get(),
+                                      tbm_info.planes[0].stride/4, tbm_info.height,
+                                      (DATA32*)tbm_info.planes[0].ptr,
+                                      1,
+                                      EVAS_COLORSPACE_ARGB8888);
+          }
+        else
+#endif
           {
-             if (tbm_lib)
-               {
-                  dlclose(tbm_lib);
-                  tbm_lib = NULL;
-               }
+             img = (RGBA_Image *)
+               evas_cache_image_data(evas_common_image_cache_get(),
+                                      tbm_info.planes[0].stride/4, tbm_info.height,
+                                      (DATA32*)tbm_info.planes[0].ptr,
+                                      1,
+                                      EVAS_COLORSPACE_ARGB8888);
           }
+
+        if (!img)
+          ERR("fail to evas_cache_image_data()");
+
+        ebuf_info = calloc(1, sizeof(evas_buffer_info));
+        ebuf_info->im = img;
+        ebuf_info->tbm_surface = surface;
+        tbm_surface_internal_set_user_data(surface, KEY_EVAS_BUFFER, ebuf_info);
+
+        if (is_first)
+           *is_first = EINA_TRUE;
      }
+
+   return ebuf_info;
 }
 
+static void
+_tbm_surface_queue_reset_cb(tbm_surface_queue_h surface_queue EINA_UNUSED, void *data)
+{
+   Outbuf *ob = data;
+   ob->priv.queue_reset = EINA_TRUE;
+}
 
 Outbuf *
-_evas_software_tbm_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, void *tbm_queue)
+evas_outbuf_setup(Evas_Engine_Info_Software_Tbm *info, int w, int h)
 {
-   Outbuf *ob = NULL;
-   char *num;
-
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   Outbuf *ob;
 
-   /* try to allocate space for new Outbuf */
+   /* try to allocate space for outbuf */
    if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
 
-   if (!tbm_init())
-     {
-        ERR("Could not initialize TBM!");
-        goto setup_err;
-     }
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng setup %dx%d(%p) => %dx%d(%p)\n",
+      ob->w, ob->h, ob->priv.tbm_queue,
+      w,h,info->info.tbm_queue);
+#endif
 
-   /* set outbuf properties */
+   /* set properties of outbuf */
    ob->w = w;
    ob->h = h;
-   ob->rotation = rot;
-   ob->depth = depth;
-   ob->priv.destination_alpha = alpha;
-   ob->tbm_queue = tbm_queue;
-   tbm_surface_info_s info;
 
-   eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
+   ob->info = info;
+   ob->depth = info->info.depth;
+   ob->rotation = info->info.rotation;
 
-   return ob;
+   if (!info->info.tbm_queue)
+     {
+        ob->priv.tbm_queue = tbm_surface_queue_create(3,
+                                                      ob->w, ob->h,
+                                                      TBM_FORMAT_ARGB8888,
+                                                      TBM_BO_DEFAULT);
+        if (!ob->priv.tbm_queue)
+           ERR("Cannot create tbm_queue! w:%d, h%d", ob->w, ob->h);
+        ob->priv.queue_need_destroy = EINA_TRUE;
+        info->info.tbm_queue = ob->priv.tbm_queue;
+     }
+   else
+     {
+        ob->priv.tbm_queue = info->info.tbm_queue;
+     }
 
-setup_err:
-   free(ob);
-   return NULL;
+   tbm_surface_queue_add_reset_cb(ob->priv.tbm_queue, _tbm_surface_queue_reset_cb, ob);
+
+   return ob;
 }
 
 void
-_evas_software_tbm_outbuf_free(Outbuf *ob)
+evas_outbuf_free(Outbuf *ob)
 {
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
-   while (ob->priv.pending_writes)
-     {
-        RGBA_Image *img;
-        Eina_Rectangle *rect;
-
-        img = ob->priv.pending_writes->data;
-        ob->priv.pending_writes =
-          eina_list_remove_list(ob->priv.pending_writes, ob->priv.pending_writes);
-
-        rect = img->extended_info;
-
-#ifdef EVAS_CSERVE2
-        if (evas_cserve2_use_get())
-          evas_cache2_image_close(&img->cache_entry);
-        else
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng free tbm_queue:%p need_destroy:%d\n",
+            ob->priv.tbm_queue, ob->priv.queue_need_destroy);
 #endif
-          evas_cache_image_drop(&img->cache_entry);
 
-        eina_rectangle_free(rect);
+   /* free allocate space for outbuf */
+   if (ob->priv.tbm_queue && ob->priv.queue_need_destroy)
+     {
+        tbm_surface_queue_destroy(ob->priv.tbm_queue);
+        ob->priv.tbm_queue = NULL;
+        ob->priv.queue_need_destroy = EINA_FALSE;
      }
 
-   _evas_software_tbm_outbuf_flush(ob, NULL, EVAS_RENDER_MODE_UNDEF);
-   _evas_software_tbm_outbuf_idle_flush(ob);
-
-   eina_array_flush(&ob->priv.onebuf_regions);
-
-   tbm_shutdown();
-
    free(ob);
 }
 
 void
-_evas_software_tbm_outbuf_idle_flush(Outbuf *ob)
+evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot EINA_UNUSED, Outbuf_Depth depth EINA_UNUSED)
 {
-   RGBA_Image *img;
-   Eina_Rectangle *rect;
-
-   if (ob->priv.onebuf)
-     {
-        img = ob->priv.onebuf;
-        ob->priv.onebuf = NULL;
-
-        rect = img->extended_info;
-        eina_rectangle_free(rect);
-
-#ifdef EVAS_CSERVE2
-        if (evas_cserve2_use_get())
-          evas_cache2_image_close(&img->cache_entry);
-        else
-#endif
-          evas_cache_image_drop(&img->cache_entry);
-     }
-   else
-     {
-        while (ob->priv.prev_pending_writes)
-          {
-             img = ob->priv.prev_pending_writes->data;
-             ob->priv.prev_pending_writes =
-               eina_list_remove_list(ob->priv.prev_pending_writes,
-                                     ob->priv.prev_pending_writes);
-             rect = img->extended_info;
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               evas_cache2_image_close(&img->cache_entry);
-             else
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng reconfig %dx%d(%p) => %dx%d\n",
+      ob->w, ob->h, ob->priv.tbm_queue,
+      w,h);
 #endif
-               evas_cache_image_drop(&img->cache_entry);
 
-             eina_rectangle_free(rect);
-          }
+   if ((ob->w != w) || (ob->h != h))
+     {
+        ob->w = w;
+        ob->h = h;
+        tbm_surface_queue_reset(ob->priv.tbm_queue, w, h, TBM_FORMAT_ARGB8888);
      }
 }
 
-void
-_evas_software_tbm_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
+Render_Engine_Swap_Mode
+evas_outbuf_swap_mode_get(Outbuf *ob)
 {
-   Eina_Rectangle *result;
-   RGBA_Image *img;
-   unsigned int n = 0, i = 0;
-
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   tbm_surface_h surface = NULL;
+   evas_buffer_info *ebuf_info;
+   Eina_Bool is_first = EINA_FALSE;
+   Render_Engine_Swap_Mode mode = MODE_FULL;
+   tbm_surface_info_s tbm_info;
 
-   if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
+   tbm_surface_queue_dequeue(ob->priv.tbm_queue, &surface);
+   if (!surface)
+      ERR("Fail to dequeue_buffer");
 
-   /* check for pending writes */
-   if (!ob->priv.pending_writes)
-     {
-        Eina_Rectangle *rect;
-        Eina_Array_Iterator it;
-
-        /* get number of buffer regions */
-        n = eina_array_count_get(&ob->priv.onebuf_regions);
-        if (n == 0) return;
-
-        /* allocate rectangles */
-        if (!(result = alloca(n * sizeof(Eina_Rectangle)))) return;
-
-        /* loop the buffer regions and assign to result */
-        EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
-          {
-             result[i] = *rect;
-             eina_rectangle_free(rect);
-          }
+   ebuf_info = _tbm_surface_evas_buffer_info_get(surface, &is_first);
+   if (!ebuf_info)
+      ERR("Fail to get evas_buffer_info");
 
-        sym_tbm_surface_unmap(ob->surface);
+   ob->priv.ebuf_info = ebuf_info;
 
-        /* clean array */
-        eina_array_clean(&ob->priv.onebuf_regions);
-
-        img = ob->priv.onebuf;
-        ob->priv.onebuf = NULL;
-        if (img)
-          {
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               evas_cache2_image_close(&img->cache_entry);
-             else
-#endif
-               evas_cache_image_drop(&img->cache_entry);
-          }
-     }
+   if (!ob->priv.frame_age || is_first == EINA_TRUE)
+      mode = MODE_FULL;
    else
      {
-        /* get number of pending writes */
-        n = eina_list_count(ob->priv.pending_writes);
-        if (n == 0) return;
-
-        /* allocate rectangles */
-        if (!(result = alloca(n * sizeof(Eina_Rectangle)))) return;
-
-        /* loop the pending writes */
-        EINA_LIST_FREE(ob->priv.pending_writes, img)
+        if (ebuf_info->age < ob->priv.frame_age)
           {
-             Eina_Rectangle *rect;
-             int x = 0, y = 0, w = 0, h = 0;
-
-             if (!(rect = img->extended_info)) continue;
-
-             x = rect->x; y = rect->y; w = rect->w; h = rect->h;
-
-             /* based on rotation, set rectangle position */
-             if (ob->rotation == 0)
-               {
-                  result[i].x = x;
-                  result[i].y = y;
-               }
-             else if (ob->rotation == 90)
-               {
-                  result[i].x = y;
-                  result[i].y = (ob->w - x - w);
-               }
-             else if (ob->rotation == 180)
-               {
-                  result[i].x = (ob->w - x - w);
-                  result[i].y = (ob->h - y - h);
-               }
-             else if (ob->rotation == 270)
-               {
-                  result[i].x = (ob->h - y - h);
-                  result[i].y = x;
-               }
-
-             /* based on rotation, set rectangle size */
-             if ((ob->rotation == 0) || (ob->rotation == 180))
-               {
-                  result[i].w = w;
-                  result[i].h = h;
-               }
-             else if ((ob->rotation == 90) || (ob->rotation == 270))
-               {
-                  result[i].w = h;
-                  result[i].h = w;
-               }
-
-             eina_rectangle_free(rect);
-
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               evas_cache2_image_close(&img->cache_entry);
-             else
-#endif
-               evas_cache_image_drop(&img->cache_entry);
-
-             i++;
+             unsigned int diff;
+             diff = ob->priv.frame_age - ebuf_info->age;
+             switch(diff)
+             {
+             case 0:
+               mode = MODE_COPY;
+               break;
+             case 1:
+               mode = MODE_DOUBLE;
+               break;
+             case 2:
+               mode = MODE_TRIPLE;
+               break;
+             case 3:
+               mode = MODE_QUADRUPLE;
+               break;
+             default:
+               mode = MODE_FULL;
+             }
           }
-
-        sym_tbm_surface_unmap(ob->surface);
      }
-   sym_tbm_surface_queue_enqueue(ob->tbm_queue, ob->surface);
-}
 
-Render_Engine_Swap_Mode
-_evas_software_tbm_outbuf_swap_mode_get(Outbuf *ob)
-{
-   /* TODO: implement if we need buffer age */
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &tbm_info);
+   tbm_surface_internal_ref(surface);
 
-   return MODE_FULL;
-}
-
-int
-_evas_software_tbm_outbuf_rotation_get(Outbuf *ob)
-{
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng swap_mod(%d) frm_age:%d buf_age:%d tbm_surf:%p\n",
+      mode,
+      ob->priv.frame_age, ebuf_info->age,
+      surface);
+#endif
 
-   return ob->rotation;
+   return MODE_FULL;
 }
 
-void
-_evas_software_tbm_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize)
+Eina_Bool
+evas_outbuf_update_region_first_rect(Outbuf *ob)
 {
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
-   if ((depth == OUTBUF_DEPTH_NONE) ||
-       (depth == OUTBUF_DEPTH_INHERIT))
-     depth = ob->depth;
+   Eina_Bool reset = ob->priv.queue_reset;
 
-   if ((ob->w == w) && (ob->h == h) &&
-       (ob->rotation == rot) && (ob->depth == depth) &&
-       (ob->priv.destination_alpha == alpha))
-     return;
+   ob->priv.queue_reset = EINA_FALSE;
 
-   ob->w = w;
-   ob->h = h;
-   ob->rotation = rot;
-   ob->depth = depth;
-   ob->priv.destination_alpha = alpha;
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng first_rect(%d)\n", reset);
+#endif
 
-   _evas_software_tbm_outbuf_idle_flush(ob);
+   return reset;
 }
 
 void *
-_evas_software_tbm_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
+evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
 {
-   RGBA_Image *img;
-   Eina_Rectangle *rect;
-   tbm_surface_info_s info;
+   evas_buffer_info *ebuf_info;
 
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   if ((w <= 0) || (h <= 0)) return NULL;
 
    RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
-   if ((w <= 0) || (h <= 0)) return NULL;
 
-   if (ob->rotation == 0)
+   ebuf_info = ob->priv.ebuf_info;
+   if (!ebuf_info)
      {
-        if (!(img = ob->priv.onebuf))
-          {
-             int bw = 0, bh = 0;
-             void *data = NULL;
-
-             if (sym_tbm_surface_queue_can_dequeue(ob->tbm_queue, 1))
-                {
-                   sym_tbm_surface_queue_dequeue(ob->tbm_queue, &ob->surface);
-                   sym_tbm_surface_map(ob->surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
-                   data = info.planes[0].ptr;
-                   if (!data)
-                      {
-                         ERR("Could not get surface data");
-                         return NULL;
-                      }
-                   bw = info.planes[0].stride / 4;
-                   bh = sym_tbm_surface_get_height(ob->surface);
-                }
-             else {
-                   ERR("sym_tbm_surface_queue_can_dequeue fail");
-                   return NULL;
-             }
-
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               {
-                  img = (RGBA_Image *)
-                    evas_cache2_image_data(evas_common_image_cache2_get(),
-                                           bw, bh, data,
-                                           ob->priv.destination_alpha,
-                                           EVAS_COLORSPACE_ARGB8888);
-               }
-             else
-#endif
-               {
-                  img = (RGBA_Image *)
-                    evas_cache_image_data(evas_common_image_cache_get(),
-                                          bw, bh, data,
-                                          ob->priv.destination_alpha,
-                                          EVAS_COLORSPACE_ARGB8888);
-
-               }
-
-             ob->priv.onebuf = img;
-             if (!img) return NULL;
-          }
+        ERR("evas_outbuf_update_region_new ebuf_info is NULL");
+        return NULL;
+     }
 
-        if (!(rect = eina_rectangle_new(x, y, w, h)))
-          return NULL;
+   if (cx) *cx = x;
+   if (cy) *cy = y;
+   if (cw) *cw = w;
+   if (ch) *ch = h;
 
-        if (!eina_array_push(&ob->priv.onebuf_regions, rect))
-          {
-#ifdef EVAS_CSERVE2
-             if (evas_cserve2_use_get())
-               evas_cache2_image_close(&img->cache_entry);
-             else
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng region_new %dx%d+%d+%d cx:%dx%d+%d+%d img:%p\n",
+         x,y,w,h,
+         *cx, *cy, *cw, *ch,
+         ebuf_info->im);
 #endif
-               evas_cache_image_drop(&img->cache_entry);
-
-             eina_rectangle_free(rect);
-             return NULL;
-          }
 
-        if (cx) *cx = x;
-        if (cy) *cy = y;
-        if (cw) *cw = w;
-        if (ch) *ch = h;
-
-        img->extended_info = rect;
-
-        return img;
-     }
-   else
-     {
-        if (!(rect = eina_rectangle_new(x, y, w, h)))
-          return NULL;
+   return (void*)ebuf_info->im;
+}
 
-#ifdef EVAS_CSERVE2
-        if (evas_cserve2_use_get())
-          img = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get());
-        else
+void
+evas_outbuf_update_region_push(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
+{
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng region_push img:%p %dx%d+%d+%d\n",
+         update,
+         x, y, w, h);
 #endif
-          img = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-
-        if (!img)
-          {
-             eina_rectangle_free(rect);
-             return NULL;
-          }
-
-        img->cache_entry.w = w;
-        img->cache_entry.h = h;
-        img->cache_entry.flags.alpha |= ob->priv.destination_alpha ? 1 : 0;
+}
 
-#ifdef EVAS_CSERVE2
-        if (evas_cserve2_use_get())
-          evas_cache2_image_surface_alloc(&img->cache_entry, w, h);
-        else
+void
+evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
+{
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng region_free img:%p\n",
+         update);
 #endif
-          evas_cache_image_surface_alloc(&img->cache_entry, w, h);
-
-        img->extended_info = rect;
-
-        ob->priv.pending_writes =
-          eina_list_append(ob->priv.pending_writes, img);
-
-        if (cx) *cx = 0;
-        if (cy) *cy = 0;
-        if (cw) *cw = w;
-        if (ch) *ch = h;
-        return img;
-     }
-
-   return NULL;
 }
 
 void
-_evas_software_tbm_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
+evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode EINA_UNUSED)
 {
-   Gfx_Func_Convert func = NULL;
-   Eina_Rectangle rect = {0, 0, 0, 0}, pr;
-   DATA32 *src;
-   DATA8 *dst;
-   int depth = 32, bpp = 0, bpl = 0, wid = 0;
-   int ww = 0, hh = 0;
-   int rx = 0, ry = 0;
-   tbm_surface_info_s info;
-
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
-   /* check for valid output buffer */
-   if (!ob) return;
-
-   /* check for pending writes */
-   if (!ob->priv.pending_writes) return;
-
-   if ((ob->rotation == 0) || (ob->rotation == 180))
-     {
-        func =
-          evas_common_convert_func_get(0, w, h, depth,
-                                       RED_MASK, GREEN_MASK, BLUE_MASK,
-                                       PAL_MODE_NONE, ob->rotation);
-     }
-   else if ((ob->rotation == 90) || (ob->rotation == 270))
-     {
-        func =
-          evas_common_convert_func_get(0, h, w, depth,
-                                       RED_MASK, GREEN_MASK, BLUE_MASK,
-                                       PAL_MODE_NONE, ob->rotation);
-     }
-
-   /* make sure we have a valid convert function */
-   if (!func) return;
-
-   /* based on rotation, set rectangle position */
-   if (ob->rotation == 0)
-     {
-        rect.x = x;
-        rect.y = y;
-     }
-   else if (ob->rotation == 90)
-     {
-        rect.x = y;
-        rect.y = (ob->w - x - w);
-     }
-   else if (ob->rotation == 180)
-     {
-        rect.x = (ob->w - x - w);
-        rect.y = (ob->h - y - h);
-     }
-   else if (ob->rotation == 270)
-     {
-        rect.x = (ob->h - y - h);
-        rect.y = x;
-     }
+   evas_buffer_info *ebuf_info = ob->priv.ebuf_info;
 
-   /* based on rotation, set rectangle size */
-   if ((ob->rotation == 0) || (ob->rotation == 180))
-     {
-        rect.w = w;
-        rect.h = h;
-     }
-   else if ((ob->rotation == 90) || (ob->rotation == 270))
-     {
-        rect.w = h;
-        rect.h = w;
-     }
-
-   /* check for valid update image data */
-   if (!(src = update->image.data)) return;
-
-   bpp = depth / 8;
-   if (bpp <= 0) return;
-
-   /* check for valid desination data */
-   if (sym_tbm_surface_queue_can_dequeue(ob->tbm_queue, 1))
-      {
-         sym_tbm_surface_queue_dequeue(ob->tbm_queue, &ob->surface);
-         sym_tbm_surface_map(ob->surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
-         dst = info.planes[0].ptr;
-         if (!dst)
-            {
-               ERR("Could not get surface data");
-               return;
-            }
-      }
-   else {
-         ERR("sym_tbm_surface_queue_can_dequeue fail");
-         return;
-   }
-
-
-   bpl = (ww * sizeof(int));
-
-   if (ob->rotation == 0)
-     {
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
-        dst += (bpl * rect.y) + (rect.x * bpp);
-        w -= rx;
-     }
-   else if (ob->rotation == 180)
-     {
-        pr = rect;
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
-        rx = pr.w - rect.w;
-        ry = pr.h - rect.h;
-        src += (update->cache_entry.w * ry) + rx;
-        w -= rx;
-     }
-   else if (ob->rotation == 90)
-     {
-        pr = rect;
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
-        rx = pr.w - rect.w; ry = pr.h - rect.h;
-        src += ry;
-        w -= ry;
-     }
-   else if (ob->rotation == 270)
-     {
-        pr = rect;
-        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
-        rx = pr.w - rect.w; ry = pr.h - rect.h;
-        src += (update->cache_entry.w * rx);
-        w -= ry;
-     }
-
-   if ((rect.w <= 0) || (rect.h <= 0)) return;
-
-   wid = bpl / bpp;
+   ob->priv.frame_age++;
+   ebuf_info->age = ob->priv.frame_age;
+   ob->priv.ebuf_info = NULL;
 
-   dst += (bpl * rect.y) + (rect.x * bpp);
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng flush frm_age:%d buf_age:%d tbm_surf:%p\n",
+         ob->priv.frame_age, ebuf_info->age, ebuf_info->tbm_surface);
+#endif
 
-   func(src, dst, (update->cache_entry.w - w), (wid - rect.w),
-        rect.w, rect.h, x + rx, y + ry, NULL);
+   tbm_surface_unmap(ebuf_info->tbm_surface);
+   tbm_surface_queue_enqueue(ob->priv.tbm_queue, ebuf_info->tbm_surface);
+   tbm_surface_internal_unref(ebuf_info->tbm_surface);
 }
 
 void
-_evas_software_tbm_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
+evas_output_idle_flush(Outbuf *ob EINA_UNUSED)
+{
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng idle_flush\n");
+#endif
+}
+
+int
+evas_outbuf_rot_get(Outbuf *ob)
 {
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+#ifdef ENG_DEBUG
+   fprintf(stderr,"[evas:sw_tbm] eng rot_get: %d\n", ob->rotation);
+#endif
+
+   return ob->rotation;
 }