evas: migrate GL_X11 to use more infrastructure of software_generic.
authorCedric BAIL <c.bail@partner.samsung.com>
Fri, 4 Jul 2014 11:51:32 +0000 (13:51 +0200)
committerCedric BAIL <c.bail@partner.samsung.com>
Fri, 4 Jul 2014 13:11:22 +0000 (15:11 +0200)
src/modules/evas/engines/gl_x11/evas_engine.c
src/modules/evas/engines/gl_x11/evas_engine.h
src/modules/evas/engines/gl_x11/evas_x_main.c

index f26903d..5838e1e 100644 (file)
 
 #define EVAS_GL_UPDATE_TILE_SIZE 16
 
-enum {
-   MERGE_BOUNDING,
-   MERGE_FULL
-};
-
-static int partial_render_debug = -1;
-static int partial_rect_union_mode = -1;
-static int swap_buffer_debug_mode = -1;
-static int swap_buffer_debug = 0;
-
-enum {
-   MODE_FULL,
-   MODE_COPY,
-   MODE_DOUBLE,
-   MODE_TRIPLE,
-   MODE_QUADRUPLE
-};
+static int safe_native = -1;
 
 typedef struct _Render_Engine               Render_Engine;
 
 struct _Render_Engine
 {
-   Tilebuf_Rect            *rects;
-   Tilebuf_Rect            *rects_prev[4];
-   Eina_Inlist             *cur_rect;
-   
-   Outbuf      *win;
-   Evas_Engine_Info_GL_X11 *info;
-   Evas                    *evas;
-   Tilebuf                 *tb;
-   int                      end;
-   int                      mode;
-   int                      w, h;
-   int                      vsync;
-   int                      lost_back;
-   int                      prev_age;
-   int                      frame_cnt;
+   Render_Engine_Software_Generic generic;
+
    Eina_Bool                evgl_initted : 1;
 
    struct {
@@ -72,9 +43,14 @@ struct _Render_Engine
    E3D_Renderer            *renderer_3d;
 };
 
+const char *debug_dir;
+int swap_buffer_debug_mode = -1;
+int swap_buffer_debug = 0;
+int partial_render_debug = -1;
+int extn_have_buffer_age = 1;
+
 static int initted = 0;
 static int gl_wins = 0;
-static int extn_have_buffer_age = 1;
 #ifdef GL_GLES
 static int extn_have_y_inverted = 1;
 #endif
@@ -87,8 +63,6 @@ typedef int             (*glsym_func_int) ();
 typedef unsigned int    (*glsym_func_uint) ();
 typedef const char     *(*glsym_func_const_char_ptr) ();
 
-static Eina_Bool eng_preload_make_current(void *data, void *doit);
-
 #ifdef GL_GLES
 
 #ifndef EGL_NATIVE_PIXMAP_KHR
@@ -195,11 +169,11 @@ evgl_eng_display_get(void *data)
      }
 
 #ifdef GL_GLES
-   if (re->win)
-      return (void*)re->win->egl_disp;
+   if (re->generic.ob)
+      return (void*)re->generic.ob->egl_disp;
 #else
-   if (re->info)
-      return (void*)re->info->info.display;
+   if (re->generic.ob->info)
+      return (void*)re->generic.ob->info->info.display;
 #endif
    else
       return NULL;
@@ -218,11 +192,11 @@ evgl_eng_evas_surface_get(void *data)
      }
 
 #ifdef GL_GLES
-   if (re->win)
-      return (void*)re->win->egl_surface[0];
+   if (re->generic.ob)
+      return (void*)re->generic.ob->egl_surface[0];
 #else
-   if (re->win)
-      return (void*)re->win->win;
+   if (re->generic.ob)
+      return (void*)re->generic.ob->win;
 #endif
    else
       return NULL;
@@ -245,7 +219,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
 #ifdef GL_GLES
    EGLContext ctx = (EGLContext)context;
    EGLSurface sfc = (EGLSurface)surface;
-   EGLDisplay dpy = re->win->egl_disp; //eglGetCurrentDisplay();
+   EGLDisplay dpy = re->generic.ob->egl_disp; //eglGetCurrentDisplay();
 
    if ((!context) && (!surface))
      {
@@ -284,7 +258,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
 
    if ((!context) && (!surface))
      {
-        ret = glXMakeCurrent(re->info->info.display, None, NULL);
+        ret = glXMakeCurrent(re->generic.ob->info->info.display, None, NULL);
         if (!ret)
           {
              ERR("glXMakeCurrent() failed!");
@@ -301,7 +275,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
         if (flush) eng_window_use(NULL);
 
         // Do a make current
-        ret = glXMakeCurrent(re->info->info.display, sfc, ctx);
+        ret = glXMakeCurrent(re->generic.ob->info->info.display, sfc, ctx);
 
         if (!ret)
           {
@@ -340,8 +314,8 @@ evgl_eng_native_window_create(void *data)
    attr.do_not_propagate_mask = NoEventMask;
    attr.event_mask = 0; 
 
-   win = XCreateWindow(re->info->info.display,
-                       DefaultRootWindow(re->info->info.display),
+   win = XCreateWindow(re->generic.ob->info->info.display,
+                       DefaultRootWindow(re->generic.ob->info->info.display),
                        0, 0, 2, 2, 0,
                        CopyFromParent, InputOutput, CopyFromParent, 
                        CWBackingStore | CWOverrideRedirect |
@@ -376,7 +350,7 @@ evgl_eng_native_window_destroy(void *data, void *native_window)
         return 0;
      }
 
-   XDestroyWindow(re->info->info.display, (Window)native_window);
+   XDestroyWindow(re->generic.ob->info->info.display, (Window)native_window);
 
    native_window = NULL;
 
@@ -402,8 +376,8 @@ evgl_eng_window_surface_create(void *data, void *native_window)
    EGLSurface surface = EGL_NO_SURFACE;
 
    // Create resource surface for EGL
-   surface = eglCreateWindowSurface(re->win->egl_disp,
-                                    re->win->egl_config,
+   surface = eglCreateWindowSurface(re->generic.ob->egl_disp,
+                                    re->generic.ob->egl_config,
                                     (EGLNativeWindowType)native_window,
                                     NULL);
    if (!surface)
@@ -418,7 +392,7 @@ evgl_eng_window_surface_create(void *data, void *native_window)
    // We don't need to create new one for GLX
    Window surface;
 
-   surface = re->win->win;
+   surface = re->generic.ob->win;
 
    return (void *)surface;
    */
@@ -446,7 +420,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
         return 0;
      }
 
-   eglDestroySurface(re->win->egl_disp, (EGLSurface)surface);
+   eglDestroySurface(re->generic.ob->egl_disp, (EGLSurface)surface);
 #endif
 
    return 1;
@@ -476,16 +450,16 @@ evgl_eng_context_create(void *data, void *share_ctx)
    // Share context already assumes that it's sharing with evas' context
    if (share_ctx)
      {
-        context = eglCreateContext(re->win->egl_disp,
-                                   re->win->egl_config,
+        context = eglCreateContext(re->generic.ob->egl_disp,
+                                   re->generic.ob->egl_config,
                                    (EGLContext)share_ctx,
                                    context_attrs);
      }
    else
      {
-        context = eglCreateContext(re->win->egl_disp,
-                                   re->win->egl_config,
-                                   re->win->egl_context[0], // Evas' GL Context
+        context = eglCreateContext(re->generic.ob->egl_disp,
+                                   re->generic.ob->egl_config,
+                                   re->generic.ob->egl_context[0], // Evas' GL Context
                                    context_attrs);
      }
 
@@ -502,16 +476,16 @@ evgl_eng_context_create(void *data, void *share_ctx)
    // Share context already assumes that it's sharing with evas' context
    if (share_ctx)
      {
-        context = glXCreateContext(re->info->info.display,
-                                   re->win->visualinfo,
+        context = glXCreateContext(re->generic.ob->info->info.display,
+                                   re->generic.ob->visualinfo,
                                    (GLXContext)share_ctx,
                                    1);
      }
    else
      {
-        context = glXCreateContext(re->info->info.display,
-                                   re->win->visualinfo,
-                                   re->win->context,      // Evas' GL Context
+        context = glXCreateContext(re->generic.ob->info->info.display,
+                                   re->generic.ob->visualinfo,
+                                   re->generic.ob->context,      // Evas' GL Context
                                    1);
      }
 
@@ -539,9 +513,9 @@ evgl_eng_context_destroy(void *data, void *context)
      }
 
 #ifdef GL_GLES
-   eglDestroyContext(re->win->egl_disp, (EGLContext)context);
+   eglDestroyContext(re->generic.ob->egl_disp, (EGLContext)context);
 #else
-   glXDestroyContext(re->info->info.display, (GLXContext)context);
+   glXDestroyContext(re->generic.ob->info->info.display, (GLXContext)context);
 #endif
 
    return 1;
@@ -560,10 +534,10 @@ evgl_eng_string_get(void *data)
      }
 
 #ifdef GL_GLES
-   return eglQueryString(re->win->egl_disp, EGL_EXTENSIONS);
+   return eglQueryString(re->generic.ob->egl_disp, EGL_EXTENSIONS);
 #else
-   return glXQueryExtensionsString(re->info->info.display,
-                                   re->info->info.screen);
+   return glXQueryExtensionsString(re->generic.ob->info->info.display,
+                                   re->generic.ob->info->info.screen);
 #endif
 }
 
@@ -591,8 +565,8 @@ evgl_eng_rotation_angle_get(void *data)
         return 0;
      }
 
-   if ((re->win) && (re->win->gl_context))
-      return re->win->gl_context->rot;
+   if ((re->generic.ob) && (re->generic.ob->gl_context))
+      return re->generic.ob->gl_context->rot;
    else
      {
         ERR("Unable to retrieve rotation angle.");
@@ -712,7 +686,7 @@ gl_extn_veto(Render_Engine *re)
 {
    const char *str = NULL;
 #ifdef GL_GLES
-   str = eglQueryString(re->win->egl_disp, EGL_EXTENSIONS);
+   str = eglQueryString(re->generic.ob->egl_disp, EGL_EXTENSIONS);
    if (str)
      {
         if (getenv("EVAS_GL_INFO"))
@@ -756,8 +730,8 @@ gl_extn_veto(Render_Engine *re)
         extn_have_buffer_age = 0;
      }
 #else
-   str = glXQueryExtensionsString(re->info->info.display,
-                                  re->info->info.screen);
+   str = glXQueryExtensionsString(re->generic.ob->info->info.display,
+                                  re->generic.ob->info->info.screen);
    if (str)
      {
         if (getenv("EVAS_GL_INFO"))
@@ -833,25 +807,12 @@ eng_info_free(Evas *eo_e EINA_UNUSED, void *info)
    free(in);
 }
 
-static int
-_re_wincheck(Render_Engine *re)
-{
-   if (re->win->surf) return 1;
-   eng_window_resurf(re->win);
-   re->lost_back = 1;
-   if (!re->win->surf)
-     {
-        ERR("GL engine can't re-create window surface!");
-     }
-   return 0;
-}
-
 static void
 _re_winfree(Render_Engine *re)
 {
-   if (!re->win->surf) return;
-   evas_gl_preload_render_relax(eng_preload_make_current, re);
-   eng_window_unsurf(re->win);
+   if (!re->generic.ob->surf) return;
+   evas_gl_preload_render_relax(eng_preload_make_current, re->generic.ob);
+   eng_window_unsurf(re->generic.ob);
 }
 
 static int
@@ -869,11 +830,113 @@ eng_setup(Evas *eo_e, void *in)
    Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
    Render_Engine *re;
    Evas_Engine_Info_GL_X11 *info;
+   Render_Engine_Swap_Mode swap_mode = MODE_FULL;
    const char *s;
 
    info = (Evas_Engine_Info_GL_X11 *)in;
+
+   if ((s = getenv("EVAS_GL_SWAP_MODE")))
+     {
+        if ((!strcasecmp(s, "full")) ||
+            (!strcasecmp(s, "f")))
+          swap_mode = MODE_FULL;
+        else if ((!strcasecmp(s, "copy")) ||
+                 (!strcasecmp(s, "c")))
+          swap_mode = MODE_COPY;
+        else if ((!strcasecmp(s, "double")) ||
+                 (!strcasecmp(s, "d")) ||
+                 (!strcasecmp(s, "2")))
+          swap_mode = MODE_DOUBLE;
+        else if ((!strcasecmp(s, "triple")) ||
+                 (!strcasecmp(s, "t")) ||
+                 (!strcasecmp(s, "3")))
+          swap_mode = MODE_TRIPLE;
+        else if ((!strcasecmp(s, "quadruple")) ||
+                 (!strcasecmp(s, "q")) ||
+                 (!strcasecmp(s, "4")))
+          swap_mode = MODE_QUADRUPLE;
+     }
+   else
+     {
+// in most gl implementations - egl and glx here that we care about the TEND
+// to either swap or copy backbuffer and front buffer, but strictly that is
+// not true. technically backbuffer content is totally undefined after a swap
+// and thus you MUST re-render all of it, thus MODE_FULL
+        swap_mode = MODE_FULL;
+// BUT... reality is that lmost every implementation copies or swaps so
+// triple buffer mode can be used as it is a superset of double buffer and
+// copy (though using those explicitly is more efficient). so let's play with
+// triple buffer mdoe as a default and see.
+//        re->mode = MODE_TRIPLE;
+// XXX: note - the above seems to break on some older intel chipsets and
+// drivers. it seems we CANT depend on backbuffer staying around. bugger!
+        switch (info->swap_mode)
+          {
+           case EVAS_ENGINE_GL_X11_SWAP_MODE_FULL:
+             swap_mode = MODE_FULL;
+             break;
+           case EVAS_ENGINE_GL_X11_SWAP_MODE_COPY:
+             swap_mode = MODE_COPY;
+             break;
+           case EVAS_ENGINE_GL_X11_SWAP_MODE_DOUBLE:
+             swap_mode = MODE_DOUBLE;
+             break;
+           case EVAS_ENGINE_GL_X11_SWAP_MODE_TRIPLE:
+             swap_mode = MODE_TRIPLE;
+             break;
+           case EVAS_ENGINE_GL_X11_SWAP_MODE_QUADRUPLE:
+             swap_mode = MODE_QUADRUPLE;
+             break;
+           default:
+             swap_mode = MODE_AUTO;
+             break;
+          }
+     }
+
+   if (safe_native == -1)
+     {
+        s = getenv("EVAS_GL_SAFE_NATIVE");
+        safe_native = 0;
+        if (s) safe_native = atoi(s);
+        else
+          {
+             s = (const char *)glGetString(GL_RENDERER);
+             if (s)
+               {
+                  if (strstr(s, "PowerVR SGX 540") ||
+                      strstr(s, "Mali-400 MP"))
+                    safe_native = 1;
+               }
+          }
+     }
+
+   // Set this env var to dump files every frame
+   // Or set the global var in gdb to 1|0 to turn it on and off
+   if (getenv("EVAS_GL_SWAP_BUFFER_DEBUG_ALWAYS"))
+     swap_buffer_debug = 1;
+
+   if (swap_buffer_debug_mode == -1)
+     {
+        if (
+#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
+            (getuid() == geteuid()) &&
+#endif
+            ((debug_dir = getenv("EVAS_GL_SWAP_BUFFER_DEBUG_DIR"))))
+          {
+             int stat;
+             // Create a directory with 0775 permission
+             stat = mkdir(debug_dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+             if ((!stat) || errno == EEXIST) swap_buffer_debug_mode = 1;
+          }
+        else
+           swap_buffer_debug_mode = 0;
+     }
+
+
    if (!e->engine.data.output)
      {
+        Outbuf *ob;
+        Render_Engine_Merge_Mode merge_mode = MERGE_BOUNDING;
 #ifdef GL_GLES
 #else
         int eb, evb;
@@ -882,29 +945,56 @@ eng_setup(Evas *eo_e, void *in)
 #endif
         re = calloc(1, sizeof(Render_Engine));
         if (!re) return 0;
-        re->info = info;
-        re->evas = (Evas *)e;
-        re->w = e->output.w;
-        re->h = e->output.h;
-        re->win = eng_window_new(re->info->info.display,
-                                 re->info->info.drawable,
-                                 re->info->info.screen,
-                                 re->info->info.visual,
-                                 re->info->info.colormap,
-                                 re->info->info.depth,
-                                 re->w,
-                                 re->h,
-                                 re->info->indirect,
-                                 re->info->info.destination_alpha,
-                                 re->info->info.rotation);
-        if (!re->win)
+        ob = eng_window_new(info, eo_e,
+                            info->info.display,
+                            info->info.drawable,
+                            info->info.screen,
+                            info->info.visual,
+                            info->info.colormap,
+                            info->info.depth,
+                            e->output.w, e->output.h,
+                            info->indirect,
+                            info->info.destination_alpha,
+                            info->info.rotation,
+                            swap_mode);
+        if (!ob)
           {
              free(re);
              return 0;
           }
+
+        if (!evas_render_engine_software_generic_init(&re->generic, ob,
+                                                      eng_outbuf_swap_mode,
+                                                      eng_outbuf_get_rot,
+                                                      eng_outbuf_reconfigure,
+                                                      eng_outbuf_region_first_rect,
+                                                      eng_outbuf_new_region_for_update,
+                                                      eng_outbuf_push_updated_region,
+                                                      eng_outbuf_push_free_region_for_update,
+                                                      NULL,
+                                                      eng_outbuf_flush,
+                                                      eng_window_free,
+                                                      e->output.w, e->output.h))
+          {
+             free(re);
+             return 0;
+          }
+
         e->engine.data.output = re;
         gl_wins++;
 
+        if ((s = getenv("EVAS_GL_PARTIAL_MERGE")))
+          {
+             if ((!strcmp(s, "bounding")) ||
+                 (!strcmp(s, "b")))
+               merge_mode = MERGE_BOUNDING;
+             else if ((!strcmp(s, "full")) ||
+                      (!strcmp(s, "f")))
+               merge_mode = MERGE_FULL;
+          }
+
+        evas_render_engine_software_generic_merge_mode_set(&re->generic, merge_mode);
+
         if (!initted)
           {
              gl_symbols();
@@ -929,111 +1019,60 @@ eng_setup(Evas *eo_e, void *in)
    else
      {
         re = e->engine.data.output;
-        if (re->win && _re_wincheck(re))
+        if (re->generic.ob && _re_wincheck(re->generic.ob))
           {
-             if ((re->info->info.display != re->win->disp) ||
-                 (re->info->info.drawable != re->win->win) ||
-                 (re->info->info.screen != re->win->screen) ||
-                 (re->info->info.visual != re->win->visual) ||
-                 (re->info->info.colormap != re->win->colormap) ||
-                 (re->info->info.depth != re->win->depth) ||
-                 (re->info->info.destination_alpha != re->win->alpha))
+             if ((re->generic.ob->info->info.display != re->generic.ob->disp) ||
+                 (re->generic.ob->info->info.drawable != re->generic.ob->win) ||
+                 (re->generic.ob->info->info.screen != re->generic.ob->screen) ||
+                 (re->generic.ob->info->info.visual != re->generic.ob->visual) ||
+                 (re->generic.ob->info->info.colormap != re->generic.ob->colormap) ||
+                 (re->generic.ob->info->info.depth != re->generic.ob->depth) ||
+                 (re->generic.ob->info->info.destination_alpha != re->generic.ob->alpha))
                {
-                  re->win->gl_context->references++;
-                  eng_window_free(re->win);
+                  Outbuf *ob;
+
+                  re->generic.ob->gl_context->references++;
+                  eng_window_free(re->generic.ob);
+                  re->generic.ob = NULL;
                   gl_wins--;
 
-                  re->w = e->output.w;
-                  re->h = e->output.h;
-                  re->win = eng_window_new(re->info->info.display,
-                                           re->info->info.drawable,
-                                           re->info->info.screen,
-                                           re->info->info.visual,
-                                           re->info->info.colormap,
-                                           re->info->info.depth,
-                                           re->w,
-                                           re->h,
-                                           re->info->indirect,
-                                           re->info->info.destination_alpha,
-                                           re->info->info.rotation);
-                  eng_window_use(re->win);
-                  if (re->win)
+                  ob = eng_window_new(info, eo_e,
+                                      re->generic.ob->info->info.display,
+                                      re->generic.ob->info->info.drawable,
+                                      re->generic.ob->info->info.screen,
+                                      re->generic.ob->info->info.visual,
+                                      re->generic.ob->info->info.colormap,
+                                      re->generic.ob->info->info.depth,
+                                      e->output.w, e->output.h,
+                                      re->generic.ob->info->indirect,
+                                      re->generic.ob->info->info.destination_alpha,
+                                      re->generic.ob->info->info.rotation,
+                                      swap_mode);
+                  eng_window_use(ob);
+                  if (ob)
                     {
+                       evas_render_engine_software_generic_update(&re->generic, ob,
+                                                                  e->output.w, e->output.h);
+
                        gl_wins++;
-                       re->win->gl_context->references--;
+                       re->generic.ob->gl_context->references--;
                     }
                }
-             else if ((re->win->w != e->output.w) ||
-                      (re->win->h != e->output.h) ||
-                      (re->info->info.rotation != re->win->rot))
+             else if ((re->generic.ob->w != e->output.w) ||
+                      (re->generic.ob->h != e->output.h) ||
+                      (re->generic.ob->info->info.rotation != re->generic.ob->rot))
                {
-                  re->w = e->output.w;
-                  re->h = e->output.h;
-                  re->win->w = e->output.w;
-                  re->win->h = e->output.h;
-                  re->win->rot = re->info->info.rotation;
-                  eng_window_use(re->win);
-                  evas_gl_common_context_resize(re->win->gl_context, re->win->w, re->win->h, re->win->rot);
+                  eng_outbuf_reconfigure(re->generic.ob, e->output.w, e->output.h, re->generic.ob->info->info.rotation, 0);
+                  if (re->generic.tb)
+                    evas_common_tilebuf_free(re->generic.tb);
+                  re->generic.tb = evas_common_tilebuf_new(e->output.w, e->output.h);
+                  if (re->generic.tb)
+                    evas_common_tilebuf_set_tile_size(re->generic.tb,
+                                                      TILESIZE, TILESIZE);
                }
           }
      }
-   if ((s = getenv("EVAS_GL_SWAP_MODE")))
-     {
-        if ((!strcasecmp(s, "full")) ||
-            (!strcasecmp(s, "f")))
-          re->mode = MODE_FULL;
-        else if ((!strcasecmp(s, "copy")) ||
-                 (!strcasecmp(s, "c")))
-          re->mode = MODE_COPY;
-        else if ((!strcasecmp(s, "double")) ||
-                 (!strcasecmp(s, "d")) ||
-                 (!strcasecmp(s, "2")))
-          re->mode = MODE_DOUBLE;
-        else if ((!strcasecmp(s, "triple")) ||
-                 (!strcasecmp(s, "t")) ||
-                 (!strcasecmp(s, "3")))
-          re->mode = MODE_TRIPLE;
-        else if ((!strcasecmp(s, "quadruple")) ||
-                 (!strcasecmp(s, "q")) ||
-                 (!strcasecmp(s, "4")))
-          re->mode = MODE_QUADRUPLE;
-     }
-   else
-     {
-// in most gl implementations - egl and glx here that we care about the TEND
-// to either swap or copy backbuffer and front buffer, but strictly that is
-// not true. technically backbuffer content is totally undefined after a swap
-// and thus you MUST re-render all of it, thus MODE_FULL
-        re->mode = MODE_FULL;
-// BUT... reality is that lmost every implementation copies or swaps so
-// triple buffer mode can be used as it is a superset of double buffer and
-// copy (though using those explicitly is more efficient). so let's play with
-// triple buffer mdoe as a default and see.
-//        re->mode = MODE_TRIPLE;
-// XXX: note - the above seems to break on some older intel chipsets and
-// drivers. it seems we CANT depend on backbuffer staying around. bugger!
-        switch (info->swap_mode)
-          {
-           case EVAS_ENGINE_GL_X11_SWAP_MODE_FULL:
-             re->mode = MODE_FULL;
-             break;
-           case EVAS_ENGINE_GL_X11_SWAP_MODE_COPY:
-             re->mode = MODE_COPY;
-             break;
-           case EVAS_ENGINE_GL_X11_SWAP_MODE_DOUBLE:
-             re->mode = MODE_DOUBLE;
-             break;
-           case EVAS_ENGINE_GL_X11_SWAP_MODE_TRIPLE:
-             re->mode = MODE_TRIPLE;
-             break;
-           case EVAS_ENGINE_GL_X11_SWAP_MODE_QUADRUPLE:
-             re->mode = MODE_QUADRUPLE;
-             break;
-           default:
-             break;
-          }
-     }
-   if (!re->win)
+   if (!re->generic.ob)
      {
         free(re);
         return 0;
@@ -1041,35 +1080,21 @@ eng_setup(Evas *eo_e, void *in)
 
    if (!e->engine.data.output)
      {
-        if (re->win)
+        if (re->generic.ob)
           {
-             eng_window_free(re->win);
+             eng_window_free(re->generic.ob);
              gl_wins--;
           }
         free(re);
         return 0;
      }
-   if (re->tb) evas_common_tilebuf_free(re->tb);
-   re->tb = evas_common_tilebuf_new(re->win->w, re->win->h);
-   if (!re->tb)
-     {
-        if (re->win)
-          {
-             eng_window_free(re->win);
-             gl_wins--;
-          }
-        free(re);
-        return 0;
-     }
-   evas_common_tilebuf_set_tile_size(re->tb, EVAS_GL_UPDATE_TILE_SIZE, EVAS_GL_UPDATE_TILE_SIZE);
-   evas_common_tilebuf_tile_strict_set(re->tb, EINA_TRUE);
+
+   evas_render_engine_software_generic_tile_strict_set(&re->generic, EINA_TRUE);
 
    if (!e->engine.data.context)
      e->engine.data.context =
      e->engine.func->context_new(e->engine.data.output);
-   eng_window_use(re->win);
-
-   re->vsync = 0;
+   eng_window_use(re->generic.ob);
 
    return 1;
 }
@@ -1083,43 +1108,35 @@ eng_output_free(void *data)
 
    if (re)
      {
-        evas_gl_preload_render_relax(eng_preload_make_current, re);
+#ifndef GL_GLES
+        Display *disp = re->generic.ob->disp;
+        Window win = re->generic.ob->win;
+#endif
+
+        evas_gl_preload_render_relax(eng_preload_make_current, re->generic.ob);
 
 #if 0
 #ifdef GL_GLES
         // Destroy the resource surface
         // Only required for EGL case
         if (re->surface)
-           eglDestroySurface(re->win->egl_disp, re->surface);
+           eglDestroySurface(re->generic.ob->egl_disp, re->surface);
 #endif
 
         // Destroy the resource context
         _destroy_internal_context(re, context);
 #endif
-        if (re->win)
-          {
-             if (gl_wins == 1) evgl_engine_shutdown(re);
 
-#ifdef GL_GLES
-             eng_window_free(re->win);
-#else        
-             Display *disp = re->win->disp;
-             Window win = re->win->win;
-             eng_window_free(re->win);
-             if (glsym_glXReleaseBuffersMESA)
-               glsym_glXReleaseBuffersMESA(disp, win);
+        if (gl_wins == 1) evgl_engine_shutdown(re);
+
+        evas_render_engine_software_generic_clean(&re->generic);
+
+#ifndef GL_GLES
+        if (glsym_glXReleaseBuffersMESA)
+          glsym_glXReleaseBuffersMESA(disp, win);
 #endif
-             gl_wins--;
-          }
-        
-        evas_common_tilebuf_free(re->tb);
-        if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
-        if (re->rects_prev[0]) evas_common_tilebuf_free_render_rects(re->rects_prev[0]);
-        if (re->rects_prev[1]) evas_common_tilebuf_free_render_rects(re->rects_prev[1]);
-        if (re->rects_prev[2]) evas_common_tilebuf_free_render_rects(re->rects_prev[2]);
-        if (re->rects_prev[3]) evas_common_tilebuf_free_render_rects(re->rects_prev[3]);
+        gl_wins--;
 
-        
         free(re);
      }
    if ((initted == 1) && (gl_wins == 0))
@@ -1131,164 +1148,23 @@ eng_output_free(void *data)
      }
 }
 
-static void
-eng_output_resize(void *data, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   re->win->w = w;
-   re->win->h = h;
-   eng_window_use(re->win);
-   evas_gl_common_context_resize(re->win->gl_context, w, h, re->win->rot);
-   evas_common_tilebuf_free(re->tb);
-   re->tb = evas_common_tilebuf_new(w, h);
-   if (re->tb)
-     {
-        evas_common_tilebuf_set_tile_size(re->tb, EVAS_GL_UPDATE_TILE_SIZE, EVAS_GL_UPDATE_TILE_SIZE);
-        evas_common_tilebuf_tile_strict_set(re->tb, EINA_TRUE);
-     }
-}
-
-static void
-eng_output_tile_size_set(void *data, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   evas_common_tilebuf_set_tile_size(re->tb, w, h);
-}
-
-static void
-eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_resize(re->win->gl_context, re->win->w, re->win->h, re->win->rot);
-   evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
-}
-
-static void
-eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
-}
-
-static void
-eng_output_redraws_clear(void *data)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   evas_common_tilebuf_clear(re->tb);
-//   INF("GL: finish update cycle!");
-}
-
-static Tilebuf_Rect *
-_merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3, Tilebuf_Rect *r4)
-{
-   Tilebuf_Rect *r, *rects;
-   Evas_Point p1, p2;
-
-   if (r1)
-     {
-        EINA_INLIST_FOREACH(EINA_INLIST_GET(r1), r)
-          {
-             evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
-          }
-     }
-   if (r2)
-     {
-        EINA_INLIST_FOREACH(EINA_INLIST_GET(r2), r)
-          {
-             evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
-          }
-     }
-   if (r3)
-     {
-        EINA_INLIST_FOREACH(EINA_INLIST_GET(r3), r)
-          {
-             evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
-          }
-     }
-   if (r4)
-     {
-        EINA_INLIST_FOREACH(EINA_INLIST_GET(r4), r)
-          {
-             evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
-          }
-     }
-   rects = evas_common_tilebuf_get_render_rects(tb);
-   
-   if (partial_rect_union_mode == -1)
-     {
-        const char *s = getenv("EVAS_GL_PARTIAL_MERGE");
-        if (s)
-          {
-             if ((!strcmp(s, "bounding")) ||
-                 (!strcmp(s, "b")))
-               partial_rect_union_mode = MERGE_BOUNDING;
-             else if ((!strcmp(s, "full")) ||
-                      (!strcmp(s, "f")))
-               partial_rect_union_mode = MERGE_FULL;
-          }
-        else
-          partial_rect_union_mode = MERGE_BOUNDING;
-     }
-   if (partial_rect_union_mode == MERGE_BOUNDING)
-     {
-// bounding box -> make a bounding box single region update of all regions.
-// yes we could try and be smart and figure out size of regions, how far
-// apart etc. etc. to try and figure out an optimal "set". this is a tradeoff
-// between multiple update regions to render and total pixels to render.
-        if (rects)
-          {
-             p1.x = rects->x; p1.y = rects->y;
-             p2.x = rects->x + rects->w; p2.y = rects->y + rects->h;
-             EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
-               {
-                  if (r->x < p1.x) p1.x = r->x;
-                  if (r->y < p1.y) p1.y = r->y;
-                  if ((r->x + r->w) > p2.x) p2.x = r->x + r->w;
-                  if ((r->y + r->h) > p2.y) p2.y = r->y + r->h;
-               }
-             evas_common_tilebuf_free_render_rects(rects);
-             rects = calloc(1, sizeof(Tilebuf_Rect));
-             if (rects)
-               {
-                  rects->x = p1.x;
-                  rects->y = p1.y;
-                  rects->w = p2.x - p1.x;
-                  rects->h = p2.y - p1.y;
-               }
-          }
-     }
-   evas_common_tilebuf_clear(tb);
-   return rects;
-}
-
 /* vsync games - not for now though */
 #define VSYNC_TO_SCREEN 1
 
-static Eina_Bool
+Eina_Bool
 eng_preload_make_current(void *data, void *doit)
 {
-   Render_Engine *re = data;
+   Outbuf *ob = data;
 
    if (doit)
      {
 #ifdef GL_GLES
-        if (!eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], re->win->egl_surface[0], re->win->egl_context[0]))
+        if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0], ob->egl_surface[0], ob->egl_context[0]))
           return EINA_FALSE;
 #else
-        if (!glXMakeCurrent(re->info->info.display, re->win->win, re->win->context))
+        if (!glXMakeCurrent(ob->info->info.display, ob->win, ob->context))
           {
-             ERR("glXMakeCurrent(%p, 0x%x, %p) failed", re->info->info.display, (unsigned int)re->win->win, (void *)re->win->context);
+             ERR("glXMakeCurrent(%p, 0x%x, %p) failed", ob->info->info.display, (unsigned int)ob->win, (void *)ob->context);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
              return EINA_FALSE;
           }
@@ -1297,12 +1173,12 @@ eng_preload_make_current(void *data, void *doit)
    else
      {
 #ifdef GL_GLES
-        if (!eglMakeCurrent(re->win->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
+        if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
           return EINA_FALSE;
 #else
-        if (!glXMakeCurrent(re->info->info.display, None, NULL))
+        if (!glXMakeCurrent(ob->info->info.display, None, NULL))
           {
-             ERR("glXMakeCurrent(%p, None, NULL) failed", re->info->info.display);
+             ERR("glXMakeCurrent(%p, None, NULL) failed", ob->info->info.display);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
              return EINA_FALSE;
           }
@@ -1311,435 +1187,6 @@ eng_preload_make_current(void *data, void *doit)
    return EINA_TRUE;
 }
 
-static void *
-eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
-{
-   Render_Engine *re;
-   Tilebuf_Rect *rect;
-   Eina_Bool first_rect = EINA_FALSE;
-   
-#define CLEAR_PREV_RECTS(x) \
-   do { \
-      if (re->rects_prev[x]) \
-        evas_common_tilebuf_free_render_rects(re->rects_prev[x]); \
-      re->rects_prev[x] = NULL; \
-   } while (0)
-
-   re = (Render_Engine *)data;
-   /* get the upate rect surface - return engine data as dummy */
-   if (re->end)
-     {
-        re->end = 0;
-        return NULL;
-     }
-   if (!re->rects)
-     {
-        re->rects = evas_common_tilebuf_get_render_rects(re->tb);
-        if (re->rects)
-          {
-             if (re->info->swap_mode == EVAS_ENGINE_GL_X11_SWAP_MODE_AUTO)
-               {
-                  if (extn_have_buffer_age)
-                    {
-#ifdef GL_GLES
-                       EGLint age = 0;
-                  
-                       if (!eglQuerySurface(re->win->egl_disp,
-                                            re->win->egl_surface[0],
-                                            EGL_BUFFER_AGE_EXT, &age))
-                         age = 0;
-#else
-                       unsigned int age = 0;
-                  
-                       if (glsym_glXQueryDrawable)
-                         {
-                            if (re->win->glxwin)
-                              glsym_glXQueryDrawable(re->win->disp,
-                                                     re->win->glxwin,
-                                                     GLX_BACK_BUFFER_AGE_EXT,
-                                                     &age);
-                            else
-                              glsym_glXQueryDrawable(re->win->disp,
-                                                     re->win->win,
-                                                     GLX_BACK_BUFFER_AGE_EXT,
-                                                     &age);
-                         }
-#endif
-                       if (age == 1) re->mode = MODE_COPY;
-                       else if (age == 2) re->mode = MODE_DOUBLE;
-                       else if (age == 3) re->mode = MODE_TRIPLE;
-                       else if (age == 4) re->mode = MODE_QUADRUPLE;
-                       else re->mode = MODE_FULL;
-                       if ((int)age != re->prev_age) re->mode = MODE_FULL;
-                       re->prev_age = age;
-                    }
-               }
-             if ((re->lost_back) || (re->mode == MODE_FULL))
-               {
-                  /* if we lost our backbuffer since the last frame redraw all */
-                  re->lost_back = 0;
-                  evas_common_tilebuf_add_redraw(re->tb, 0, 0, re->win->w, re->win->h);
-                  evas_common_tilebuf_free_render_rects(re->rects);
-                  re->rects = evas_common_tilebuf_get_render_rects(re->tb);
-               }
-             /* ensure we get rid of previous rect lists we dont need if mode
-              * changed/is appropriate */
-             evas_common_tilebuf_clear(re->tb);
-             CLEAR_PREV_RECTS(3);
-             re->rects_prev[3] = re->rects_prev[2];
-             re->rects_prev[2] = re->rects_prev[1];
-             re->rects_prev[1] = re->rects_prev[0];
-             re->rects_prev[0] = re->rects;
-             re->rects = NULL;
-             switch (re->mode)
-               {
-                case MODE_FULL:
-                case MODE_COPY: // no prev rects needed
-                  re->rects = _merge_rects(re->tb, re->rects_prev[0], NULL, NULL, NULL);
-                  break;
-                case MODE_DOUBLE: // double mode - only 1 level of prev rect
-                  re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], NULL, NULL);
-                  break;
-                case MODE_TRIPLE: // triple mode - 2 levels of prev rect
-                  re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], re->rects_prev[2], NULL);
-                  break;
-                case MODE_QUADRUPLE: // keep all
-                  re->rects = _merge_rects(re->tb, re->rects_prev[0], re->rects_prev[1], re->rects_prev[2], re->rects_prev[3]);
-                  break;
-                default:
-                  break;
-               }
-             first_rect = EINA_TRUE;
-          }
-        evas_common_tilebuf_clear(re->tb);
-        re->cur_rect = EINA_INLIST_GET(re->rects);
-     }
-   if (!re->cur_rect) return NULL;
-   rect = (Tilebuf_Rect *)re->cur_rect;
-   if (re->rects)
-     {
-        re->win->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
-
-        switch (re->mode)
-          {
-           case MODE_COPY:
-           case MODE_DOUBLE:
-           case MODE_TRIPLE:
-           case MODE_QUADRUPLE:
-             rect = (Tilebuf_Rect *)re->cur_rect;
-             *x = rect->x;
-             *y = rect->y;
-             *w = rect->w;
-             *h = rect->h;
-             *cx = rect->x;
-             *cy = rect->y;
-             *cw = rect->w;
-             *ch = rect->h;
-             re->cur_rect = re->cur_rect->next;
-             re->win->gl_context->master_clip.enabled = EINA_TRUE;
-             re->win->gl_context->master_clip.x = rect->x;
-             re->win->gl_context->master_clip.y = rect->y;
-             re->win->gl_context->master_clip.w = rect->w;
-             re->win->gl_context->master_clip.h = rect->h;
-             break;
-           case MODE_FULL:
-             re->cur_rect = NULL;
-             if (x) *x = 0;
-             if (y) *y = 0;
-             if (w) *w = re->win->w;
-             if (h) *h = re->win->h;
-             if (cx) *cx = 0;
-             if (cy) *cy = 0;
-             if (cw) *cw = re->win->w;
-             if (ch) *ch = re->win->h;
-             re->win->gl_context->master_clip.enabled = EINA_FALSE;
-             break;
-           default:
-             break;
-          }
-        if (first_rect)
-          {
-             evas_gl_preload_render_lock(eng_preload_make_current, re);
-#ifdef GL_GLES
-             // dont need to for egl - eng_window_use() can check for other ctxt's
-#else
-             eng_window_use(NULL);
-#endif
-             eng_window_use(re->win);
-             if (!_re_wincheck(re)) return NULL;
-             
-             evas_gl_common_context_flush(re->win->gl_context);
-             evas_gl_common_context_newframe(re->win->gl_context);
-             if (partial_render_debug == -1)
-               {
-                  if (getenv("EVAS_GL_PARTIAL_DEBUG")) partial_render_debug = 1;
-                  else partial_render_debug = 0;
-               }
-             if (partial_render_debug == 1)
-               {
-                  glClearColor(0.2, 0.5, 1.0, 1.0);
-                  glClear(GL_COLOR_BUFFER_BIT);
-               }
-          }
-        if (!re->cur_rect)
-          {
-             re->end = 1;
-          }
-        return re->win->gl_context->def_surface;
-     }
-   return NULL;
-}
-
-static int safe_native = -1;
-
-static void
-eng_output_redraws_next_update_push(void *data, void *surface EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED, Evas_Render_Mode render_mode)
-{
-   Render_Engine *re;
-
-   if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
-
-   re = (Render_Engine *)data;
-   /* put back update surface.. in this case just unflag redraw */
-   if (!_re_wincheck(re)) return;
-   re->win->draw.drew = 1;
-   evas_gl_common_context_flush(re->win->gl_context);
-   if (safe_native == -1)
-     {
-        const char *s = getenv("EVAS_GL_SAFE_NATIVE");
-        safe_native = 0;
-        if (s) safe_native = atoi(s);
-        else
-          {
-             s = (const char *)glGetString(GL_RENDERER);
-             if (s)
-               {
-                  if (strstr(s, "PowerVR SGX 540") ||
-                      strstr(s, "Mali-400 MP"))
-                    safe_native = 1;
-               }
-          }
-     }
-#ifdef GL_GLES
-   // this is needed to make sure all previous rendering is flushed to
-   // buffers/surfaces
-   // previous rendering should be done and swapped
-//xx   if (!safe_native) eglWaitNative(EGL_CORE_NATIVE_ENGINE);
-//   if (eglGetError() != EGL_SUCCESS)
-//     {
-//        printf("Error:  eglWaitNative(EGL_CORE_NATIVE_ENGINE) fail.\n");
-//     }
-#else
-   // previous rendering should be done and swapped
-//xx   if (!safe_native) glXWaitX();
-#endif
-}
-
-static void
-eng_output_flush(void *data, Evas_Render_Mode render_mode)
-{
-   Render_Engine *re;
-   static char *dname = NULL;
-
-   re = (Render_Engine *)data;
-
-   if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
-
-   if (!_re_wincheck(re)) goto end;
-   if (!re->win->draw.drew) goto end;
-   
-   re->win->draw.drew = 0;
-   eng_window_use(re->win);
-   evas_gl_common_context_done(re->win->gl_context);
-
-   // Save contents of the framebuffer to a file
-   if (swap_buffer_debug_mode == -1)
-     {
-        if (
-#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
-            (getuid() == geteuid()) &&
-#endif
-            ((dname = getenv("EVAS_GL_SWAP_BUFFER_DEBUG_DIR"))))
-          {
-             int stat;
-             // Create a directory with 0775 permission
-             stat = mkdir(dname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-             if ((!stat) || errno == EEXIST) swap_buffer_debug_mode = 1;
-          }
-        else
-           swap_buffer_debug_mode = 0;
-     }
-
-   if (swap_buffer_debug_mode == 1)
-     {
-        // Set this env var to dump files every frame
-        // Or set the global var in gdb to 1|0 to turn it on and off
-        if (getenv("EVAS_GL_SWAP_BUFFER_DEBUG_ALWAYS"))
-           swap_buffer_debug = 1;
-
-        if (swap_buffer_debug)
-          {
-             char fname[100];
-             int ret = 0;
-             snprintf(fname, sizeof(fname), "%p", (void*)re->win);
-
-             ret = evas_gl_common_buffer_dump(re->win->gl_context,
-                                              (const char*)dname,
-                                              (const char*)fname,
-                                              re->frame_cnt,
-                                              NULL);
-             if (!ret) swap_buffer_debug_mode = 0;
-          }
-     }
-
-#ifdef GL_GLES
-   if (!re->vsync)
-     {
-        if (re->info->vsync) eglSwapInterval(re->win->egl_disp, 1);
-        else eglSwapInterval(re->win->egl_disp, 0);
-        re->vsync = 1;
-     }
-   if (re->info->callback.pre_swap)
-     {
-        re->info->callback.pre_swap(re->info->callback.data, re->evas);
-     }
-   if ((glsym_eglSwapBuffersWithDamage) && (re->mode != MODE_FULL))
-     {
-        EGLint num = 0, *rects = NULL, i = 0;
-        Tilebuf_Rect *r;
-        
-        // if partial swaps can be done use re->rects
-        num = eina_inlist_count(EINA_INLIST_GET(re->rects));
-        if (num > 0)
-          {
-             rects = alloca(sizeof(EGLint) * 4 * num);
-             EINA_INLIST_FOREACH(EINA_INLIST_GET(re->rects), r)
-               {
-                  int gw, gh;
-                  
-                  gw = re->win->gl_context->w;
-                  gh = re->win->gl_context->h;
-                  switch (re->win->rot)
-                    {
-                     case 0:
-                       rects[i + 0] = r->x;
-                       rects[i + 1] = gh - (r->y + r->h);
-                       rects[i + 2] = r->w;
-                       rects[i + 3] = r->h;
-                       break;
-                     case 90:
-                       rects[i + 0] = r->y;
-                       rects[i + 1] = r->x;
-                       rects[i + 2] = r->h;
-                       rects[i + 3] = r->w;
-                       break;
-                     case 180:
-                       rects[i + 0] = gw - (r->x + r->w);
-                       rects[i + 1] = r->y;
-                       rects[i + 2] = r->w;
-                       rects[i + 3] = r->h;
-                       break;
-                     case 270:
-                       rects[i + 0] = gh - (r->y + r->h);
-                       rects[i + 1] = gw - (r->x + r->w);
-                       rects[i + 2] = r->h;
-                       rects[i + 3] = r->w;
-                       break;
-                     default:
-                       rects[i + 0] = r->x;
-                       rects[i + 1] = gh - (r->y + r->h);
-                       rects[i + 2] = r->w;
-                       rects[i + 3] = r->h;
-                       break;
-                    }
-                  i += 4;
-               }
-             glsym_eglSwapBuffersWithDamage(re->win->egl_disp,
-                                            re->win->egl_surface[0],
-                                            rects, num);
-          }
-     }
-   else
-      eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]);
-
-//xx   if (!safe_native) eglWaitGL();
-   if (re->info->callback.post_swap)
-     {
-        re->info->callback.post_swap(re->info->callback.data, re->evas);
-     }
-//   if (eglGetError() != EGL_SUCCESS)
-//     {
-//        printf("Error:  eglSwapBuffers() fail.\n");
-//     }
-#else
-#ifdef VSYNC_TO_SCREEN
-   if (re->info->vsync)
-     {
-        if (glsym_glXSwapIntervalEXT)
-          {
-             if (!re->vsync)
-               {
-                  if (re->info->vsync) glsym_glXSwapIntervalEXT(re->win->disp, re->win->win, 1);
-                  else glsym_glXSwapIntervalEXT(re->win->disp, re->win->win, 0);
-                  re->vsync = 1;
-               }
-          }
-        else if (glsym_glXSwapIntervalSGI)
-          {
-             if (!re->vsync)
-               {
-                  if (re->info->vsync) glsym_glXSwapIntervalSGI(1);
-                  else glsym_glXSwapIntervalSGI(0);
-                  re->vsync = 1;
-               }
-          }
-        else
-          {
-             if ((glsym_glXGetVideoSync) && (glsym_glXWaitVideoSync))
-               {
-                  unsigned int rc;
-
-                  glsym_glXGetVideoSync(&rc);
-                  glsym_glXWaitVideoSync(1, 0, &rc);
-               }
-          }
-     }
-#endif
-   if (re->info->callback.pre_swap)
-     {
-        re->info->callback.pre_swap(re->info->callback.data, re->evas);
-     }
-   // XXX: if partial swaps can be done use re->rects
-//   measure(0, "swap");
-   glXSwapBuffers(re->win->disp, re->win->win);
-//   measure(1, "swap");
-   if (re->info->callback.post_swap)
-     {
-        re->info->callback.post_swap(re->info->callback.data, re->evas);
-     }
-#endif
-   // clear out rects after swap as we may use them during swap
-   if (re->rects)
-     {
-        evas_common_tilebuf_free_render_rects(re->rects);
-        re->rects = NULL;
-     }
-
-   re->frame_cnt++;
-
- end:
-   evas_gl_preload_render_unlock(eng_preload_make_current, re);
-}
-
-static void
-eng_output_idle_flush(void *data)
-{
-   Render_Engine *re;
-
-   re = (Render_Engine *)data;
-   (void) re;
-}
-
 static void
 eng_output_dump(void *data)
 {
@@ -1748,40 +1195,20 @@ eng_output_dump(void *data)
    re = (Render_Engine *)data;
    evas_common_image_image_all_unload();
    evas_common_font_font_all_unload();
-   evas_gl_common_image_all_unload(re->win->gl_context);
+   evas_gl_common_image_all_unload(re->generic.ob->gl_context);
    _re_winfree(re);
 }
 
 static void
-eng_context_cutout_add(void *data EINA_UNUSED, void *context, int x, int y, int w, int h)
-{
-//   Render_Engine *re;
-//
-//   re = (Render_Engine *)data;
-//   re->win->gl_context->dc = context;
-   evas_common_draw_context_add_cutout(context, x, y, w, h);
-}
-
-static void
-eng_context_cutout_clear(void *data EINA_UNUSED, void *context)
-{
-//   Render_Engine *re;
-//
-//   re = (Render_Engine *)data;
-//   re->win->gl_context->dc = context;
-   evas_common_draw_context_clear_cutouts(context);
-}
-
-static void
 eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h, Eina_Bool do_async EINA_UNUSED)
 {
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
-   re->win->gl_context->dc = context;
-   evas_gl_common_rect_draw(re->win->gl_context, x, y, w, h);
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_target_surface_set(re->generic.ob->gl_context, surface);
+   re->generic.ob->gl_context->dc = context;
+   evas_gl_common_rect_draw(re->generic.ob->gl_context, x, y, w, h);
 }
 
 static void
@@ -1790,10 +1217,10 @@ eng_line_draw(void *data, void *context, void *surface, int p1x, int p1y, int p2
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
-   re->win->gl_context->dc = context;
-   evas_gl_common_line_draw(re->win->gl_context, p1x, p1y, p2x, p2y);
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_target_surface_set(re->generic.ob->gl_context, surface);
+   re->generic.ob->gl_context->dc = context;
+   evas_gl_common_line_draw(re->generic.ob->gl_context, p1x, p1y, p2x, p2y);
 }
 
 static void *
@@ -1822,10 +1249,10 @@ eng_polygon_draw(void *data, void *context, void *surface EINA_UNUSED, void *pol
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
-   re->win->gl_context->dc = context;
-   evas_gl_common_poly_draw(re->win->gl_context, polygon, x, y);
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_target_surface_set(re->generic.ob->gl_context, surface);
+   re->generic.ob->gl_context->dc = context;
+   evas_gl_common_poly_draw(re->generic.ob->gl_context, polygon, x, y);
 }
 
 static int
@@ -1867,7 +1294,7 @@ eng_image_alpha_set(void *data, void *image, int has_alpha)
         im->alpha = has_alpha;
         return image;
      }
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    if ((im->tex) && (im->tex->pt->dyn.img))
      {
         im->alpha = has_alpha;
@@ -1962,7 +1389,7 @@ eng_image_colorspace_set(void *data, void *image, Evas_Colorspace cspace)
    if (im->native.data) return;
    /* FIXME: can move to gl_common */
    if (im->cs.space == cspace) return;
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    evas_gl_common_image_alloc_ensure(im);
    evas_cache_image_colorspace(&im->im->cache_entry, cspace);
    switch (cspace)
@@ -2054,7 +1481,7 @@ _native_bind_cb(void *data, void *image)
 
       if (glsym_glXBindTexImage)
         {
-          glsym_glXBindTexImage(re->win->disp, n->glx_pixmap,
+          glsym_glXBindTexImage(re->generic.ob->disp, n->glx_pixmap,
                                 GLX_FRONT_LEFT_EXT, NULL);
           GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         }
@@ -2088,7 +1515,7 @@ _native_unbind_cb(void *data, void *image)
 
       if (glsym_glXReleaseTexImage)
         {
-          glsym_glXReleaseTexImage(re->win->disp, n->glx_pixmap,
+          glsym_glXReleaseTexImage(re->generic.ob->disp, n->glx_pixmap,
                                    GLX_FRONT_LEFT_EXT);
           GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         }
@@ -2117,13 +1544,13 @@ _native_free_cb(void *data, void *image)
   if (n->ns.type == EVAS_NATIVE_SURFACE_X11)
     {
       pmid = n->pixmap;
-      eina_hash_del(re->win->gl_context->shared->native_pm_hash, &pmid, im);
+      eina_hash_del(re->generic.ob->gl_context->shared->native_pm_hash, &pmid, im);
 #ifdef GL_GLES
       if (n->egl_surface)
         {
           if (glsym_eglDestroyImage)
             {
-              glsym_eglDestroyImage(re->win->egl_disp,
+              glsym_eglDestroyImage(re->generic.ob->egl_disp,
                                     n->egl_surface);
               if (eglGetError() != EGL_SUCCESS)
                 ERR("eglDestroyImage() failed.");
@@ -2139,7 +1566,7 @@ _native_free_cb(void *data, void *image)
             {
               if (glsym_glXReleaseTexImage)
                 {
-                  glsym_glXReleaseTexImage(re->win->disp, n->glx_pixmap,
+                  glsym_glXReleaseTexImage(re->generic.ob->disp, n->glx_pixmap,
                                            GLX_FRONT_LEFT_EXT);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                 }
@@ -2148,7 +1575,7 @@ _native_free_cb(void *data, void *image)
             }
           if (glsym_glXDestroyPixmap)
             {
-              glsym_glXDestroyPixmap(re->win->disp, n->glx_pixmap);
+              glsym_glXDestroyPixmap(re->generic.ob->disp, n->glx_pixmap);
               GLERR(__FUNCTION__, __FILE__, __LINE__, "");
             }
           else
@@ -2161,7 +1588,7 @@ _native_free_cb(void *data, void *image)
   else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
     {
       texid = n->ns.data.opengl.texture_id;
-      eina_hash_del(re->win->gl_context->shared->native_tex_hash, &texid, im);
+      eina_hash_del(re->generic.ob->gl_context->shared->native_tex_hash, &texid, im);
     }
   im->native.data        = NULL;
   im->native.func.data   = NULL;
@@ -2188,7 +1615,7 @@ eng_image_native_set(void *data, void *image, void *native)
     {
        if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_OPENGL))
          {
-            im = evas_gl_common_image_new_from_data(re->win->gl_context,
+            im = evas_gl_common_image_new_from_data(re->generic.ob->gl_context,
                                                     ns->data.opengl.w,
                                                     ns->data.opengl.h,
                                                     NULL, 1,
@@ -2227,7 +1654,7 @@ eng_image_native_set(void *data, void *image, void *native)
     }
   if ((!ns) && (!im->native.data)) return im;
 
-  eng_window_use(re->win);
+  eng_window_use(re->generic.ob);
 
   if (im->native.data)
     {
@@ -2241,7 +1668,7 @@ eng_image_native_set(void *data, void *image, void *native)
   if (ns->type == EVAS_NATIVE_SURFACE_X11)
     {
       pmid = pm;
-      im2 = eina_hash_find(re->win->gl_context->shared->native_pm_hash, &pmid);
+      im2 = eina_hash_find(re->generic.ob->gl_context->shared->native_pm_hash, &pmid);
       if (im2 == im) return im;
       if (im2)
         {
@@ -2257,7 +1684,7 @@ eng_image_native_set(void *data, void *image, void *native)
   else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
     {
        texid = tex;
-       im2 = eina_hash_find(re->win->gl_context->shared->native_tex_hash, &texid);
+       im2 = eina_hash_find(re->generic.ob->gl_context->shared->native_tex_hash, &texid);
        if (im2 == im) return im;
        if (im2)
          {
@@ -2271,7 +1698,7 @@ eng_image_native_set(void *data, void *image, void *native)
          }
 
     }
-  im2 = evas_gl_common_image_new_from_data(re->win->gl_context,
+  im2 = evas_gl_common_image_new_from_data(re->generic.ob->gl_context,
                                            im->w, im->h, NULL, im->alpha,
                                            EVAS_COLORSPACE_ARGB8888);
   evas_gl_common_image_free(im);
@@ -2290,7 +1717,7 @@ eng_image_native_set(void *data, void *image, void *native)
               int num_config, i = 0;
               int yinvert = 1;
 
-              eina_hash_add(re->win->gl_context->shared->native_pm_hash, &pmid, im);
+              eina_hash_add(re->generic.ob->gl_context->shared->native_pm_hash, &pmid, im);
 
               // assume 32bit pixmap! :)
               config_attrs[i++] = EGL_RED_SIZE;
@@ -2311,14 +1738,14 @@ eng_image_native_set(void *data, void *image, void *native)
               config_attrs[i++] = EGL_PIXMAP_BIT;
               config_attrs[i++] = EGL_NONE;
 
-              if (!eglChooseConfig(re->win->egl_disp, config_attrs,
+              if (!eglChooseConfig(re->generic.ob->egl_disp, config_attrs,
                                    &egl_config, 1, &num_config))
                 ERR("eglChooseConfig() failed for pixmap 0x%x, num_config = %i", (unsigned int)pm, num_config);
               else
                 {
                   int val;
                   if (extn_have_y_inverted &&
-                      eglGetConfigAttrib(re->win->egl_disp, egl_config,
+                      eglGetConfigAttrib(re->generic.ob->egl_disp, egl_config,
                                          EGL_Y_INVERTED_NOK, &val))
                         yinvert = val;
                 }
@@ -2327,7 +1754,7 @@ eng_image_native_set(void *data, void *image, void *native)
               n->pixmap = pm;
               n->visual = vis;
               if (glsym_eglCreateImage)
-                n->egl_surface = glsym_eglCreateImage(re->win->egl_disp,
+                n->egl_surface = glsym_eglCreateImage(re->generic.ob->egl_disp,
                                                       EGL_NO_CONTEXT,
                                                       EGL_NATIVE_PIXMAP_KHR,
                                                       (void *)pm,
@@ -2357,7 +1784,7 @@ eng_image_native_set(void *data, void *image, void *native)
             Window wdummy;
             
             // fixme: round trip :(
-            XGetGeometry(re->win->disp, pm, &wdummy, &dummy, &dummy,
+            XGetGeometry(re->generic.ob->disp, pm, &wdummy, &dummy, &dummy,
                          &w, &h, &border, &depth);
             if (depth <= 32)
               {
@@ -2405,8 +1832,8 @@ eng_image_native_set(void *data, void *image, void *native)
                       
                       config_attrs[i++] = 0;
                       
-                      configs = glXChooseFBConfig(re->win->disp,
-                                                  re->win->screen,
+                      configs = glXChooseFBConfig(re->generic.ob->disp,
+                                                  re->generic.ob->screen,
                                                   config_attrs,
                                                   &num);
                       if (configs)
@@ -2420,42 +1847,42 @@ eng_image_native_set(void *data, void *image, void *native)
                                   {
                                      XVisualInfo *vi;
                                      
-                                     vi = glXGetVisualFromFBConfig(re->win->disp, configs[j]);
+                                     vi = glXGetVisualFromFBConfig(re->generic.ob->disp, configs[j]);
                                      if (!vi) continue;
                                      if (vi->depth != (int)depth) continue;
                                      XFree(vi);
                                      
-                                     glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                     glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                           GLX_BUFFER_SIZE, &val);
                                      if (val != (int) depth) continue;
                                   }
-                                glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                      GLX_DRAWABLE_TYPE, &val);
                                 if (!(val & GLX_PIXMAP_BIT)) continue;
                                 tex_format = GLX_TEXTURE_FORMAT_RGB_EXT;
-                                glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                      GLX_ALPHA_SIZE, &val);
                                 if ((depth == 32) && (!val)) continue;
                                 if (val > 0)
                                   {
-                                     glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                     glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                           GLX_BIND_TO_TEXTURE_RGBA_EXT, &val);
                                      if (val) tex_format = GLX_TEXTURE_FORMAT_RGBA_EXT;
                                   }
                                 else
                                   {
-                                     glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                     glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                           GLX_BIND_TO_TEXTURE_RGB_EXT, &val);
                                      if (val) tex_format = GLX_TEXTURE_FORMAT_RGB_EXT;
                                   }
-                                glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                      GLX_Y_INVERTED_EXT, &val);
                                 yinvert = val;
-                                glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                      GLX_BIND_TO_TEXTURE_TARGETS_EXT,
                                                      &val);
                                 tex_target = val;
-                                glXGetFBConfigAttrib(re->win->disp, configs[j],
+                                glXGetFBConfigAttrib(re->generic.ob->disp, configs[j],
                                                      GLX_BIND_TO_MIPMAP_TEXTURE_EXT, &val);
                                 mipmap = val;
                                 n->fbc = configs[j];
@@ -2470,7 +1897,7 @@ eng_image_native_set(void *data, void *image, void *native)
                            XFree(configs);
                         }
                       
-                      eina_hash_add(re->win->gl_context->shared->native_pm_hash, &pmid, im);
+                      eina_hash_add(re->generic.ob->gl_context->shared->native_pm_hash, &pmid, im);
                       if ((tex_target & GLX_TEXTURE_2D_BIT_EXT))
                         target = GLX_TEXTURE_2D_EXT;
                       else if ((tex_target & GLX_TEXTURE_RECTANGLE_BIT_EXT))
@@ -2503,7 +1930,7 @@ eng_image_native_set(void *data, void *image, void *native)
                       n->pixmap = pm;
                       n->visual = vis;
                       if (glsym_glXCreatePixmap)
-                        n->glx_pixmap = glsym_glXCreatePixmap(re->win->disp,
+                        n->glx_pixmap = glsym_glXCreatePixmap(re->generic.ob->disp,
                                                               n->fbc,
                                                               n->pixmap,
                                                               pixmap_att);
@@ -2517,7 +1944,7 @@ eng_image_native_set(void *data, void *image, void *native)
                              {
                                 ERR("no target :(");
                                 if (glsym_glXQueryDrawable)
-                                  glsym_glXQueryDrawable(re->win->disp,
+                                  glsym_glXQueryDrawable(re->generic.ob->disp,
                                                          n->pixmap,
                                                          GLX_TEXTURE_TARGET_EXT,
                                                          &target);
@@ -2544,7 +1971,7 @@ eng_image_native_set(void *data, void *image, void *native)
                       else
                         ERR("GLX Pixmap create fail");
                       im->native.yinvert     = yinvert;
-                      im->native.loose       = re->win->detected.loose_binding;
+                      im->native.loose       = re->generic.ob->detected.loose_binding;
                       im->native.data        = n;
                       im->native.func.data   = re;
                       im->native.func.bind   = _native_bind_cb;
@@ -2567,7 +1994,7 @@ eng_image_native_set(void *data, void *image, void *native)
             {
               memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
 
-              eina_hash_add(re->win->gl_context->shared->native_tex_hash, &texid, im);
+              eina_hash_add(re->generic.ob->gl_context->shared->native_tex_hash, &texid, im);
 
               n->pixmap = 0;
               n->visual = 0;
@@ -2622,8 +2049,8 @@ eng_image_load(void *data, const char *file, const char *key, int *error, Evas_I
 
    re = (Render_Engine *)data;
    *error = EVAS_LOAD_ERROR_NONE;
-   eng_window_use(re->win);
-   return evas_gl_common_image_load(re->win->gl_context, file, key, lo, error);
+   eng_window_use(re->generic.ob);
+   return evas_gl_common_image_load(re->generic.ob->gl_context, file, key, lo, error);
 }
 
 static void *
@@ -2633,8 +2060,8 @@ eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image
 
    re = (Render_Engine *)data;
    *error = EVAS_LOAD_ERROR_NONE;
-   eng_window_use(re->win);
-   return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error);
+   eng_window_use(re->generic.ob);
+   return evas_gl_common_image_mmap(re->generic.ob->gl_context, f, key, lo, error);
 }
 
 static void *
@@ -2643,8 +2070,8 @@ eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha,
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   return evas_gl_common_image_new_from_data(re->win->gl_context, w, h, image_data, alpha, cspace);
+   eng_window_use(re->generic.ob);
+   return evas_gl_common_image_new_from_data(re->generic.ob->gl_context, w, h, image_data, alpha, cspace);
 }
 
 static void *
@@ -2653,8 +2080,8 @@ eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   return evas_gl_common_image_new_from_copied_data(re->win->gl_context, w, h, image_data, alpha, cspace);
+   eng_window_use(re->generic.ob);
+   return evas_gl_common_image_new_from_copied_data(re->generic.ob->gl_context, w, h, image_data, alpha, cspace);
 }
 
 static void
@@ -2664,7 +2091,7 @@ eng_image_free(void *data, void *image)
 
    re = (Render_Engine *)data;
    if (!image) return;
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    evas_gl_common_image_free(image);
 }
 
@@ -2696,7 +2123,7 @@ eng_image_size_set(void *data, void *image, int w, int h)
         im->h = h;
         return image;
      }
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    if ((im->tex) && (im->tex->pt->dyn.img))
      {
         evas_gl_common_texture_free(im->tex, EINA_TRUE);
@@ -2727,13 +2154,13 @@ eng_image_size_set(void *data, void *image, int w, int h)
      return image;
    if (im_old)
      {
-        im = evas_gl_common_image_new(re->win->gl_context, w, h,
+        im = evas_gl_common_image_new(re->generic.ob->gl_context, w, h,
                                       eng_image_alpha_get(data, image),
                                       eng_image_colorspace_get(data, image));
         evas_gl_common_image_free(im_old);
      }
    else
-     im = evas_gl_common_image_new(re->win->gl_context, w, h, 1, EVAS_COLORSPACE_ARGB8888);
+     im = evas_gl_common_image_new(re->generic.ob->gl_context, w, h, 1, EVAS_COLORSPACE_ARGB8888);
    return im;
 }
 
@@ -2746,7 +2173,7 @@ eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h)
    re = (Render_Engine *)data;
    if (!image) return NULL;
    if (im->native.data) return image;
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    evas_gl_common_image_dirty(image, x, y, w, h);
    return image;
 }
@@ -2774,7 +2201,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
      }
 
 #ifdef GL_GLES
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
 
    if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.img) && (im->cs.space == EVAS_COLORSPACE_ARGB8888))
      {
@@ -2785,7 +2212,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
              if (err) *err = EVAS_LOAD_ERROR_NONE;
              return im;
           }
-        *image_data = im->tex->pt->dyn.data = glsym_eglMapImageSEC(re->win->egl_disp, 
+        *image_data = im->tex->pt->dyn.data = glsym_eglMapImageSEC(re->generic.ob->egl_disp, 
                                                                    im->tex->pt->dyn.img, 
                                                                    EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC, 
                                                                    EGL_MAP_GL_TEXTURE_OPTION_WRITE_SEC);
@@ -2809,7 +2236,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
         return im;
      }
 
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
 #endif
 
    /* Engine can be fail to create texture after cache drop like eng_image_content_hint_set function,
@@ -2891,7 +2318,7 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
    if (!image) return NULL;
    im = image;
    if (im->native.data) return image;
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    evas_gl_common_image_alloc_ensure(im);
    if ((im->tex) && (im->tex->pt)
        && (im->tex->pt->dyn.data)
@@ -2904,7 +2331,7 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
                  im->tex->pt->dyn.checked_out--;
 #ifdef GL_GLES
                  if (im->tex->pt->dyn.checked_out == 0)
-                   glsym_eglUnmapImageSEC(re->win->egl_disp, im->tex->pt->dyn.img, EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC);
+                   glsym_eglUnmapImageSEC(re->generic.ob->egl_disp, im->tex->pt->dyn.img, EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC);
 #endif
                }
 
@@ -2973,7 +2400,7 @@ eng_image_data_preload_request(void *data, void *image, const Eo *target)
 #endif
      evas_cache_image_preload_data(&im->cache_entry, target, NULL, NULL, NULL);
    if (!gim->tex)
-     gim->tex = evas_gl_common_texture_new(re->win->gl_context, gim->im);
+     gim->tex = evas_gl_common_texture_new(re->generic.ob->gl_context, gim->im);
    evas_gl_preload_target_register(gim->tex, (Eo*) target);
 }
 
@@ -3014,39 +2441,39 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
      {
         DBG("Rendering Directly to the window: %p", data);
 
-        re->win->gl_context->dc = context;
+        re->generic.ob->gl_context->dc = context;
 
         if (re->func.get_pixels)
           {
-             if ((re->win->gl_context->master_clip.enabled) &&
-                 (re->win->gl_context->master_clip.w > 0) &&
-                 (re->win->gl_context->master_clip.h > 0))
+             if ((re->generic.ob->gl_context->master_clip.enabled) &&
+                 (re->generic.ob->gl_context->master_clip.w > 0) &&
+                 (re->generic.ob->gl_context->master_clip.h > 0))
                {
                   // Pass the preserve flag info the evas_gl
-                  evgl_direct_partial_info_set(re->win->gl_context->preserve_bit);
+                  evgl_direct_partial_info_set(re->generic.ob->gl_context->preserve_bit);
                }
 
              // Set necessary info for direct rendering
-             evgl_direct_info_set(re->win->gl_context->w,
-                                  re->win->gl_context->h,
-                                  re->win->gl_context->rot,
+             evgl_direct_info_set(re->generic.ob->gl_context->w,
+                                  re->generic.ob->gl_context->h,
+                                  re->generic.ob->gl_context->rot,
                                   dst_x, dst_y, dst_w, dst_h,
-                                  re->win->gl_context->dc->clip.x,
-                                  re->win->gl_context->dc->clip.y,
-                                  re->win->gl_context->dc->clip.w,
-                                  re->win->gl_context->dc->clip.h);
+                                  re->generic.ob->gl_context->dc->clip.x,
+                                  re->generic.ob->gl_context->dc->clip.y,
+                                  re->generic.ob->gl_context->dc->clip.w,
+                                  re->generic.ob->gl_context->dc->clip.h);
 
              // Call pixel get function
              re->func.get_pixels(re->func.get_pixels_data, re->func.obj);
 
              // Call end tile if it's being used
-             if ((re->win->gl_context->master_clip.enabled) &&
-                 (re->win->gl_context->master_clip.w > 0) &&
-                 (re->win->gl_context->master_clip.h > 0))
+             if ((re->generic.ob->gl_context->master_clip.enabled) &&
+                 (re->generic.ob->gl_context->master_clip.w > 0) &&
+                 (re->generic.ob->gl_context->master_clip.h > 0))
                {
                   evgl_direct_partial_render_end();
                   evgl_direct_partial_info_clear();
-                  re->win->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
+                  re->generic.ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
                }
 
              // Reset direct rendering info
@@ -3055,10 +2482,10 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
      }
    else
      {
-        eng_window_use(re->win);
-        evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
-        re->win->gl_context->dc = context;
-        evas_gl_common_image_draw(re->win->gl_context, image,
+        eng_window_use(re->generic.ob);
+        evas_gl_common_context_target_surface_set(re->generic.ob->gl_context, surface);
+        re->generic.ob->gl_context->dc = context;
+        evas_gl_common_image_draw(re->generic.ob->gl_context, image,
                                   src_x, src_y, src_w, src_h,
                                   dst_x, dst_y, dst_w, dst_h,
                                   smooth);
@@ -3089,9 +2516,9 @@ eng_image_map_draw(void *data, void *context, void *surface, void *image, RGBA_M
 
    re = (Render_Engine *)data;
    if (!image) return EINA_FALSE;
-   eng_window_use(re->win);
-   evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
-   re->win->gl_context->dc = context;
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_target_surface_set(re->generic.ob->gl_context, surface);
+   re->generic.ob->gl_context->dc = context;
    if (m->count != 4)
      {
         // FIXME: nash - you didn't fix this
@@ -3127,7 +2554,7 @@ eng_image_map_draw(void *data, void *context, void *surface, void *image, RGBA_M
      }
    else
      {
-        evas_gl_common_image_map_draw(re->win->gl_context, image, m->count, &m->pts[0],
+        evas_gl_common_image_map_draw(re->generic.ob->gl_context, image, m->count, &m->pts[0],
                                       smooth, level);
      }
 
@@ -3145,8 +2572,8 @@ eng_image_map_surface_new(void *data, int w, int h, int alpha)
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   return evas_gl_common_image_surface_new(re->win->gl_context, w, h, alpha);
+   eng_window_use(re->generic.ob);
+   return evas_gl_common_image_surface_new(re->generic.ob->gl_context, w, h, alpha);
 }
 
 static void
@@ -3155,7 +2582,7 @@ eng_image_map_surface_free(void *data, void *surface)
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
    evas_gl_common_image_free(surface);
 }
 
@@ -3165,7 +2592,7 @@ eng_image_content_hint_set(void *data, void *image, int hint)
    Render_Engine *re;
    re = (Render_Engine *)data;
 
-   if (re) eng_window_use(re->win);
+   if (re) eng_window_use(re->generic.ob);
    if (image) evas_gl_common_image_content_hint_set(image, hint);
 }
 
@@ -3185,12 +2612,12 @@ eng_image_cache_flush(void *data)
 
    re = (Render_Engine *)data;
 
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
 
    tmp_size = evas_common_image_get_cache();
    evas_common_image_set_cache(0);
    evas_common_rgba_image_scalecache_flush();
-   evas_gl_common_image_cache_flush(re->win->gl_context);
+   evas_gl_common_image_cache_flush(re->generic.ob->gl_context);
    evas_common_image_set_cache(tmp_size);
 }
 
@@ -3201,11 +2628,11 @@ eng_image_cache_set(void *data, int bytes)
 
    re = (Render_Engine *)data;
 
-   eng_window_use(re->win);
+   eng_window_use(re->generic.ob);
 
    evas_common_image_set_cache(bytes);
    evas_common_rgba_image_scalecache_size_set(bytes);
-   evas_gl_common_image_cache_flush(re->win->gl_context);
+   evas_gl_common_image_cache_flush(re->generic.ob->gl_context);
 }
 
 static int
@@ -3255,20 +2682,20 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font EINA
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
-   re->win->gl_context->dc = context;
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_target_surface_set(re->generic.ob->gl_context, surface);
+   re->generic.ob->gl_context->dc = context;
      {
         // FIXME: put im into context so we can free it
         static RGBA_Image *im = NULL;
 
         if (!im)
           im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
-        im->cache_entry.w = re->win->gl_context->shared->w;
-        im->cache_entry.h = re->win->gl_context->shared->h;
+        im->cache_entry.w = re->generic.ob->gl_context->shared->w;
+        im->cache_entry.h = re->generic.ob->gl_context->shared->h;
 
         evas_common_draw_context_font_ext_set(context,
-                                              re->win->gl_context,
+                                              re->generic.ob->gl_context,
                                               evas_gl_font_texture_new,
                                               evas_gl_font_texture_free,
                                               evas_gl_font_texture_draw);
@@ -3288,7 +2715,7 @@ static Eina_Bool
 eng_canvas_alpha_get(void *data, void *info EINA_UNUSED)
 {
    Render_Engine *re = (Render_Engine *)data;
-   return re->win->alpha;
+   return re->generic.ob->alpha;
 }
 
 //--------------------------------//
@@ -3339,13 +2766,13 @@ eng_gl_make_current(void *data, void *surface, void *context)
    EVGLINIT(data, 0);
    if ((sfc) && (ctx))
      {
-        if ((re->win->gl_context->havestuff) ||
-            (re->win->gl_context->master_clip.used))
+        if ((re->generic.ob->gl_context->havestuff) ||
+            (re->generic.ob->gl_context->master_clip.used))
           {
-             eng_window_use(re->win);
-             evas_gl_common_context_flush(re->win->gl_context);
-             if (re->win->gl_context->master_clip.used)
-                evas_gl_common_context_done(re->win->gl_context);
+             eng_window_use(re->generic.ob);
+             evas_gl_common_context_flush(re->generic.ob->gl_context);
+             if (re->generic.ob->gl_context->master_clip.used)
+                evas_gl_common_context_done(re->generic.ob->gl_context);
           }
      }
 
@@ -3603,8 +3030,8 @@ static void
 eng_image_max_size_get(void *data, int *maxw, int *maxh)
 {
    Render_Engine *re = (Render_Engine *)data;
-   if (maxw) *maxw = re->win->gl_context->shared->info.max_texture_size;
-   if (maxh) *maxh = re->win->gl_context->shared->info.max_texture_size;
+   if (maxw) *maxw = re->generic.ob->gl_context->shared->info.max_texture_size;
+   if (maxh) *maxh = re->generic.ob->gl_context->shared->info.max_texture_size;
 }
 
 static Eina_Bool
@@ -3700,13 +3127,13 @@ eng_context_flush(void *data)
    Render_Engine *re;
    re = (Render_Engine *)data;
 
-   if ((re->win->gl_context->havestuff) ||
-     (re->win->gl_context->master_clip.used))
+   if ((re->generic.ob->gl_context->havestuff) ||
+     (re->generic.ob->gl_context->master_clip.used))
    {
-      eng_window_use(re->win);
-      evas_gl_common_context_flush(re->win->gl_context);
-      if (re->win->gl_context->master_clip.used)
-         evas_gl_common_context_done(re->win->gl_context);
+      eng_window_use(re->generic.ob);
+      evas_gl_common_context_flush(re->generic.ob->gl_context);
+      if (re->generic.ob->gl_context->master_clip.used)
+         evas_gl_common_context_done(re->generic.ob->gl_context);
    }
 }
 
@@ -3716,7 +3143,7 @@ eng_context_3d_use(void *data)
    Render_Engine *re = (Render_Engine *)data;
 
    if (!re->context_3d)
-     re->context_3d = eng_gl_context_new(re->win);
+     re->context_3d = eng_gl_context_new(re->generic.ob);
    if (re->context_3d) eng_gl_context_use(re->context_3d);
 }
 
@@ -3781,8 +3208,8 @@ eng_drawable_scene_render(void *data, void *drawable, void *scene_data)
    Render_Engine *re = (Render_Engine *)data;
    E3D_Renderer *renderer = NULL;
 
-   eng_window_use(re->win);
-   evas_gl_common_context_flush(re->win->gl_context);
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_flush(re->generic.ob->gl_context);
 
    eng_context_3d_use(data);
    renderer = eng_renderer_3d_get(data);
@@ -3806,8 +3233,8 @@ eng_texture_data_set(void *data, void *texture, Evas_3D_Color_Format color_forma
                      Evas_3D_Pixel_Format pixel_format, int w, int h, const void *pixels)
 {
    Render_Engine *re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_flush(re->win->gl_context);
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_flush(re->generic.ob->gl_context);
    eng_context_3d_use(data);
 
    e3d_texture_data_set((E3D_Texture *)texture, color_format, pixel_format, w, h, pixels);
@@ -3817,8 +3244,8 @@ static void
 eng_texture_file_set(void *data, void *texture, const char *file, const char *key)
 {
    Render_Engine *re = (Render_Engine *)data;
-   eng_window_use(re->win);
-   evas_gl_common_context_flush(re->win->gl_context);
+   eng_window_use(re->generic.ob);
+   evas_gl_common_context_flush(re->generic.ob->gl_context);
    eng_context_3d_use(data);
 
    e3d_texture_file_set((E3D_Texture *)texture, file, key);
@@ -3894,6 +3321,12 @@ module_open(Evas_Module *em)
         return 0;
      }
 
+   if (partial_render_debug == -1)
+     {
+        if (getenv("EVAS_GL_PARTIAL_DEBUG")) partial_render_debug = 1;
+        else partial_render_debug = 0;
+     }
+
    /* store it for later use */
    func = pfunc;
    /* now to override methods */
@@ -3903,17 +3336,6 @@ module_open(Evas_Module *em)
    ORD(setup);
    ORD(canvas_alpha_get);
    ORD(output_free);
-   ORD(output_resize);
-   ORD(output_tile_size_set);
-   ORD(output_redraws_rect_add);
-   ORD(output_redraws_rect_del);
-   ORD(output_redraws_clear);
-   ORD(output_redraws_next_update_get);
-   ORD(output_redraws_next_update_push);
-   ORD(context_cutout_add);
-   ORD(context_cutout_clear);
-   ORD(output_flush);
-   ORD(output_idle_flush);
    ORD(output_dump);
    ORD(rectangle_draw);
    ORD(line_draw);
index 42d346a..603c715 100644 (file)
@@ -31,6 +31,8 @@
 # include <GL/glx.h>
 #endif
 
+#include "../software_generic/Evas_Engine_Software_Generic.h"
+
 extern int _evas_engine_GL_X11_log_dom ;
 #ifdef ERR
 # undef ERR
@@ -62,20 +64,6 @@ typedef struct _Evas_GL_X11_Context Evas_GL_X11_Context;
 
 struct _Outbuf
 {
-   Display         *disp;
-   Window           win;
-   int              w, h;
-   int              screen;
-   XVisualInfo     *visualinfo;
-   Visual          *visual;
-   Colormap         colormap;
-   int              depth;
-   int              alpha;
-   int              rot;
-   Evas_Engine_GL_Context *gl_context;
-   struct {
-      int           drew : 1;
-   } draw;
 #ifdef GL_GLES
    EGLContext       egl_context[1];
    EGLSurface       egl_surface[1];
@@ -89,7 +77,32 @@ struct _Outbuf
       unsigned int loose_binding : 1;
    } detected;
 #endif
-   int             surf : 1;
+
+   Evas            *evas;
+   Display         *disp;
+   XVisualInfo     *visualinfo;
+   Visual          *visual;
+   Evas_Engine_GL_Context *gl_context;
+   Evas_Engine_Info_GL_X11 *info;
+
+   Render_Engine_Swap_Mode swap_mode;
+   Colormap         colormap;
+   Window           win;
+   int              w, h;
+   int              screen;
+   int              depth;
+   int              alpha;
+   int              rot;
+   int              prev_age;
+   int              frame_cnt;
+   int              vsync;
+
+   unsigned char    lost_back : 1;
+   unsigned char    surf : 1;
+
+   struct {
+      unsigned char drew : 1;
+   } draw;
 };
 
 struct _Evas_GL_X11_Context
@@ -106,10 +119,24 @@ struct _Evas_GL_X11_Context
 #endif
 };
 
-Outbuf *eng_window_new(Display *disp, Window win, int screen,
-                                   Visual *vis, Colormap cmap,
-                                   int depth, int w, int h, int indirect,
-                                   int alpha, int rot);
+extern int extn_have_buffer_age;
+extern int partial_render_debug;
+extern int swap_buffer_debug_mode;
+extern int swap_buffer_debug;
+extern const char *debug_dir;
+
+extern void     (*glsym_glXQueryDrawable)   (Display *a, XID b, int c, unsigned int *d);
+extern void     (*glsym_glXSwapIntervalEXT) (Display *s, GLXDrawable b, int c);
+extern int      (*glsym_glXSwapIntervalSGI) (int a);
+extern int      (*glsym_glXGetVideoSync)    (unsigned int *a);
+extern int      (*glsym_glXWaitVideoSync)   (int a, int b, unsigned int *c);
+
+Outbuf *eng_window_new(Evas_Engine_Info_GL_X11 *info, Evas *e,
+                       Display *disp, Window win, int screen,
+                       Visual *vis, Colormap cmap,
+                       int depth, int w, int h, int indirect,
+                       int alpha, int rot,
+                       Render_Engine_Swap_Mode swap_mode);
 void      eng_window_free(Outbuf *gw);
 void      eng_window_use(Outbuf *gw);
 void      eng_window_unsurf(Outbuf *gw);
@@ -123,4 +150,31 @@ Evas_GL_X11_Context *eng_gl_context_new(Outbuf *win);
 void      eng_gl_context_free(Evas_GL_X11_Context *context);
 void      eng_gl_context_use(Evas_GL_X11_Context *context);
 
+void eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
+int eng_outbuf_get_rot(Outbuf *ob);
+Render_Engine_Swap_Mode eng_outbuf_swap_mode(Outbuf *ob);
+Eina_Bool eng_outbuf_region_first_rect(Outbuf *ob);
+void *eng_outbuf_new_region_for_update(Outbuf *ob,
+                                       int x, int y, int w, int h,
+                                       int *cx, int *cy, int *cw, int *ch);
+void eng_outbuf_push_free_region_for_update(Outbuf *ob, RGBA_Image *update);
+void eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update,
+                                    int x, int y, int w, int h);
+void eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
+
+Eina_Bool eng_preload_make_current(void *data, void *doit);
+
+static inline int
+_re_wincheck(Outbuf *ob)
+{
+   if (ob->surf) return 1;
+   eng_window_resurf(ob);
+   ob->lost_back = 1;
+   if (!ob->surf)
+     {
+        ERR("GL engine can't re-create window surface!");
+     }
+   return 0;
+}
+
 #endif
index b3dc5f5..f4ba440 100644 (file)
@@ -23,7 +23,9 @@ static Colormap     _evas_gl_x11_rgba_cmap = 0;
 static int win_count = 0;
 
 Outbuf *
-eng_window_new(Display *disp,
+eng_window_new(Evas_Engine_Info_GL_X11 *info,
+               Evas *e,
+               Display *disp,
                Window   win,
                int      screen,
                Visual  *vis,
@@ -33,7 +35,8 @@ eng_window_new(Display *disp,
                int      h,
                int      indirect,
                int      alpha,
-               int      rot)
+               int      rot,
+               Render_Engine_Swap_Mode swap_mode)
 {
    Outbuf *gw;
 #ifdef GL_GLES
@@ -62,6 +65,9 @@ eng_window_new(Display *disp,
    gw->w = w;
    gw->h = h;
    gw->rot = rot;
+   gw->swap_mode = swap_mode;
+   gw->info = info;
+   gw->evas = e;
 
    vi_use = _evas_gl_x11_vi;
    if (gw->alpha)
@@ -939,3 +945,305 @@ eng_gl_context_use(Evas_GL_X11_Context *ctx)
      }
 #endif
 }
+
+void
+eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EINA_UNUSED)
+{
+   ob->w = w;
+   ob->h = h;
+   ob->rot = rot;
+   eng_window_use(ob);
+   evas_gl_common_context_resize(ob->gl_context, w, h, rot);
+}
+
+int
+eng_outbuf_get_rot(Outbuf *ob)
+{
+   return ob->rot;
+}
+
+Render_Engine_Swap_Mode
+eng_outbuf_swap_mode(Outbuf *ob)
+{
+   if (ob->swap_mode == MODE_AUTO && extn_have_buffer_age)
+     {
+        Render_Engine_Swap_Mode swap_mode;
+#ifdef GL_GLES
+        EGLint age = 0;
+
+        if (!eglQuerySurface(ob->egl_disp,
+                             ob->egl_surface[0],
+                             EGL_BUFFER_AGE_EXT, &age))
+          age = 0;
+#else
+        unsigned int age = 0;
+
+        if (glsym_glXQueryDrawable)
+          {
+             if (ob->glxwin)
+               glsym_glXQueryDrawable(ob->disp,
+                                      ob->glxwin,
+                                      GLX_BACK_BUFFER_AGE_EXT,
+                                      &age);
+             else
+               glsym_glXQueryDrawable(ob->disp,
+                                      ob->win,
+                                      GLX_BACK_BUFFER_AGE_EXT,
+                                      &age);
+          }
+#endif
+        if (age == 1) swap_mode = MODE_COPY;
+        else if (age == 2) swap_mode = MODE_DOUBLE;
+        else if (age == 3) swap_mode = MODE_TRIPLE;
+        else if (age == 4) swap_mode = MODE_QUADRUPLE;
+        else swap_mode = MODE_FULL;
+        if ((int)age != ob->prev_age) swap_mode = MODE_FULL;
+        ob->prev_age = age;
+
+        return swap_mode;
+     }
+
+   return ob->swap_mode;
+}
+
+Eina_Bool
+eng_outbuf_region_first_rect(Outbuf *ob)
+{
+   ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
+
+   evas_gl_preload_render_lock(eng_preload_make_current, ob);
+#ifdef GL_GLES
+             // dont need to for egl - eng_window_use() can check for other ctxt's
+#else
+   eng_window_use(NULL);
+#endif
+   eng_window_use(ob);
+   if (!_re_wincheck(ob)) return EINA_TRUE;
+
+   evas_gl_common_context_flush(ob->gl_context);
+   evas_gl_common_context_newframe(ob->gl_context);
+   if (partial_render_debug == 1)
+     {
+        glClearColor(0.2, 0.5, 1.0, 1.0);
+        glClear(GL_COLOR_BUFFER_BIT);
+     }
+
+   return EINA_FALSE;
+}
+
+void*
+eng_outbuf_new_region_for_update(Outbuf *ob,
+                                 int x, int y, int w, int h,
+                                 int *cx EINA_UNUSED, int *cy EINA_UNUSED,
+                                 int *cw EINA_UNUSED, int *ch EINA_UNUSED)
+{
+   if (w == ob->w && h == ob->h)
+     {
+        ob->gl_context->master_clip.enabled = EINA_FALSE;
+     }
+   else
+     {
+        ob->gl_context->master_clip.enabled = EINA_TRUE;
+        ob->gl_context->master_clip.x = x;
+        ob->gl_context->master_clip.y = y;
+        ob->gl_context->master_clip.w = w;
+        ob->gl_context->master_clip.h = h;
+     }
+   return ob->gl_context->def_surface;
+}
+
+void
+eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update EINA_UNUSED,
+                               int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
+{
+   /* Is it really necessary to flush per region ? Shouldn't we be able to
+      still do that for the full canvas when doing partial update */
+   if (!_re_wincheck(ob)) return;
+   ob->draw.drew = 1;
+   evas_gl_common_context_flush(ob->gl_context);
+#ifdef GL_GLES
+   // this is needed to make sure all previous rendering is flushed to
+   // buffers/surfaces
+   // previous rendering should be done and swapped
+//xx   if (!safe_native) eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+//   if (eglGetError() != EGL_SUCCESS)
+//     {
+//        printf("Error:  eglWaitNative(EGL_CORE_NATIVE_ENGINE) fail.\n");
+//     }
+#else
+   // previous rendering should be done and swapped
+//xx   if (!safe_native) glXWaitX();
+#endif
+}
+
+void
+eng_outbuf_push_free_region_for_update(Outbuf *ob EINA_UNUSED,
+                                       RGBA_Image *update EINA_UNUSED)
+{
+   /* Nothing to do here as we don't really create an image per area */
+}
+
+void
+eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode)
+{
+   if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
+
+   if (!_re_wincheck(ob)) goto end;
+   if (!ob->draw.drew) goto end;
+
+   ob->draw.drew = 0;
+   eng_window_use(ob);
+   evas_gl_common_context_done(ob->gl_context);
+
+   // Save contents of the framebuffer to a file
+   if (swap_buffer_debug_mode == 1)
+     {
+        if (swap_buffer_debug)
+          {
+             char fname[100];
+             int ret = 0;
+             snprintf(fname, sizeof(fname), "%p", (void*)ob);
+
+             ret = evas_gl_common_buffer_dump(ob->gl_context,
+                                              (const char*)debug_dir,
+                                              (const char*)fname,
+                                              ob->frame_cnt,
+                                              NULL);
+             if (!ret) swap_buffer_debug_mode = 0;
+          }
+     }
+
+#ifdef GL_GLES
+   if (!ob->vsync)
+     {
+        if (ob->info->vsync) eglSwapInterval(ob->egl_disp, 1);
+        else eglSwapInterval(ob->egl_disp, 0);
+        ob->vsync = 1;
+     }
+   if (ob->info->callback.pre_swap)
+     {
+        ob->info->callback.pre_swap(ob->info->callback.data, re->evas);
+     }
+   if ((glsym_eglSwapBuffersWithDamage) && (re->swap_mode != MODE_FULL))
+     {
+        EGLint num = 0, *result = NULL, i = 0;
+        Tilebuf_Rect *r;
+
+        // if partial swaps can be done use re->rects
+        num = eina_inlist_count(EINA_INLIST_GET(rects));
+        if (num > 0)
+          {
+             result = alloca(sizeof(EGLint) * 4 * num);
+             EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
+               {
+                  int gw, gh;
+
+                  gw = ob->gl_context->w;
+                  gh = ob->gl_context->h;
+                  switch (ob->rot)
+                    {
+                     case 0:
+                       result[i + 0] = r->x;
+                       result[i + 1] = gh - (r->y + r->h);
+                       result[i + 2] = r->w;
+                       result[i + 3] = r->h;
+                       break;
+                     case 90:
+                       result[i + 0] = r->y;
+                       result[i + 1] = r->x;
+                       result[i + 2] = r->h;
+                       result[i + 3] = r->w;
+                       break;
+                     case 180:
+                       result[i + 0] = gw - (r->x + r->w);
+                       result[i + 1] = r->y;
+                       result[i + 2] = r->w;
+                       result[i + 3] = r->h;
+                       break;
+                     case 270:
+                       result[i + 0] = gh - (r->y + r->h);
+                       result[i + 1] = gw - (r->x + r->w);
+                       result[i + 2] = r->h;
+                       result[i + 3] = r->w;
+                       break;
+                     default:
+                       result[i + 0] = r->x;
+                       result[i + 1] = gh - (r->y + r->h);
+                       result[i + 2] = r->w;
+                       result[i + 3] = r->h;
+                       break;
+                    }
+                  i += 4;
+               }
+             glsym_eglSwapBuffersWithDamage(ob->egl_disp,
+                                            ob->egl_surface[0],
+                                            rects, num);
+          }
+     }
+   else
+      eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]);
+
+//xx   if (!safe_native) eglWaitGL();
+   if (ob->info->callback.post_swap)
+     {
+        ob->info->callback.post_swap(ob->info->callback.data, ob->evas);
+     }
+//   if (eglGetError() != EGL_SUCCESS)
+//     {
+//        printf("Error:  eglSwapBuffers() fail.\n");
+//     }
+#else
+   (void)rects;
+#ifdef VSYNC_TO_SCREEN
+   if (ob->info->vsync)
+     {
+        if (glsym_glXSwapIntervalEXT)
+          {
+             if (!ob->vsync)
+               {
+                  if (ob->info->vsync) glsym_glXSwapIntervalEXT(ob->disp, ob->win, 1);
+                  else glsym_glXSwapIntervalEXT(ob->disp, ob->win, 0);
+                  ob->vsync = 1;
+               }
+          }
+        else if (glsym_glXSwapIntervalSGI)
+          {
+             if (!ob->vsync)
+               {
+                  if (ob->info->vsync) glsym_glXSwapIntervalSGI(1);
+                  else glsym_glXSwapIntervalSGI(0);
+                  ob->vsync = 1;
+               }
+          }
+        else
+          {
+             if ((glsym_glXGetVideoSync) && (glsym_glXWaitVideoSync))
+               {
+                  unsigned int rc;
+
+                  glsym_glXGetVideoSync(&rc);
+                  glsym_glXWaitVideoSync(1, 0, &rc);
+               }
+          }
+     }
+#endif
+   if (ob->info->callback.pre_swap)
+     {
+        ob->info->callback.pre_swap(ob->info->callback.data, ob->evas);
+     }
+   // XXX: if partial swaps can be done use re->rects
+//   measure(0, "swap");
+   glXSwapBuffers(ob->disp, ob->win);
+//   measure(1, "swap");
+   if (ob->info->callback.post_swap)
+     {
+        ob->info->callback.post_swap(ob->info->callback.data, ob->evas);
+     }
+#endif
+   // clear out rects after swap as we may use them during swap
+
+   ob->frame_cnt++;
+
+ end:
+   evas_gl_preload_render_unlock(eng_preload_make_current, ob);
+}