{
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;
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,
_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);
}
}
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));
#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"
# 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
#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;
} 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);
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
/*
}
*/
-
-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)
{
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
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)
{
}
re = e->engine.data.output;
+ _outbufs = eina_list_append(_outbufs, re->generic.ob);
return 1;
}
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);
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
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;
}
}
xcbob->shm_info = NULL;
xcbob->w = w;
xcbob->h = h;
+ xcbob->refcount = 1;
if (try_shm > 0)
{
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);
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);
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);
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);
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;
(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);
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,
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())
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,
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
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();
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;
}
xob->shm_info = NULL;
xob->w = w;
xob->h = h;
+ xob->refcount = 1;
if (try_shm > 0)
{
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);
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);
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);
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
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();
/* 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)
{
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, "
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;
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);
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);
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())
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);