This series fixes two problems in the VNC implementation.
authorGuilherme Iscaro <iscaro@profusion.mobi>
Fri, 21 Oct 2016 04:56:00 +0000 (13:56 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Fri, 21 Oct 2016 04:56:00 +0000 (13:56 +0900)
One deadlock and one segfault.

Patch 1:

Software X11 Evas Engine: Fix deadlock

Summary:
The patch bc6e8d269208 introduced a callback responsible to notify the pixels
that were sent to the X server. Since all EFL rendering is done by another
thread, the callback should be called from the main thread context.
To achieve this behaviour evas_software_x11_region_push_hook_call()
was using ecore_thread_main_loop_begin(), which may cause deadlocks, since
evas mainloop waits for the render thread and the render thread waits
the mainloop.

In order to fix this problem, the function
ecore_main_loop_thread_safe_call_async() will be used to
schedule the callback to run in the main loop context.

Since a callback is schedule to run in async manner, the pixels that
were sent to the X server must not be deleted until the user is informed.
In order to avoid more mallocs(), this patch adds the support for refcounts to the
X_Output_Buffer and Xcb_Output_Buffer.

Patch 2:

Ecore_Evas VNC: Use the image size to create the buffer.

In same cases they may differ and may lead to a segfault, since
memcpy() causes a buffer overrun.

Reviewers: bdilly, raster

Reviewed By: raster

Subscribers: cedric, jpeg

Differential Revision: https://phab.enlightenment.org/D4323

src/modules/ecore_evas/engines/x/ecore_evas_x.c
src/modules/evas/engines/software_x11/evas_engine.c
src/modules/evas/engines/software_x11/evas_engine.h
src/modules/evas/engines/software_x11/evas_xcb_buffer.c
src/modules/evas/engines/software_x11/evas_xcb_buffer.h
src/modules/evas/engines/software_x11/evas_xcb_outbuf.c
src/modules/evas/engines/software_x11/evas_xlib_buffer.c
src/modules/evas/engines/software_x11/evas_xlib_buffer.h
src/modules/evas/engines/software_x11/evas_xlib_outbuf.c

index ac8d1b4..48abefe 100644 (file)
@@ -236,7 +236,9 @@ _ecore_evas_x11_region_push_hook(Evas *e, int x, int y, int w, int h,
 {
    Ecore_Evas *ee;
    Ecore_Evas_Engine_Data_X11 *edata;
-   size_t size;
+   size_t size, src_stride;
+   int dy;
+   Eina_Bool new_buf = EINA_FALSE;
 
    ee = evas_data_attach_get(e);
    edata = ee->engine.data;
@@ -249,10 +251,11 @@ _ecore_evas_x11_region_push_hook(Evas *e, int x, int y, int w, int h,
         new_fb = malloc(size);
         EINA_SAFETY_ON_NULL_RETURN(new_fb);
         free(edata->frame_buffer);
-        memcpy(new_fb, pixels, size);
         edata->frame_buffer = new_fb;
         edata->last_w = ee->w;
         edata->last_h = ee->h;
+        new_buf = EINA_TRUE;
+
         if (edata->vnc_screen)
           {
              rfbNewFramebuffer(edata->vnc_screen, edata->frame_buffer, ee->w,
@@ -261,17 +264,58 @@ _ecore_evas_x11_region_push_hook(Evas *e, int x, int y, int w, int h,
              _ecore_evas_x11_vnc_server_format_setup(edata);
           }
      }
-   else
+
+   if (y > edata->last_h || x > edata->last_w)
+     return;
+
+   //Do not paint outside the VNC canvas
+   if (y + h > edata->last_h)
+     h = edata->last_h - y;
+
+   //Do not paint outside the VNC canvas
+   if (x + w > edata->last_w)
+     w = edata->last_w - x;
+
+   src_stride = w * VNC_BYTES_PER_PIXEL;
+
+   for (dy = 0; dy < h; dy++)
      {
-        //Partial update
-        int dy;
-        const int src_stride = w * VNC_BYTES_PER_PIXEL;
+        memcpy(edata->frame_buffer + (x * VNC_BYTES_PER_PIXEL)
+               + ((dy + y) * (edata->last_w * VNC_BYTES_PER_PIXEL)),
+               (char *)pixels + (dy * src_stride), src_stride);
+     }
 
-        for (dy = 0; dy < h; dy++)
+   //We did not receive the whole buffer yet, zero the missing bytes for now.
+   if (new_buf)
+     {
+        //Missing width
+        if (edata->last_w != w || x != 0)
           {
-             memcpy(edata->frame_buffer + (x * VNC_BYTES_PER_PIXEL)
-                    + ((dy + y) * (edata->last_w * VNC_BYTES_PER_PIXEL)),
-                    (char *)pixels + (dy * src_stride), src_stride);
+             for (dy = 0; dy < h; dy++)
+               {
+                  if (x)
+                    {
+                       memset(edata->frame_buffer
+                              + ((dy + y) * (edata->last_w * VNC_BYTES_PER_PIXEL)),
+                              0, x * VNC_BYTES_PER_PIXEL);
+                    }
+
+                  memset(edata->frame_buffer +
+                         ((dy + y) * (edata->last_w * VNC_BYTES_PER_PIXEL))
+                         + ((x + w) * VNC_BYTES_PER_PIXEL),
+                         0, (edata->last_w - (w + x)) * VNC_BYTES_PER_PIXEL);
+               }
+          }
+
+        //Missing height
+        if (edata->last_h != h || y != 0)
+          {
+             src_stride = edata->last_w * VNC_BYTES_PER_PIXEL;
+             for (dy = 0; dy < y; dy++)
+               memset(edata->frame_buffer + (dy * src_stride), 0, src_stride);
+
+             for (dy = y + h; dy < edata->last_h; dy++)
+               memset(edata->frame_buffer + (dy * src_stride), 0, src_stride);
           }
      }
 
@@ -5347,7 +5391,7 @@ _ecore_evas_x11_vnc_client_connection_new(rfbClientRec *client)
    ee = client->screen->screenData;
    edata = ee->engine.data;
 
-   if (!edata->accept_cb(edata->accept_cb_data, ee, client->host))
+   if (edata->accept_cb && !edata->accept_cb(edata->accept_cb_data, ee, client->host))
      return RFB_CLIENT_REFUSE;
 
    cdata = calloc(1, sizeof(Ecore_Evas_X11_Vnc_Client_Data));
index 08e151f..44ad45e 100644 (file)
@@ -9,6 +9,7 @@
 
 #ifdef BUILD_ENGINE_SOFTWARE_XLIB
 # include "evas_xlib_outbuf.h"
+# include "evas_xlib_buffer.h"
 # include "evas_xlib_swapbuf.h"
 # include "evas_xlib_color.h"
 # include "evas_xlib_image.h"
@@ -20,6 +21,7 @@
 # include "evas_xcb_color.h"
 # include "evas_xcb_xdefaults.h"
 # include "evas_xcb_image.h"
+# include "evas_xcb_buffer.h"
 #endif
 
 #ifdef BUILD_ENGINE_SOFTWARE_XLIB
@@ -33,6 +35,7 @@
 #endif
 
 #include <Ecore.h>
+#include <Eina.h>
 
 Evas_Native_Tbm_Surface_Image_Set_Call  glsym__evas_native_tbm_surface_image_set = NULL;
 Evas_Native_Tbm_Surface_Stride_Get_Call  glsym__evas_native_tbm_surface_stride_get = NULL;
@@ -56,6 +59,22 @@ struct _Render_Engine
    } egl;
 };
 
+typedef struct _Region_Push_Hook_Ctx {
+#ifdef BUILD_ENGINE_SOFTWARE_XLIB
+   X_Output_Buffer *changed_pixels;
+#else
+   Xcb_Output_Buffer *changed_pixels;
+#endif
+   Outbuf *buf;
+   Eina_Spinlock *lock;
+   struct {
+      void (*cb)(Evas *evas, int x, int y, int w, int h, const void *pixels);
+      Evas *evas;
+   } region_push_hook;
+   int x;
+   int y;
+} Region_Push_Hook_Ctx;
+
 /* prototypes we will use here */
 static void *_best_visual_get(int backend, void *connection, int screen);
 static unsigned int _best_colormap_get(int backend, void *connection, int screen);
@@ -66,8 +85,65 @@ static void eng_info_free(Evas *eo_e, void *info);
 static int eng_setup(Evas *eo_e, void *info);
 static void eng_output_free(void *data);
 
+static Eina_List *_outbufs = NULL;
+
 /* internal engine routines */
 
+
+static void
+_evas_software_x11_region_push_hook_call(void *data)
+{
+   Region_Push_Hook_Ctx *ctx = data;
+
+   if (eina_list_data_find(_outbufs, ctx->buf))
+     {
+#ifdef BUILD_ENGINE_SOFTWARE_XLIB
+        ctx->region_push_hook.cb(ctx->region_push_hook.evas, ctx->x, ctx->y,
+                                 ctx->changed_pixels->xim->width,
+                                 ctx->changed_pixels->xim->height,
+                                 evas_software_xlib_x_output_buffer_data(ctx->changed_pixels, NULL));
+        eina_spinlock_take(ctx->lock);
+        evas_software_xlib_x_output_buffer_unref(ctx->changed_pixels, 0);
+        eina_spinlock_release(ctx->lock);
+#else
+        ctx->region_push_hook.cb(ctx->region_push_hook.evas, ctx->x, ctx->y,
+                                 ctx->changed_pixels->xim->width,
+                                 ctx->changed_pixels->xim->height,
+                                 evas_software_xcb_output_buffer_data(ctx->changed_pixels, NULL));
+        eina_spinlock_take(ctx->lock);
+        evas_software_xcb_output_buffer_unref(ctx->changed_pixels, EINA_FALSE);
+        eina_spinlock_release(ctx->lock);
+#endif
+     }
+   free(ctx);
+}
+
+void
+evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, void *out_buf,
+                                        Eina_Spinlock *lock)
+{
+   Region_Push_Hook_Ctx *ctx;
+
+   if (!buf->region_push_hook.cb)
+     return;
+
+   ctx = malloc(sizeof(Region_Push_Hook_Ctx));
+   EINA_SAFETY_ON_NULL_RETURN(ctx);
+   ctx->x = x;
+   ctx->y = y;
+   ctx->region_push_hook.cb = buf->region_push_hook.cb;
+   ctx->region_push_hook.evas = buf->region_push_hook.evas;
+#ifdef BUILD_ENGINE_SOFTWARE_XLIB
+   ctx->changed_pixels = evas_software_xlib_x_output_buffer_ref(out_buf);
+#else
+   ctx->changed_pixels = evas_software_xcb_output_buffer_ref(out_buf);
+#endif
+   ctx->buf = buf;
+   ctx->lock = lock;
+   ecore_main_loop_thread_safe_call_async(_evas_software_x11_region_push_hook_call,
+                                          ctx);
+}
+
 #ifdef BUILD_ENGINE_SOFTWARE_XLIB
 
 /*
@@ -135,23 +211,6 @@ _output_egl_setup(int w, int h, int rot, Display *disp, Drawable draw,
 }
 */
 
-
-void
-evas_software_x11_region_push_hook_call(Outbuf *buf, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED,
-                                        const void *pixels EINA_UNUSED)
-{
-   /* int err; */
-
-   if (!buf->region_push_hook.cb)
-     return;
-/*
-   err = ecore_thread_main_loop_begin();
-   EINA_SAFETY_ON_TRUE_RETURN(err == -1);
-   buf->region_push_hook.cb(buf->region_push_hook.evas, x, y, w, h, pixels);
-   ecore_thread_main_loop_end();
- */
-}
-
 static void
 _output_egl_shutdown(Render_Engine *re)
 {
@@ -563,6 +622,8 @@ eng_setup(Evas *eo_e, void *in)
                                     info->info.mask, info->info.shape_dither,
                                     info->info.destination_alpha);
              re->outbuf_alpha_get = evas_software_xcb_outbuf_alpha_get;
+             re->generic.ob->region_push_hook.cb = info->func.region_push_hook;
+             re->generic.ob->region_push_hook.evas = eo_e;
           }
 #endif
 
@@ -576,6 +637,8 @@ eng_setup(Evas *eo_e, void *in)
         re = e->engine.data.output;
         /* if ((re) && (re->ob)) ponebuf = re->ob->onebuf; */
 
+        _outbufs = eina_list_remove(_outbufs, re->generic.ob);
+
 #ifdef BUILD_ENGINE_SOFTWARE_XLIB
         if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
           {
@@ -656,6 +719,7 @@ eng_setup(Evas *eo_e, void *in)
      }
 
    re = e->engine.data.output;
+   _outbufs =  eina_list_append(_outbufs, re->generic.ob);
 
    return 1;
 }
@@ -667,6 +731,7 @@ eng_output_free(void *data)
 
    if ((re = (Render_Engine *)data))
      {
+        _outbufs = eina_list_remove(_outbufs, re->generic.ob);
         evas_render_engine_software_generic_clean(&re->generic);
 #ifdef BUILD_ENGINE_SOFTWARE_XLIB
         _output_egl_shutdown(re);
index 5999e68..2be0966 100644 (file)
@@ -123,6 +123,6 @@ struct _Outbuf
 void evas_software_xlib_x_init(void);
 void evas_software_xcb_init(void);
 
-void evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, int w, int h, const void *pixels);
+void evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, void *out_buf, Eina_Spinlock *lock);
 
 #endif
index ff90a68..6dbd579 100644 (file)
@@ -243,7 +243,7 @@ evas_software_xcb_can_do_shm(xcb_connection_t *conn, xcb_screen_t *screen)
           cached_result = 0;
         else 
           {
-             evas_software_xcb_output_buffer_free(xcbob, EINA_TRUE);
+             evas_software_xcb_output_buffer_unref(xcbob, EINA_TRUE);
              cached_result = 1;
           }
      }
@@ -267,6 +267,7 @@ evas_software_xcb_output_buffer_new(xcb_connection_t *conn, xcb_visualtype_t *vi
    xcbob->shm_info = NULL;
    xcbob->w = w;
    xcbob->h = h;
+   xcbob->refcount = 1;
 
    if (try_shm > 0) 
      {
@@ -352,9 +353,23 @@ evas_software_xcb_output_buffer_new(xcb_connection_t *conn, xcb_visualtype_t *vi
    return xcbob;
 }
 
+Xcb_Output_Buffer *
+evas_software_xcb_output_buffer_ref(Xcb_Output_Buffer *xcbob)
+{
+   if (xcbob->refcount == UINT_MAX)
+     return NULL;
+   xcbob->refcount++;
+   return xcbob;
+}
+
 void 
-evas_software_xcb_output_buffer_free(Xcb_Output_Buffer *xcbob, Eina_Bool sync) 
+evas_software_xcb_output_buffer_unref(Xcb_Output_Buffer *xcbob, Eina_Bool sync) 
 {
+   if (!xcbob->refcount)
+     return;
+   xcbob->refcount--;
+   if (xcbob->refcount)
+     return;
    if (xcbob->shm_info) 
      {
         if (sync) _xcbob_sync(xcbob->connection);
index dc1f0b4..6e73e5a 100644 (file)
@@ -12,6 +12,7 @@ struct _Xcb_Output_Buffer
    xcb_shm_segment_info_t *shm_info;
    unsigned char *data;
    int w, h, bpl, psize;
+   unsigned int refcount;
 };
 
 void evas_software_xcb_write_mask_line(Outbuf *buf, Xcb_Output_Buffer *xcbob, DATA32 *src, int w, int y);
@@ -20,7 +21,8 @@ void evas_software_xcb_write_mask_line_vert(Outbuf *buf, Xcb_Output_Buffer *xcbo
 void evas_software_xcb_write_mask_line_vert_rev(Outbuf *buf, Xcb_Output_Buffer *xcbob, DATA32 *src, int h, int y, int w);
 Eina_Bool evas_software_xcb_can_do_shm(xcb_connection_t *conn, xcb_screen_t *screen);
 Xcb_Output_Buffer *evas_software_xcb_output_buffer_new(xcb_connection_t *conn, xcb_visualtype_t *vis, int depth, int w, int h, int try_shm, unsigned char *data);
-void evas_software_xcb_output_buffer_free(Xcb_Output_Buffer *xcbob, Eina_Bool sync);
+void evas_software_xcb_output_buffer_unref(Xcb_Output_Buffer *xcbob, Eina_Bool sync);
+Xcb_Output_Buffer *evas_software_xcb_output_buffer_ref(Xcb_Output_Buffer *xcbob);
 void evas_software_xcb_output_buffer_paste(Xcb_Output_Buffer *xcbob, xcb_drawable_t drawable, xcb_gcontext_t gc, int x, int y, Eina_Bool sync);
 DATA8 *evas_software_xcb_output_buffer_data(Xcb_Output_Buffer *xcbob, int *bpl_ret);
 int evas_software_xcb_output_buffer_depth(Xcb_Output_Buffer *xcbob);
index b376600..dd8af98 100644 (file)
@@ -139,7 +139,7 @@ evas_software_xcb_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, xcb_co
         return NULL;
      }
    buf->priv.x11.xcb.imdepth = evas_software_xcb_output_buffer_depth(xob);
-   evas_software_xcb_output_buffer_free(xob, EINA_FALSE);
+   evas_software_xcb_output_buffer_unref(xob, EINA_FALSE);
    
    eina_array_step_set(&buf->priv.onebuf_regions, sizeof(Eina_Array), 8);
 
@@ -368,7 +368,7 @@ evas_software_xcb_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w,
 
              if (!im) 
                {
-                  evas_software_xcb_output_buffer_free(obr->xcbob, EINA_FALSE);
+                  evas_software_xcb_output_buffer_unref(obr->xcbob, EINA_FALSE);
                   free(obr);
                   eina_spinlock_release(&(buf->priv.lock));
                   return NULL;
@@ -681,9 +681,8 @@ evas_software_xcb_outbuf_flush(Outbuf *buf, Tilebuf_Rect *surface_damage EINA_UN
                                 (const xcb_rectangle_t *)pixman_region_rectangles(&tmpr, NULL));
         if (obr->xcbob)
           {
-             evas_software_x11_region_push_hook_call(buf, 0, 0, obr->xcbob->xim->width,
-                                                     obr->xcbob->xim->height,
-                                                     evas_software_xcb_output_buffer_data(obr->xcbob, NULL));
+             evas_software_x11_region_push_hook_call(buf, 0, 0, obr->xcbob,
+                                                     &shmpool_lock);
              evas_software_xcb_output_buffer_paste(obr->xcbob,
                                                    buf->priv.x11.xcb.win,
                                                    buf->priv.x11.xcb.gc, 0, 0, 0);
@@ -716,9 +715,8 @@ evas_software_xcb_outbuf_flush(Outbuf *buf, Tilebuf_Rect *surface_damage EINA_UN
              if (obr->xcbob)
                {
                   evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
-                                                          obr->xcbob->xim->width,
-                                                          obr->xcbob->xim->height,
-                                                          evas_software_xcb_output_buffer_data(obr->xcbob, NULL));
+                                                          obr->xcbob,
+                                                          &shmpool_lock);
                   evas_software_xcb_output_buffer_paste(obr->xcbob,
                                                         buf->priv.x11.xcb.win,
                                                         buf->priv.x11.xcb.gc,
@@ -796,10 +794,18 @@ evas_software_xcb_outbuf_idle_flush(Outbuf *buf)
         im = buf->priv.onebuf;
         buf->priv.onebuf = NULL;
         obr = im->extended_info;
-        if (obr->xcbob) 
-          evas_software_xcb_output_buffer_free(obr->xcbob, EINA_FALSE);
-        if (obr->mask) 
-          evas_software_xcb_output_buffer_free(obr->mask, EINA_FALSE);
+        if (obr->xcbob)
+          {
+             SHMPOOL_LOCK();
+             evas_software_xcb_output_buffer_unref(obr->xcbob, EINA_FALSE);
+             SHMPOOL_UNLOCK();
+          }
+        if (obr->mask)
+          {
+             SHMPOOL_LOCK();
+             evas_software_xcb_output_buffer_unref(obr->mask, EINA_FALSE);
+             SHMPOOL_UNLOCK();
+          }
         free(obr);
 # ifdef EVAS_CSERVE2
         if (evas_cserve2_use_get())
@@ -972,9 +978,8 @@ evas_software_xcb_outbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, in
         if (obr->xcbob)
           {
              evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
-                                                     obr->xcbob->xim->width,
-                                                     obr->xcbob->xim->height,
-                                                     evas_software_xcb_output_buffer_data(obr->xcbob, NULL));
+                                                     obr->xcbob,
+                                                     &shmpool_lock);
              evas_software_xcb_output_buffer_paste(obr->xcbob,
                                                    buf->priv.x11.xcb.win,
                                                    buf->priv.x11.xcb.gc,
@@ -1269,12 +1274,16 @@ _unfind_xcbob(Xcb_Output_Buffer *xcbob, Eina_Bool sync)
              xcbob = xl->data;
              _shmpool = eina_list_remove_list(_shmpool, xl);
              _shmsize -= xcbob->psize * xcbob->xim->depth / 8;
-             evas_software_xcb_output_buffer_free(xcbob, sync);
+             evas_software_xcb_output_buffer_unref(xcbob, sync);
           }
         SHMPOOL_UNLOCK();
      }
    else
-     evas_software_xcb_output_buffer_free(xcbob, sync);
+     {
+        SHMPOOL_LOCK();
+        evas_software_xcb_output_buffer_unref(xcbob, sync);
+        SHMPOOL_UNLOCK();
+     }
 }
 
 static void 
@@ -1287,7 +1296,7 @@ _clear_xcbob(Eina_Bool sync)
  
         xcbob = _shmpool->data;
         _shmpool = eina_list_remove_list(_shmpool, _shmpool);
-        evas_software_xcb_output_buffer_free(xcbob, sync);
+        evas_software_xcb_output_buffer_unref(xcbob, sync);
      }
    _shmsize = 0;
    SHMPOOL_UNLOCK();
index 6ab1278..b88571d 100644 (file)
@@ -244,7 +244,7 @@ evas_software_xlib_x_can_do_shm(Display *d)
             cached_result = 0;
             return 0;
          }
-       evas_software_xlib_x_output_buffer_free(xob, 1);
+       evas_software_xlib_x_output_buffer_unref(xob, 1);
        cached_result = 1;
        return 1;
      }
@@ -275,6 +275,7 @@ evas_software_xlib_x_output_buffer_new(Display *d, Visual *v, int depth, int w,
    xob->shm_info = NULL;
    xob->w = w;
    xob->h = h;
+   xob->refcount = 1;
 
    if (try_shm > 0)
      {
@@ -370,9 +371,23 @@ evas_software_xlib_x_output_buffer_new(Display *d, Visual *v, int depth, int w,
    return xob;
 }
 
+X_Output_Buffer *
+evas_software_xlib_x_output_buffer_ref(X_Output_Buffer *xob)
+{
+   if (xob->refcount == UINT_MAX)
+     return NULL;
+   xob->refcount++;
+   return xob;
+}
+
 void
-evas_software_xlib_x_output_buffer_free(X_Output_Buffer *xob, int psync)
+evas_software_xlib_x_output_buffer_unref(X_Output_Buffer *xob, int psync)
 {
+   if (!xob->refcount)
+     return;
+   xob->refcount--;
+   if (xob->refcount)
+     return;
    if (xob->shm_info)
      {
        if (psync) XSync(xob->display, False);
index 01c4db0..703ddcb 100644 (file)
@@ -18,6 +18,7 @@ struct _X_Output_Buffer
    int              h;
    int              bpl;
    int              psize;
+   unsigned int     refcount;
 };
 
 void evas_software_xlib_x_write_mask_line               (Outbuf *buf, X_Output_Buffer *xob, DATA32 *src, int w, int y);
@@ -29,7 +30,9 @@ int evas_software_xlib_x_can_do_shm                     (Display *d);
 
 X_Output_Buffer *evas_software_xlib_x_output_buffer_new (Display *d, Visual *v, int depth, int w, int h, int try_shm, void *data);
 
-void evas_software_xlib_x_output_buffer_free            (X_Output_Buffer *xob, int sync);
+void evas_software_xlib_x_output_buffer_unref            (X_Output_Buffer *xob, int sync);
+
+X_Output_Buffer *evas_software_xlib_x_output_buffer_ref(X_Output_Buffer *xob);
 
 void evas_software_xlib_x_output_buffer_paste           (X_Output_Buffer *xob, Drawable d, GC gc, int x, int y, int sync);
 
index 0fb671c..ce83881 100644 (file)
@@ -124,12 +124,16 @@ _unfind_xob(X_Output_Buffer *xob, int psync)
             xob = xl->data;
              shmpool = eina_list_remove_list(shmpool, xl);
              shmsize -= xob->psize * xob->xim->depth / 8;
-            evas_software_xlib_x_output_buffer_free(xob, psync);
+            evas_software_xlib_x_output_buffer_unref(xob, psync);
          }
         SHMPOOL_UNLOCK();
      }
    else
-     evas_software_xlib_x_output_buffer_free(xob, psync);
+     {
+        SHMPOOL_LOCK();
+        evas_software_xlib_x_output_buffer_unref(xob, psync);
+        SHMPOOL_UNLOCK();
+     }
 }
 
 static void
@@ -142,7 +146,7 @@ _clear_xob(int psync)
 
        xob = shmpool->data;
        shmpool = eina_list_remove_list(shmpool, shmpool);
-       evas_software_xlib_x_output_buffer_free(xob, psync);
+       evas_software_xlib_x_output_buffer_unref(xob, psync);
      }
    shmsize = 0;
    SHMPOOL_UNLOCK();
@@ -318,12 +322,12 @@ evas_software_xlib_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
                /* FIXME: only alloc once per display+cmap */
                buf->priv.pal = evas_software_xlib_x_color_allocate(disp, cmap, vis,
                                                                    pm);
-               if (!buf->priv.pal)
-                 {
-                     if (xob) evas_software_xlib_x_output_buffer_free(xob, 1);
-                    free(buf);
-                    return NULL;
-                 }
+                if (!buf->priv.pal)
+                  {
+                     if (xob) evas_software_xlib_x_output_buffer_unref(xob, 1);
+                     free(buf);
+                     return NULL;
+                  }
             }
           if (buf->priv.pal)
             {
@@ -362,7 +366,7 @@ evas_software_xlib_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
                                                             buf->rot);
             }
            buf->priv.x11.xlib.imdepth = evas_software_xlib_x_output_buffer_depth(xob);
-           evas_software_xlib_x_output_buffer_free(xob, 1);
+           evas_software_xlib_x_output_buffer_unref(xob, 1);
           if (!conv_func)
             {
                 ERR("At depth: %i, RGB format mask: %08x %08x %08x, "
@@ -479,7 +483,7 @@ evas_software_xlib_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w
                                                         alpha, EVAS_COLORSPACE_ARGB8888);
              if (!im)
                {
-                  evas_software_xlib_x_output_buffer_free(obr->xob, 0);
+                  evas_software_xlib_x_output_buffer_unref(obr->xob, 0);
                   free(obr);
                   eina_spinlock_release(&(buf->priv.lock));
                   return NULL;
@@ -819,9 +823,8 @@ evas_software_xlib_outbuf_flush(Outbuf *buf, Tilebuf_Rect *surface_damage EINA_U
        XSetRegion(buf->priv.x11.xlib.disp, buf->priv.x11.xlib.gc, tmpr);
         if (obr->xob)
           {
-             evas_software_x11_region_push_hook_call(buf, 0, 0, obr->xob->xim->width,
-                                                     obr->xob->xim->height,
-                                                     evas_software_xlib_x_output_buffer_data(obr->xob, NULL));
+             evas_software_x11_region_push_hook_call(buf, 0, 0, obr->xob,
+                                                     &shmpool_lock);
              evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
                                                       buf->priv.x11.xlib.gc,
                                                       0, 0, 0);
@@ -850,9 +853,7 @@ evas_software_xlib_outbuf_flush(Outbuf *buf, Tilebuf_Rect *surface_damage EINA_U
              if (obr->xob)
                {
                   evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
-                                                          obr->xob->xim->width,
-                                                          obr->xob->xim->height,
-                                                          evas_software_xlib_x_output_buffer_data(obr->xob, NULL));
+                                                          obr->xob, &shmpool_lock);
                   evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
                                                            buf->priv.x11.xlib.gc,
                                                            obr->x, obr->y, 0);
@@ -952,8 +953,18 @@ evas_software_xlib_outbuf_idle_flush(Outbuf *buf)
        im = buf->priv.onebuf;
        buf->priv.onebuf = NULL;
        obr = im->extended_info;
-       if (obr->xob) evas_software_xlib_x_output_buffer_free(obr->xob, 0);
-       if (obr->mxob) evas_software_xlib_x_output_buffer_free(obr->mxob, 0);
+        if (obr->xob)
+          {
+             SHMPOOL_LOCK();
+             evas_software_xlib_x_output_buffer_unref(obr->xob, 0);
+             SHMPOOL_UNLOCK();
+          }
+        if (obr->mxob)
+          {
+             SHMPOOL_LOCK();
+             evas_software_xlib_x_output_buffer_unref(obr->mxob, 0);
+             SHMPOOL_UNLOCK();
+          }
        free(obr);
 #ifdef EVAS_CSERVE2
         if (evas_cserve2_use_get())
@@ -1137,9 +1148,7 @@ evas_software_xlib_outbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, i
         if (obr->xob)
           {
              evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
-                                                     obr->xob->xim->width,
-                                                     obr->xob->xim->height,
-                                                     evas_software_xlib_x_output_buffer_data(obr->xob, NULL));
+                                                     obr->xob, &shmpool_lock);
              evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
                                                       buf->priv.x11.xlib.gc,
                                                       obr->x, obr->y, 0);