forked from enlightenment/efl
This series fixes two problems in the VNC implementation.
One deadlock and one segfault.
Patch 1:
Software X11 Evas Engine: Fix deadlock
Summary:
The patch bc6e8d2692
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
This commit is contained in:
parent
094c9091b4
commit
8040d20f90
|
@ -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
|
||||
{
|
||||
//Partial update
|
||||
int dy;
|
||||
const int src_stride = w * VNC_BYTES_PER_PIXEL;
|
||||
|
||||
for (dy = 0; dy < h; dy++)
|
||||
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++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
//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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
void
|
||||
evas_software_xcb_output_buffer_free(Xcb_Output_Buffer *xcbob, Eina_Bool sync)
|
||||
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_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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
void
|
||||
evas_software_xlib_x_output_buffer_free(X_Output_Buffer *xob, int psync)
|
||||
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_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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue