forked from enlightenment/efl
Merge branch 'devs/devilhorns/evas_wayland_shm'
This merge pulls in the Evas Wayland Shm engine refactor which addressed resize issues causing crashes in E wl compositor.
This commit is contained in:
commit
d54591720e
|
@ -1179,10 +1179,8 @@ WAYLAND_SHM_SOURCES = \
|
|||
modules/evas/engines/wayland_shm/Evas_Engine_Wayland_Shm.h \
|
||||
modules/evas/engines/wayland_shm/evas_engine.c \
|
||||
modules/evas/engines/wayland_shm/evas_engine.h \
|
||||
modules/evas/engines/wayland_shm/evas_swapbuf.c \
|
||||
modules/evas/engines/wayland_shm/evas_swapbuf.h \
|
||||
modules/evas/engines/wayland_shm/evas_swapper.c \
|
||||
modules/evas/engines/wayland_shm/evas_swapper.h
|
||||
modules/evas/engines/wayland_shm/evas_shm.c \
|
||||
modules/evas/engines/wayland_shm/evas_outbuf.c
|
||||
if EVAS_STATIC_BUILD_WAYLAND_SHM
|
||||
lib_evas_libevas_la_SOURCES += $(WAYLAND_SHM_SOURCES)
|
||||
lib_evas_libevas_la_CPPFLAGS += @evas_engine_wayland_shm_cflags@
|
||||
|
|
|
@ -46,15 +46,6 @@ static void _ecore_evas_wayland_alpha_do(Ecore_Evas *ee, int alpha);
|
|||
static void _ecore_evas_wayland_transparent_do(Ecore_Evas *ee, int transparent);
|
||||
static void _ecore_evas_wl_common_border_update(Ecore_Evas *ee);
|
||||
|
||||
/* Frame listener */
|
||||
static void _ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t tm);
|
||||
|
||||
/* Frame listener */
|
||||
static const struct wl_callback_listener frame_listener =
|
||||
{
|
||||
_ecore_evas_wl_frame_complete,
|
||||
};
|
||||
|
||||
/* local functions */
|
||||
static void
|
||||
_ecore_evas_wl_common_state_update(Ecore_Evas *ee)
|
||||
|
@ -592,8 +583,6 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee)
|
|||
|
||||
if (!ee) return;
|
||||
wdata = ee->engine.data;
|
||||
if (wdata->frame_callback) wl_callback_destroy(wdata->frame_callback);
|
||||
wdata->frame_callback = NULL;
|
||||
if (wdata->win) ecore_wl_window_free(wdata->win);
|
||||
wdata->win = NULL;
|
||||
free(wdata);
|
||||
|
@ -1441,42 +1430,6 @@ _ecore_evas_wl_common_post_render(Ecore_Evas *ee)
|
|||
if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_evas_wl_common_frame_callback_clean(Ecore_Evas *ee)
|
||||
{
|
||||
Ecore_Evas_Engine_Wl_Data *wdata;
|
||||
|
||||
wdata = ee->engine.data;
|
||||
|
||||
if (!wdata->frame_pending)
|
||||
return;
|
||||
wl_callback_destroy(wdata->frame_callback);
|
||||
wdata->frame_callback = NULL;
|
||||
wdata->frame_pending = EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback EINA_UNUSED, uint32_t tm EINA_UNUSED)
|
||||
{
|
||||
Ecore_Evas *ee = data;
|
||||
Ecore_Wl_Window *win = NULL;
|
||||
Ecore_Evas_Engine_Wl_Data *wdata;
|
||||
|
||||
if (!ee) return;
|
||||
|
||||
_ecore_evas_wl_common_frame_callback_clean(ee);
|
||||
|
||||
wdata = ee->engine.data;
|
||||
if (!(win = wdata->win)) return;
|
||||
|
||||
if (ecore_wl_window_surface_get(win))
|
||||
{
|
||||
wdata->frame_callback =
|
||||
wl_surface_frame(ecore_wl_window_surface_get(win));
|
||||
wl_callback_add_listener(wdata->frame_callback, &frame_listener, ee);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
_ecore_evas_wl_common_render(Ecore_Evas *ee)
|
||||
{
|
||||
|
@ -1516,20 +1469,6 @@ _ecore_evas_wl_common_render(Ecore_Evas *ee)
|
|||
updates = evas_render_updates(ee->evas);
|
||||
rend = _ecore_evas_wl_common_render_updates_process(ee, updates);
|
||||
evas_render_updates_free(updates);
|
||||
|
||||
if (!wdata->frame_pending)
|
||||
{
|
||||
if (!wdata->frame_callback)
|
||||
{
|
||||
wdata->frame_callback =
|
||||
wl_surface_frame(ecore_wl_window_surface_get(win));
|
||||
wl_callback_add_listener(wdata->frame_callback,
|
||||
&frame_listener, ee);
|
||||
}
|
||||
|
||||
if (rend)
|
||||
wdata->frame_pending = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
else if (evas_render_async(ee->evas))
|
||||
{
|
||||
|
|
|
@ -373,7 +373,6 @@ _ecore_evas_wl_hide(Ecore_Evas *ee)
|
|||
if (!ee->visible) return;
|
||||
ee->visible = 0;
|
||||
ee->should_be_visible = 0;
|
||||
_ecore_evas_wl_common_frame_callback_clean(ee);
|
||||
|
||||
if (ee->func.fn_hide) ee->func.fn_hide(ee);
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ struct _Ecore_Evas_Engine_Wl_Data
|
|||
#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
|
||||
struct wl_egl_window *egl_win;
|
||||
#endif
|
||||
Eina_Bool frame_pending : 1;
|
||||
struct wl_callback *frame_callback;
|
||||
};
|
||||
|
||||
Ecore_Evas_Interface_Wayland *_ecore_evas_wl_interface_new(void);
|
||||
|
|
|
@ -366,7 +366,6 @@ _ecore_evas_wl_hide(Ecore_Evas *ee)
|
|||
if (!ee->visible) return;
|
||||
ee->visible = 0;
|
||||
ee->should_be_visible = 0;
|
||||
_ecore_evas_wl_common_frame_callback_clean(ee);
|
||||
|
||||
if (ee->func.fn_hide) ee->func.fn_hide(ee);
|
||||
}
|
||||
|
|
|
@ -1,171 +1,156 @@
|
|||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
#include "Evas_Engine_Wayland_Shm.h"
|
||||
#ifdef EVAS_CSERVE2
|
||||
# include "evas_cs2_private.h"
|
||||
#endif
|
||||
|
||||
#include "evas_engine.h"
|
||||
#include "evas_swapbuf.h"
|
||||
|
||||
/* local structures */
|
||||
/* logging domain variable */
|
||||
int _evas_engine_way_shm_log_dom = -1;
|
||||
|
||||
/* evas function tables - filled in later (func and parent func) */
|
||||
static Evas_Func func, pfunc;
|
||||
|
||||
/* engine structure data */
|
||||
typedef struct _Render_Engine Render_Engine;
|
||||
|
||||
struct _Render_Engine
|
||||
{
|
||||
Render_Engine_Software_Generic generic;
|
||||
|
||||
void (*outbuf_reconfigure)(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha);
|
||||
void (*outbuf_reconfigure)(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize);
|
||||
};
|
||||
|
||||
/* engine function prototypes */
|
||||
static void *eng_info(Evas *eo_evas EINA_UNUSED);
|
||||
static void eng_info_free(Evas *eo_evas EINA_UNUSED, void *einfo);
|
||||
static int eng_setup(Evas *eo_evas, void *einfo);
|
||||
static void eng_output_free(void *data);
|
||||
|
||||
/* local variables */
|
||||
static Evas_Func func, pfunc;
|
||||
|
||||
/* external variables */
|
||||
int _evas_engine_way_shm_log_dom = -1;
|
||||
|
||||
/* local functions */
|
||||
static void *
|
||||
_output_engine_setup(Evas_Engine_Info_Wayland_Shm *info,
|
||||
int w, int h,
|
||||
unsigned int rotation, unsigned int depth,
|
||||
Eina_Bool destination_alpha,
|
||||
struct wl_shm *wl_shm,
|
||||
struct wl_surface *wl_surface)
|
||||
/* LOCAL FUNCTIONS */
|
||||
Render_Engine *
|
||||
_render_engine_swapbuf_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha, struct wl_shm *shm, struct wl_surface *surface)
|
||||
{
|
||||
Render_Engine *re = NULL;
|
||||
Render_Engine *re;
|
||||
Outbuf *ob;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to allocate a new render engine */
|
||||
if (!(re = calloc(1, sizeof(Render_Engine))))
|
||||
return NULL;
|
||||
/* try to allocate space for new render engine */
|
||||
if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
|
||||
|
||||
ob = _evas_outbuf_setup(w, h, rotation, depth, alpha, shm, surface);
|
||||
if (!ob) goto err;
|
||||
|
||||
ob = evas_swapbuf_setup(info, w, h, rotation, depth,
|
||||
destination_alpha, wl_shm,
|
||||
wl_surface);
|
||||
if (!ob) goto on_error;
|
||||
|
||||
if (!evas_render_engine_software_generic_init(&re->generic, ob,
|
||||
evas_swapbuf_state_get,
|
||||
evas_swapbuf_rotation_get,
|
||||
if (!evas_render_engine_software_generic_init(&re->generic, ob,
|
||||
_evas_outbuf_swapmode_get,
|
||||
_evas_outbuf_rotation_get,
|
||||
NULL,
|
||||
NULL,
|
||||
evas_swapbuf_update_region_new,
|
||||
evas_swapbuf_update_region_push,
|
||||
evas_swapbuf_update_region_free,
|
||||
evas_swapbuf_idle_flush,
|
||||
evas_swapbuf_flush,
|
||||
evas_swapbuf_free,
|
||||
NULL,
|
||||
_evas_outbuf_update_region_new,
|
||||
_evas_outbuf_update_region_push,
|
||||
_evas_outbuf_update_region_free,
|
||||
_evas_outbuf_idle_flush,
|
||||
_evas_outbuf_flush,
|
||||
_evas_outbuf_free,
|
||||
w, h))
|
||||
goto on_error;
|
||||
goto err;
|
||||
|
||||
re->outbuf_reconfigure = evas_swapbuf_reconfigure;
|
||||
re->outbuf_reconfigure = _evas_outbuf_reconfigure;
|
||||
|
||||
/* return allocated render engine */
|
||||
return re;
|
||||
|
||||
on_error:
|
||||
if (ob) evas_swapbuf_free(ob);
|
||||
err:
|
||||
if (ob) _evas_outbuf_free(ob);
|
||||
free(re);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* engine functions */
|
||||
/* ENGINE API FUNCTIONS WE PROVIDE */
|
||||
static void *
|
||||
eng_info(Evas *eo_evas EINA_UNUSED)
|
||||
{
|
||||
Evas_Engine_Info_Wayland_Shm *info;
|
||||
Evas_Engine_Info_Wayland_Shm *einfo;
|
||||
|
||||
/* try to allocate space for engine info */
|
||||
if (!(info = calloc(1, sizeof(Evas_Engine_Info_Wayland_Shm))))
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to allocate space for new engine info */
|
||||
if (!(einfo = calloc(1, sizeof(Evas_Engine_Info_Wayland_Shm))))
|
||||
return NULL;
|
||||
|
||||
/* fill in default engine info fields */
|
||||
info->magic.magic = rand();
|
||||
info->render_mode = EVAS_RENDER_MODE_BLOCKING;
|
||||
/* fill in engine info */
|
||||
einfo->magic.magic = rand();
|
||||
einfo->render_mode = EVAS_RENDER_MODE_BLOCKING;
|
||||
|
||||
/* return allocated engine info */
|
||||
return info;
|
||||
return einfo;
|
||||
}
|
||||
|
||||
static void
|
||||
eng_info_free(Evas *eo_evas EINA_UNUSED, void *einfo)
|
||||
eng_info_free(Evas *eo_evas EINA_UNUSED, void *info)
|
||||
{
|
||||
Evas_Engine_Info_Wayland_Shm *info;
|
||||
Evas_Engine_Info_Wayland_Shm *einfo;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to free previously allocated engine info */
|
||||
if ((info = (Evas_Engine_Info_Wayland_Shm *)einfo))
|
||||
free(info);
|
||||
if ((einfo = (Evas_Engine_Info_Wayland_Shm *)info))
|
||||
free(einfo);
|
||||
}
|
||||
|
||||
static int
|
||||
eng_setup(Evas *eo_evas, void *einfo)
|
||||
eng_setup(Evas *eo_evas, void *info)
|
||||
{
|
||||
Evas_Engine_Info_Wayland_Shm *info;
|
||||
Evas_Engine_Info_Wayland_Shm *einfo;
|
||||
Evas_Public_Data *epd;
|
||||
Render_Engine *re = NULL;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to cast the engine info to our engine info */
|
||||
if (!(info = (Evas_Engine_Info_Wayland_Shm *)einfo))
|
||||
/* try to cast to our engine info */
|
||||
if (!(einfo = (Evas_Engine_Info_Wayland_Shm *)info))
|
||||
return 0;
|
||||
|
||||
/* try to get evas public data from the canvas */
|
||||
/* try to get evas public data */
|
||||
if (!(epd = eo_data_scope_get(eo_evas, EVAS_CANVAS_CLASS)))
|
||||
return 0;
|
||||
|
||||
/* test for valid engine output */
|
||||
if (!(re = epd->engine.data.output))
|
||||
{
|
||||
static int try_swap = -1;
|
||||
|
||||
/* NB: If we have no valid output then assume we have not been
|
||||
* initialized yet and call any needed common init routines */
|
||||
/* if we have no engine data, assume we have not initialized yet */
|
||||
evas_common_init();
|
||||
|
||||
if (try_swap == -1)
|
||||
{
|
||||
/* check for env var to see if we should try swapping */
|
||||
if (getenv("EVAS_NO_WAYLAND_SWAPBUF")) try_swap = 0;
|
||||
else try_swap = 1;
|
||||
}
|
||||
re = _render_engine_swapbuf_setup(epd->output.w, epd->output.h,
|
||||
einfo->info.rotation,
|
||||
einfo->info.depth,
|
||||
einfo->info.destination_alpha,
|
||||
einfo->info.wl_shm,
|
||||
einfo->info.wl_surface);
|
||||
|
||||
if (!(re =
|
||||
_output_engine_setup(info, epd->output.w, epd->output.h,
|
||||
info->info.rotation, info->info.depth,
|
||||
info->info.destination_alpha,
|
||||
info->info.wl_shm, info->info.wl_surface)))
|
||||
return 0;
|
||||
}
|
||||
if (re)
|
||||
re->generic.ob->info = einfo;
|
||||
else
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
Outbuf *ob;
|
||||
int ponebuf = 0;
|
||||
|
||||
if ((re) && (re->generic.ob)) ponebuf = re->generic.ob->onebuf;
|
||||
|
||||
ob = evas_swapbuf_setup(info, epd->output.w, epd->output.h,
|
||||
info->info.rotation,
|
||||
info->info.depth,
|
||||
info->info.destination_alpha,
|
||||
info->info.wl_shm,
|
||||
info->info.wl_surface);
|
||||
if (!ob) return 0;
|
||||
|
||||
evas_render_engine_software_generic_update(&re->generic, ob, epd->output.w, epd->output.h);
|
||||
|
||||
if ((re) && (re->generic.ob)) re->generic.ob->onebuf = ponebuf;
|
||||
ob = _evas_outbuf_setup(epd->output.w, epd->output.h,
|
||||
einfo->info.rotation, einfo->info.depth,
|
||||
einfo->info.destination_alpha,
|
||||
einfo->info.wl_shm, einfo->info.wl_surface);
|
||||
if (ob)
|
||||
{
|
||||
ob->info = einfo;
|
||||
evas_render_engine_software_generic_update(&re->generic, ob,
|
||||
epd->output.w,
|
||||
epd->output.h);
|
||||
}
|
||||
}
|
||||
|
||||
/* reassign render engine to output */
|
||||
epd->engine.data.output = re;
|
||||
if (!epd->engine.data.output) return 0;
|
||||
if (!epd->engine.data.output)
|
||||
{
|
||||
ERR("Failed to create Render Engine");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!epd->engine.data.context)
|
||||
{
|
||||
|
@ -173,86 +158,92 @@ eng_setup(Evas *eo_evas, void *einfo)
|
|||
epd->engine.func->context_new(epd->engine.data.output);
|
||||
}
|
||||
|
||||
/* return success */
|
||||
return 1;
|
||||
|
||||
err:
|
||||
evas_common_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
eng_output_free(void *data)
|
||||
{
|
||||
Render_Engine *re = data;
|
||||
Render_Engine *re;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
evas_render_engine_software_generic_clean(&re->generic);
|
||||
free(re);
|
||||
if ((re = (Render_Engine *)data))
|
||||
{
|
||||
evas_render_engine_software_generic_clean(&re->generic);
|
||||
free(re);
|
||||
}
|
||||
|
||||
evas_common_shutdown();
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
eng_output_resize(void *data, int w, int h)
|
||||
{
|
||||
Render_Engine *re;
|
||||
Evas_Engine_Info_Wayland_Shm *info;
|
||||
Evas_Engine_Info_Wayland_Shm *einfo;
|
||||
int dx = 0, dy = 0;
|
||||
Eina_Bool resize = EINA_FALSE;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!(re = (Render_Engine *)data)) return;
|
||||
if (!(einfo = re->generic.ob->info)) return;
|
||||
|
||||
if (!(info = re->generic.ob->info)) return;
|
||||
|
||||
if (info->info.edges & 4)
|
||||
if (einfo->info.edges & 4) // resize from left
|
||||
{
|
||||
if ((info->info.rotation == 90) || (info->info.rotation == 270))
|
||||
if ((einfo->info.rotation == 90) || (einfo->info.rotation == 270))
|
||||
dx = re->generic.ob->h - h;
|
||||
else
|
||||
dx = re->generic.ob->w - w;
|
||||
}
|
||||
|
||||
if (info->info.edges & 1)
|
||||
if (einfo->info.edges & 1) // resize from top
|
||||
{
|
||||
if ((info->info.rotation == 90) || (info->info.rotation == 270))
|
||||
if ((einfo->info.rotation == 90) || (einfo->info.rotation == 270))
|
||||
dy = re->generic.ob->w - w;
|
||||
else
|
||||
dy = re->generic.ob->h - h;
|
||||
}
|
||||
|
||||
re->outbuf_reconfigure(re->generic.ob, dx, dy, w, h,
|
||||
info->info.rotation, info->info.depth,
|
||||
info->info.destination_alpha);
|
||||
if (einfo->info.edges) resize = EINA_TRUE;
|
||||
|
||||
re->outbuf_reconfigure(re->generic.ob, dx, dy, w, h,
|
||||
einfo->info.rotation, einfo->info.depth,
|
||||
einfo->info.destination_alpha, resize);
|
||||
|
||||
evas_common_tilebuf_free(re->generic.tb);
|
||||
if ((re->generic.tb = evas_common_tilebuf_new(w, h)))
|
||||
evas_common_tilebuf_set_tile_size(re->generic.tb, TILESIZE, TILESIZE);
|
||||
}
|
||||
|
||||
/* module functions */
|
||||
/* EVAS MODULE FUNCTIONS */
|
||||
static int
|
||||
module_open(Evas_Module *em)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid evas module */
|
||||
if (!em) return 0;
|
||||
|
||||
/* try to get functions from whatever engine module we inherit from */
|
||||
if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
|
||||
|
||||
/* try to create our logging domain */
|
||||
_evas_engine_way_shm_log_dom =
|
||||
eina_log_domain_register("evas-wayland_shm", EVAS_DEFAULT_LOG_COLOR);
|
||||
if (_evas_engine_way_shm_log_dom < 0)
|
||||
{
|
||||
/* creating the logging domain failed. notify user */
|
||||
EINA_LOG_ERR("Could not create a module log domain.");
|
||||
|
||||
/* return failure */
|
||||
EINA_LOG_ERR("Cannot create a module logging domain");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try to inherit base functions from the software generic engine */
|
||||
if (!_evas_module_engine_inherit(&pfunc, "software_generic"))
|
||||
return 0;
|
||||
|
||||
/* copy base functions from the software_generic engine */
|
||||
/* copy parent functions */
|
||||
func = pfunc;
|
||||
|
||||
/* override any engine specific functions that we provide */
|
||||
/* override engine specific functions */
|
||||
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
|
||||
ORD(info);
|
||||
ORD(info_free);
|
||||
|
@ -260,19 +251,23 @@ module_open(Evas_Module *em)
|
|||
ORD(output_free);
|
||||
ORD(output_resize);
|
||||
|
||||
/* advertise out our own api */
|
||||
/* advertise our own engine functions */
|
||||
em->functions = (void *)(&func);
|
||||
|
||||
/* return success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
module_close(Evas_Module *em EINA_UNUSED)
|
||||
{
|
||||
/* if we have the log domain, unregister it */
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* unregister logging domain */
|
||||
if (_evas_engine_way_shm_log_dom > -1)
|
||||
eina_log_domain_unregister(_evas_engine_way_shm_log_dom);
|
||||
|
||||
/* reset logging domain variable */
|
||||
_evas_engine_way_shm_log_dom = -1;
|
||||
}
|
||||
|
||||
static Evas_Module_Api evas_modapi =
|
||||
|
|
|
@ -38,32 +38,69 @@ extern int _evas_engine_way_shm_log_dom;
|
|||
# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_way_shm_log_dom, __VA_ARGS__)
|
||||
|
||||
# include <wayland-client.h>
|
||||
# include "../software_generic/Evas_Engine_Software_Generic.h"
|
||||
# include "Evas_Engine_Wayland_Shm.h"
|
||||
|
||||
#include "Evas_Engine_Wayland_Shm.h"
|
||||
# define MAX_BUFFERS 4
|
||||
# define SURFACE_HINT_RESIZING 0x10
|
||||
|
||||
#include "../software_generic/Evas_Engine_Software_Generic.h"
|
||||
typedef struct _Shm_Pool Shm_Pool;
|
||||
struct _Shm_Pool
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
size_t size, used;
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef struct _Shm_Data Shm_Data;
|
||||
struct _Shm_Data
|
||||
{
|
||||
struct wl_buffer *buffer;
|
||||
Shm_Pool *pool;
|
||||
void *map;
|
||||
};
|
||||
|
||||
typedef struct _Shm_Leaf Shm_Leaf;
|
||||
struct _Shm_Leaf
|
||||
{
|
||||
int w, h, busy;
|
||||
Shm_Data *data;
|
||||
Shm_Pool *resize_pool;
|
||||
Eina_Bool valid : 1;
|
||||
};
|
||||
|
||||
typedef struct _Shm_Surface Shm_Surface;
|
||||
struct _Shm_Surface
|
||||
{
|
||||
struct wl_shm *shm;
|
||||
struct wl_surface *surface;
|
||||
struct wl_callback *frame_cb;
|
||||
uint32_t flags;
|
||||
int w, h;
|
||||
int dx, dy;
|
||||
int num_buff;
|
||||
|
||||
Shm_Leaf leaf[MAX_BUFFERS];
|
||||
Shm_Leaf *current;
|
||||
|
||||
Eina_Bool redraw : 1;
|
||||
Eina_Bool alpha : 1;
|
||||
};
|
||||
|
||||
struct _Outbuf
|
||||
{
|
||||
Evas_Engine_Info_Wayland_Shm *info;
|
||||
|
||||
int w, h;
|
||||
int rotation;
|
||||
int onebuf;
|
||||
int num_buff;
|
||||
Outbuf_Depth depth;
|
||||
|
||||
Evas_Engine_Info_Wayland_Shm *info;
|
||||
|
||||
Shm_Surface *surface;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
/* wayland shared memory object */
|
||||
struct wl_shm *shm;
|
||||
struct wl_surface *surface;
|
||||
} wl;
|
||||
|
||||
/* swapper */
|
||||
void *swapper;
|
||||
|
||||
/* one big buffer for updates. flushed on idle_flush */
|
||||
RGBA_Image *onebuf;
|
||||
Eina_Array onebuf_regions;
|
||||
|
@ -74,8 +111,28 @@ struct _Outbuf
|
|||
/* list of previous frame pending regions to write out */
|
||||
Eina_List *prev_pending_writes;
|
||||
|
||||
/* Eina_Bool redraw : 1; */
|
||||
Eina_Bool destination_alpha : 1;
|
||||
} priv;
|
||||
};
|
||||
|
||||
Shm_Surface *_evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w, int h, Eina_Bool alpha);
|
||||
void _evas_shm_surface_destroy(Shm_Surface *surface);
|
||||
void _evas_shm_surface_prepare(Shm_Surface *surface, int dx, int dy, int w, int h, int num_buff, uint32_t flags);
|
||||
void _evas_shm_surface_swap(Shm_Surface *surface, Eina_Rectangle *rects, unsigned int count);
|
||||
void *_evas_shm_surface_data_get(Shm_Surface *surface, int *w, int *h);
|
||||
void _evas_shm_surface_redraw(Shm_Surface *surface);
|
||||
|
||||
Outbuf *_evas_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *shm, struct wl_surface *surface);
|
||||
void _evas_outbuf_free(Outbuf *ob);
|
||||
void _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
|
||||
void _evas_outbuf_idle_flush(Outbuf *ob);
|
||||
|
||||
Render_Engine_Swap_Mode _evas_outbuf_swapmode_get(Outbuf *ob);
|
||||
int _evas_outbuf_rotation_get(Outbuf *ob);
|
||||
void _evas_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize);
|
||||
void *_evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
|
||||
void _evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
|
||||
void _evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,383 +1,87 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
//#include <sys/mman.h>
|
||||
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
#ifdef EVAS_CSERVE2
|
||||
# include "evas_cs2_private.h"
|
||||
#endif
|
||||
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_macros.h"
|
||||
#include "evas_engine.h"
|
||||
#include "evas_swapbuf.h"
|
||||
#include "evas_swapper.h"
|
||||
|
||||
#define RED_MASK 0x00ff0000
|
||||
#define GREEN_MASK 0x0000ff00
|
||||
#define BLUE_MASK 0x000000ff
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
Outbuf *
|
||||
evas_swapbuf_setup(Evas_Engine_Info_Wayland_Shm *info, int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *wl_shm, struct wl_surface *wl_surface)
|
||||
_evas_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *shm, struct wl_surface *surface)
|
||||
{
|
||||
Outbuf *ob = NULL;
|
||||
char *num;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to allocate a new Outbuf */
|
||||
if (!(ob = calloc(1, sizeof(Outbuf))))
|
||||
return NULL;
|
||||
/* try to allocate space for new Outbuf */
|
||||
if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
|
||||
|
||||
/* set some properties */
|
||||
/* set outbuf properties */
|
||||
ob->w = w;
|
||||
ob->h = h;
|
||||
ob->rotation = rotation;
|
||||
ob->rotation = rot;
|
||||
ob->depth = depth;
|
||||
ob->priv.destination_alpha = alpha;
|
||||
ob->priv.wl.shm = wl_shm;
|
||||
ob->priv.wl.surface = wl_surface;
|
||||
ob->info = info;
|
||||
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
/* default to double buffer */
|
||||
ob->num_buff = 2;
|
||||
|
||||
/* check for any 'number of buffers' override in the environment */
|
||||
if ((num = getenv("EVAS_WAYLAND_SHM_BUFFERS")))
|
||||
{
|
||||
ob->priv.swapper =
|
||||
evas_swapper_setup(0, 0, w, h, depth, alpha, ob->priv.wl.shm,
|
||||
ob->priv.wl.surface);
|
||||
}
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
{
|
||||
ob->priv.swapper =
|
||||
evas_swapper_setup(0, 0, h, w, depth, alpha, ob->priv.wl.shm,
|
||||
ob->priv.wl.surface);
|
||||
int n = 0;
|
||||
|
||||
n = atoi(num);
|
||||
if (n <= 0) n = 1;
|
||||
if (n > 4) n = 4;
|
||||
|
||||
ob->num_buff = n;
|
||||
}
|
||||
|
||||
/* check that a swapper was created */
|
||||
if (!ob->priv.swapper)
|
||||
{
|
||||
/* free the Outbuf structure allocation */
|
||||
free(ob);
|
||||
/* try to create the outbuf surface */
|
||||
if (!(ob->surface = _evas_shm_surface_create(shm, surface, w, h, alpha)))
|
||||
goto surf_err;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* call prepare function to setup first buffer */
|
||||
_evas_shm_surface_prepare(ob->surface, 0, 0, w, h,
|
||||
ob->num_buff, ob->surface->flags);
|
||||
|
||||
/* set step size of regions array */
|
||||
eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
|
||||
|
||||
/* return allocated Outbuf */
|
||||
return ob;
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapbuf_free(Outbuf *ob)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid output buffer */
|
||||
if (!ob) return;
|
||||
|
||||
/* flush the output buffer */
|
||||
evas_swapbuf_flush(ob, NULL, MODE_FULL);
|
||||
evas_swapbuf_idle_flush(ob);
|
||||
evas_swapper_free(ob->priv.swapper);
|
||||
eina_array_flush(&ob->priv.onebuf_regions);
|
||||
|
||||
/* free the allocated structure */
|
||||
surf_err:
|
||||
free(ob);
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rotation, Outbuf_Depth depth, Eina_Bool alpha)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid output buffer */
|
||||
if (!ob) return;
|
||||
|
||||
if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth;
|
||||
|
||||
/* check that something was actually changed */
|
||||
if ((ob->w == w) && (ob->h == h) &&
|
||||
(ob->rotation == rotation) && (ob->depth == depth))
|
||||
return;
|
||||
|
||||
/* set some properties */
|
||||
ob->w = w;
|
||||
ob->h = h;
|
||||
ob->rotation = rotation;
|
||||
ob->depth = depth;
|
||||
ob->priv.destination_alpha = alpha;
|
||||
|
||||
/* check for valid swapper */
|
||||
if (ob->priv.swapper)
|
||||
{
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
ob->priv.swapper = evas_swapper_reconfigure(ob->priv.swapper,
|
||||
x, y, w, h, depth,
|
||||
alpha);
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
ob->priv.swapper = evas_swapper_reconfigure(ob->priv.swapper,
|
||||
x, y, h, w, depth,
|
||||
alpha);
|
||||
return;
|
||||
}
|
||||
|
||||
/* create new swapper */
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
{
|
||||
ob->priv.swapper =
|
||||
evas_swapper_setup(x, y, w, h, depth, alpha, ob->priv.wl.shm,
|
||||
ob->priv.wl.surface);
|
||||
}
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
{
|
||||
ob->priv.swapper =
|
||||
evas_swapper_setup(x, y, h, w, depth, alpha, ob->priv.wl.shm,
|
||||
ob->priv.wl.surface);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
evas_swapbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
|
||||
{
|
||||
RGBA_Image *img;
|
||||
Eina_Rectangle *rect;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
|
||||
if ((w <= 0) || (h <= 0)) return NULL;
|
||||
|
||||
if (ob->rotation == 0)
|
||||
{
|
||||
if (!(img = ob->priv.onebuf))
|
||||
{
|
||||
int bpl = 0;
|
||||
int bw = 0, bh = 0;
|
||||
void *data;
|
||||
|
||||
data = evas_swapper_buffer_map(ob->priv.swapper, &bw, &bh);
|
||||
bpl = (bw * sizeof(int));
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
img = (RGBA_Image *)evas_cache2_image_data(evas_common_image_cache2_get(),
|
||||
bpl / sizeof(int), bh,
|
||||
data,
|
||||
ob->priv.destination_alpha,
|
||||
EVAS_COLORSPACE_ARGB8888);
|
||||
else
|
||||
#endif
|
||||
img = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
|
||||
bpl / sizeof(int), bh,
|
||||
data,
|
||||
ob->priv.destination_alpha,
|
||||
EVAS_COLORSPACE_ARGB8888);
|
||||
|
||||
ob->priv.onebuf = img;
|
||||
if (!img) return NULL;
|
||||
}
|
||||
|
||||
if (!(rect = eina_rectangle_new(x, y, w, h)))
|
||||
return NULL;
|
||||
|
||||
if (!eina_array_push(&ob->priv.onebuf_regions, rect))
|
||||
{
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
evas_cache2_image_close(&img->cache_entry);
|
||||
else
|
||||
#endif
|
||||
evas_cache_image_drop(&img->cache_entry);
|
||||
|
||||
eina_rectangle_free(rect);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* clip the region to the onebuf region */
|
||||
if (cx) *cx = x;
|
||||
if (cy) *cy = y;
|
||||
if (cw) *cw = w;
|
||||
if (ch) *ch = h;
|
||||
return img;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(rect = eina_rectangle_new(x, y, w, h)))
|
||||
return NULL;
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
img = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get());
|
||||
else
|
||||
#endif
|
||||
img = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
|
||||
|
||||
if (!img)
|
||||
{
|
||||
eina_rectangle_free(rect);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
img->cache_entry.flags.alpha |= ob->priv.destination_alpha;
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
evas_cache2_image_surface_alloc(&img->cache_entry, w, h);
|
||||
else
|
||||
#endif
|
||||
evas_cache_image_surface_alloc(&img->cache_entry, w, h);
|
||||
|
||||
img->extended_info = rect;
|
||||
|
||||
ob->priv.pending_writes =
|
||||
eina_list_append(ob->priv.pending_writes, img);
|
||||
|
||||
if (cx) *cx = 0;
|
||||
if (cy) *cy = 0;
|
||||
if (cw) *cw = w;
|
||||
if (ch) *ch = h;
|
||||
return img;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
|
||||
_evas_outbuf_free(Outbuf *ob)
|
||||
{
|
||||
Gfx_Func_Convert func = NULL;
|
||||
Eina_Rectangle rect = {0, 0, 0, 0}, pr;
|
||||
DATA32 *src;
|
||||
DATA8 *dst;
|
||||
int depth = 32, bpp = 0, bpl = 0, wid = 0;
|
||||
int ww = 0, hh = 0;
|
||||
int rx = 0, ry = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid output buffer */
|
||||
if (!ob) return;
|
||||
_evas_outbuf_flush(ob, NULL, MODE_FULL);
|
||||
_evas_outbuf_idle_flush(ob);
|
||||
|
||||
/* check for pending writes */
|
||||
if (!ob->priv.pending_writes) return;
|
||||
if (ob->surface) _evas_shm_surface_destroy(ob->surface);
|
||||
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
{
|
||||
func =
|
||||
evas_common_convert_func_get(0, w, h, depth,
|
||||
RED_MASK, GREEN_MASK, BLUE_MASK,
|
||||
PAL_MODE_NONE, ob->rotation);
|
||||
}
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
{
|
||||
func =
|
||||
evas_common_convert_func_get(0, h, w, depth,
|
||||
RED_MASK, GREEN_MASK, BLUE_MASK,
|
||||
PAL_MODE_NONE, ob->rotation);
|
||||
}
|
||||
eina_array_flush(&ob->priv.onebuf_regions);
|
||||
|
||||
/* make sure we have a valid convert function */
|
||||
if (!func) return;
|
||||
|
||||
/* based on rotation, set rectangle position */
|
||||
if (ob->rotation == 0)
|
||||
{
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
}
|
||||
else if (ob->rotation == 90)
|
||||
{
|
||||
rect.x = y;
|
||||
rect.y = (ob->w - x - w);
|
||||
}
|
||||
else if (ob->rotation == 180)
|
||||
{
|
||||
rect.x = (ob->w - x - w);
|
||||
rect.y = (ob->h - y - h);
|
||||
}
|
||||
else if (ob->rotation == 270)
|
||||
{
|
||||
rect.x = (ob->h - y - h);
|
||||
rect.y = x;
|
||||
}
|
||||
|
||||
/* based on rotation, set rectangle size */
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
{
|
||||
rect.w = w;
|
||||
rect.h = h;
|
||||
}
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
{
|
||||
rect.w = h;
|
||||
rect.h = w;
|
||||
}
|
||||
|
||||
/* check for valid update image data */
|
||||
if (!(src = update->image.data)) return;
|
||||
|
||||
bpp = depth / 8;
|
||||
if (bpp <= 0) return;
|
||||
|
||||
/* check for valid desination data */
|
||||
if (!(dst = evas_swapper_buffer_map(ob->priv.swapper, &ww, &hh))) return;
|
||||
|
||||
bpl = (ww * sizeof(int));
|
||||
|
||||
if (ob->rotation == 0)
|
||||
{
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
dst += (bpl * rect.y) + (rect.x * bpp);
|
||||
w -= rx;
|
||||
}
|
||||
else if (ob->rotation == 180)
|
||||
{
|
||||
pr = rect;
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
rx = pr.w - rect.w;
|
||||
ry = pr.h - rect.h;
|
||||
src += (update->cache_entry.w * ry) + rx;
|
||||
w -= rx;
|
||||
}
|
||||
else if (ob->rotation == 90)
|
||||
{
|
||||
pr = rect;
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
rx = pr.w - rect.w; ry = pr.h - rect.h;
|
||||
src += ry;
|
||||
w -= ry;
|
||||
}
|
||||
else if (ob->rotation == 270)
|
||||
{
|
||||
pr = rect;
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
rx = pr.w - rect.w; ry = pr.h - rect.h;
|
||||
src += (update->cache_entry.w * rx);
|
||||
w -= ry;
|
||||
}
|
||||
|
||||
if ((rect.w <= 0) || (rect.h <= 0)) return;
|
||||
|
||||
wid = bpl / bpp;
|
||||
|
||||
dst += (bpl * rect.y) + (rect.x * bpp);
|
||||
|
||||
func(src, dst, (update->cache_entry.w - w), (wid - rect.w),
|
||||
rect.w, rect.h, x + rx, y + ry, NULL);
|
||||
free(ob);
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
|
||||
_evas_outbuf_idle_flush(Outbuf *ob)
|
||||
{
|
||||
/* NB: nothing to do, they are cleaned up on flush */
|
||||
_evas_shm_surface_redraw(ob->surface);
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
|
||||
_evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
|
||||
{
|
||||
Eina_Rectangle *result;
|
||||
RGBA_Image *img;
|
||||
|
@ -387,8 +91,11 @@ evas_swapbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
|
|||
|
||||
if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
|
||||
|
||||
/* check for valid output buffer */
|
||||
if (!ob) return;
|
||||
if (!ob->surface->current)
|
||||
{
|
||||
WRN("Cannot Flush. No Current Leaf !!");
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for pending writes */
|
||||
if (!ob->priv.pending_writes)
|
||||
|
@ -407,11 +114,8 @@ evas_swapbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
|
|||
EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
|
||||
result[i] = *rect;
|
||||
|
||||
/* unmap the buffer */
|
||||
evas_swapper_buffer_unmap(ob->priv.swapper);
|
||||
|
||||
/* force a buffer swap */
|
||||
evas_swapper_swap(ob->priv.swapper, result, n);
|
||||
_evas_shm_surface_swap(ob->surface, result, n);
|
||||
|
||||
/* clean array */
|
||||
eina_array_clean(&ob->priv.onebuf_regions);
|
||||
|
@ -493,45 +197,319 @@ evas_swapbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
|
|||
i++;
|
||||
}
|
||||
|
||||
/* unmap the buffer */
|
||||
evas_swapper_buffer_unmap(ob->priv.swapper);
|
||||
|
||||
/* force a buffer swap */
|
||||
evas_swapper_swap(ob->priv.swapper, result, n);
|
||||
_evas_shm_surface_swap(ob->surface, result, n);
|
||||
}
|
||||
|
||||
_evas_shm_surface_redraw(ob->surface);
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapbuf_idle_flush(Outbuf *ob EINA_UNUSED)
|
||||
Render_Engine_Swap_Mode
|
||||
_evas_outbuf_swapmode_get(Outbuf *ob)
|
||||
{
|
||||
// LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid output buffer */
|
||||
/* if (!ob) return; */
|
||||
|
||||
/* check for valid swapper */
|
||||
/* if (!ob->priv.swapper) return; */
|
||||
|
||||
/* tell the swapper to release any buffers that have been rendered */
|
||||
/* evas_swapper_buffer_idle_flush(ob->priv.swapper); */
|
||||
}
|
||||
|
||||
Render_Engine_Swap_Mode
|
||||
evas_swapbuf_state_get(Outbuf *ob)
|
||||
{
|
||||
int mode = 0;
|
||||
int i = 0, count = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!ob->priv.swapper) return MODE_FULL;
|
||||
mode = evas_swapper_buffer_state_get(ob->priv.swapper);
|
||||
return mode;
|
||||
for (; i < ob->num_buff; i++)
|
||||
{
|
||||
if (ob->surface->leaf[i].busy)
|
||||
count++;
|
||||
}
|
||||
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
return MODE_COPY;
|
||||
case 1:
|
||||
return MODE_DOUBLE;
|
||||
case 2:
|
||||
return MODE_TRIPLE;
|
||||
case 3:
|
||||
return MODE_QUADRUPLE;
|
||||
default:
|
||||
return MODE_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
evas_swapbuf_rotation_get(Outbuf *ob)
|
||||
int
|
||||
_evas_outbuf_rotation_get(Outbuf *ob)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
return ob->rotation;
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
void
|
||||
_evas_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth;
|
||||
|
||||
if ((ob->w == w) && (ob->h == h) &&
|
||||
(ob->rotation == rot) && (ob->depth == depth) &&
|
||||
(ob->priv.destination_alpha == alpha))
|
||||
return;
|
||||
|
||||
ob->w = w;
|
||||
ob->h = h;
|
||||
ob->rotation = rot;
|
||||
ob->depth = depth;
|
||||
ob->priv.destination_alpha = alpha;
|
||||
|
||||
if (resize)
|
||||
ob->surface->flags = SURFACE_HINT_RESIZING;
|
||||
else
|
||||
ob->surface->flags = 0;
|
||||
|
||||
_evas_shm_surface_prepare(ob->surface, x, y, w, h,
|
||||
ob->num_buff, ob->surface->flags);
|
||||
}
|
||||
|
||||
void *
|
||||
_evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
|
||||
{
|
||||
RGBA_Image *img;
|
||||
Eina_Rectangle *rect;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
|
||||
if ((w <= 0) || (h <= 0)) return NULL;
|
||||
|
||||
if (ob->rotation == 0)
|
||||
{
|
||||
if (!(img = ob->priv.onebuf))
|
||||
{
|
||||
int bw = 0, bh = 0, bpl = 0;
|
||||
void *data;
|
||||
|
||||
if (!(data = _evas_shm_surface_data_get(ob->surface, &bw, &bh)))
|
||||
{
|
||||
ERR("Could not get surface data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bpl = (bw * sizeof(int));
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
{
|
||||
img = (RGBA_Image *)
|
||||
evas_cache2_image_data(evas_common_image_cache2_get(),
|
||||
bpl / sizeof(int), bh, data,
|
||||
ob->priv.destination_alpha,
|
||||
EVAS_COLORSPACE_ARGB8888);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
img = (RGBA_Image *)
|
||||
evas_cache_image_data(evas_common_image_cache_get(),
|
||||
bpl / sizeof(int), bh, data,
|
||||
ob->priv.destination_alpha,
|
||||
EVAS_COLORSPACE_ARGB8888);
|
||||
|
||||
}
|
||||
|
||||
ob->priv.onebuf = img;
|
||||
if (!img) return NULL;
|
||||
}
|
||||
|
||||
if (!(rect = eina_rectangle_new(x, y, w, h)))
|
||||
return NULL;
|
||||
|
||||
if (!eina_array_push(&ob->priv.onebuf_regions, rect))
|
||||
{
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
evas_cache2_image_close(&img->cache_entry);
|
||||
else
|
||||
#endif
|
||||
evas_cache_image_drop(&img->cache_entry);
|
||||
|
||||
eina_rectangle_free(rect);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cx) *cx = x;
|
||||
if (cy) *cy = y;
|
||||
if (cw) *cw = w;
|
||||
if (ch) *ch = h;
|
||||
|
||||
img->extended_info = rect;
|
||||
|
||||
return img;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(rect = eina_rectangle_new(x, y, w, h)))
|
||||
return NULL;
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
img = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get());
|
||||
else
|
||||
#endif
|
||||
img = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
|
||||
|
||||
if (!img)
|
||||
{
|
||||
eina_rectangle_free(rect);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
img->cache_entry.flags.alpha |= ob->priv.destination_alpha ? 1 : 0;
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
if (evas_cserve2_use_get())
|
||||
evas_cache2_image_surface_alloc(&img->cache_entry, w, h);
|
||||
else
|
||||
#endif
|
||||
evas_cache_image_surface_alloc(&img->cache_entry, w, h);
|
||||
|
||||
img->extended_info = rect;
|
||||
|
||||
ob->priv.pending_writes =
|
||||
eina_list_append(ob->priv.pending_writes, img);
|
||||
|
||||
if (cx) *cx = 0;
|
||||
if (cy) *cy = 0;
|
||||
if (cw) *cw = w;
|
||||
if (ch) *ch = h;
|
||||
return img;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
|
||||
{
|
||||
Gfx_Func_Convert func = NULL;
|
||||
Eina_Rectangle rect = {0, 0, 0, 0}, pr;
|
||||
DATA32 *src;
|
||||
DATA8 *dst;
|
||||
int depth = 32, bpp = 0, bpl = 0, wid = 0;
|
||||
int ww = 0, hh = 0;
|
||||
int rx = 0, ry = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid output buffer */
|
||||
if (!ob) return;
|
||||
|
||||
/* check for pending writes */
|
||||
if (!ob->priv.pending_writes) return;
|
||||
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
{
|
||||
func =
|
||||
evas_common_convert_func_get(0, w, h, depth,
|
||||
RED_MASK, GREEN_MASK, BLUE_MASK,
|
||||
PAL_MODE_NONE, ob->rotation);
|
||||
}
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
{
|
||||
func =
|
||||
evas_common_convert_func_get(0, h, w, depth,
|
||||
RED_MASK, GREEN_MASK, BLUE_MASK,
|
||||
PAL_MODE_NONE, ob->rotation);
|
||||
}
|
||||
|
||||
/* make sure we have a valid convert function */
|
||||
if (!func) return;
|
||||
|
||||
/* based on rotation, set rectangle position */
|
||||
if (ob->rotation == 0)
|
||||
{
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
}
|
||||
else if (ob->rotation == 90)
|
||||
{
|
||||
rect.x = y;
|
||||
rect.y = (ob->w - x - w);
|
||||
}
|
||||
else if (ob->rotation == 180)
|
||||
{
|
||||
rect.x = (ob->w - x - w);
|
||||
rect.y = (ob->h - y - h);
|
||||
}
|
||||
else if (ob->rotation == 270)
|
||||
{
|
||||
rect.x = (ob->h - y - h);
|
||||
rect.y = x;
|
||||
}
|
||||
|
||||
/* based on rotation, set rectangle size */
|
||||
if ((ob->rotation == 0) || (ob->rotation == 180))
|
||||
{
|
||||
rect.w = w;
|
||||
rect.h = h;
|
||||
}
|
||||
else if ((ob->rotation == 90) || (ob->rotation == 270))
|
||||
{
|
||||
rect.w = h;
|
||||
rect.h = w;
|
||||
}
|
||||
|
||||
/* check for valid update image data */
|
||||
if (!(src = update->image.data)) return;
|
||||
|
||||
bpp = depth / 8;
|
||||
if (bpp <= 0) return;
|
||||
|
||||
/* check for valid desination data */
|
||||
if (!(dst = _evas_shm_surface_data_get(ob->surface, &ww, &hh))) return;
|
||||
|
||||
bpl = (ww * sizeof(int));
|
||||
|
||||
if (ob->rotation == 0)
|
||||
{
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
dst += (bpl * rect.y) + (rect.x * bpp);
|
||||
w -= rx;
|
||||
}
|
||||
else if (ob->rotation == 180)
|
||||
{
|
||||
pr = rect;
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
rx = pr.w - rect.w;
|
||||
ry = pr.h - rect.h;
|
||||
src += (update->cache_entry.w * ry) + rx;
|
||||
w -= rx;
|
||||
}
|
||||
else if (ob->rotation == 90)
|
||||
{
|
||||
pr = rect;
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
rx = pr.w - rect.w; ry = pr.h - rect.h;
|
||||
src += ry;
|
||||
w -= ry;
|
||||
}
|
||||
else if (ob->rotation == 270)
|
||||
{
|
||||
pr = rect;
|
||||
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
|
||||
rx = pr.w - rect.w; ry = pr.h - rect.h;
|
||||
src += (update->cache_entry.w * rx);
|
||||
w -= ry;
|
||||
}
|
||||
|
||||
if ((rect.w <= 0) || (rect.h <= 0)) return;
|
||||
|
||||
wid = bpl / bpp;
|
||||
|
||||
dst += (bpl * rect.y) + (rect.x * bpp);
|
||||
|
||||
func(src, dst, (update->cache_entry.w - w), (wid - rect.w),
|
||||
rect.w, rect.h, x + rx, y + ry, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
}
|
|
@ -0,0 +1,477 @@
|
|||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
#ifdef EVAS_CSERVE2
|
||||
# include "evas_cs2_private.h"
|
||||
#endif
|
||||
#include "evas_engine.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
static void
|
||||
_evas_shm_surface_cb_frame(void *data, struct wl_callback *callback, uint32_t timestamp EINA_UNUSED)
|
||||
{
|
||||
Shm_Surface *surf;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!(surf = data)) return;
|
||||
if (callback != surf->frame_cb) return;
|
||||
|
||||
wl_callback_destroy(callback);
|
||||
surf->frame_cb = NULL;
|
||||
surf->redraw = EINA_FALSE;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener _frame_listener =
|
||||
{
|
||||
_evas_shm_surface_cb_frame
|
||||
};
|
||||
|
||||
static struct wl_shm_pool *
|
||||
_shm_pool_make(struct wl_shm *shm, int size, void **data)
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
static const char tmp[] = "/evas-wayland_shm-XXXXXX";
|
||||
const char *path;
|
||||
char *name;
|
||||
int fd = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid wl_shm */
|
||||
if (!shm) return NULL;
|
||||
|
||||
/* create tmp file name */
|
||||
if ((path = getenv("XDG_RUNTIME_DIR")))
|
||||
{
|
||||
if ((name = malloc(strlen(path) + sizeof(tmp))))
|
||||
strcpy(name, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((name = malloc(strlen("/tmp") + sizeof(tmp))))
|
||||
strcpy(name, "/tmp");
|
||||
}
|
||||
|
||||
if (!name) return NULL;
|
||||
|
||||
strcat(name, tmp);
|
||||
|
||||
/* try to create tmp file */
|
||||
if ((fd = mkstemp(name)) < 0)
|
||||
{
|
||||
ERR("Could not create temporary file: %m");
|
||||
free(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unlink(name);
|
||||
free(name);
|
||||
|
||||
/* try to truncate file to size */
|
||||
if (ftruncate(fd, size) < 0)
|
||||
{
|
||||
ERR("Could not truncate temporary file: %m");
|
||||
goto fd_err;
|
||||
}
|
||||
|
||||
/* try to mmap the file */
|
||||
*data = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
|
||||
if (*data == MAP_FAILED)
|
||||
{
|
||||
ERR("Could not mmap temporary file: %m");
|
||||
goto fd_err;
|
||||
}
|
||||
|
||||
/* create wl_shm_pool using fd */
|
||||
pool = wl_shm_create_pool(shm, fd, size);
|
||||
|
||||
close(fd);
|
||||
|
||||
return pool;
|
||||
|
||||
fd_err:
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Shm_Pool *
|
||||
_shm_pool_create(struct wl_shm *shm, size_t size)
|
||||
{
|
||||
Shm_Pool *pool;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!(pool = malloc(sizeof(Shm_Pool)))) return NULL;
|
||||
|
||||
pool->pool = _shm_pool_make(shm, size, &pool->data);
|
||||
if (!pool->pool) goto err;
|
||||
|
||||
pool->size = size;
|
||||
pool->used = 0;
|
||||
|
||||
return pool;
|
||||
|
||||
err:
|
||||
free(pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_shm_pool_destroy(Shm_Pool *pool)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
munmap(pool->data, pool->size);
|
||||
wl_shm_pool_destroy(pool->pool);
|
||||
free(pool);
|
||||
}
|
||||
|
||||
static void *
|
||||
_shm_pool_allocate(Shm_Pool *pool, size_t size, int *offset)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if ((pool->used + size) > pool->size)
|
||||
return NULL;
|
||||
|
||||
*offset = pool->used;
|
||||
pool->used += size;
|
||||
|
||||
return (char *)pool->data + *offset;
|
||||
}
|
||||
|
||||
static void
|
||||
_shm_pool_reset(Shm_Pool *pool)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
pool->used = 0;
|
||||
}
|
||||
|
||||
static Shm_Data *
|
||||
_shm_data_create_from_pool(Shm_Pool *pool, int w, int h, Eina_Bool alpha)
|
||||
{
|
||||
Shm_Data *data;
|
||||
int len, offset;
|
||||
uint32_t wl_format = WL_SHM_FORMAT_XRGB8888;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to malloc space for data */
|
||||
if (!(data = malloc(sizeof(Shm_Data))))
|
||||
{
|
||||
ERR("Could not allocate space for data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (w * sizeof(int)) * h;
|
||||
data->pool = NULL;
|
||||
|
||||
if (!(data->map = _shm_pool_allocate(pool, len, &offset)))
|
||||
{
|
||||
ERR("Could not map leaf data");
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (alpha)
|
||||
wl_format = WL_SHM_FORMAT_ARGB8888;
|
||||
|
||||
data->buffer =
|
||||
wl_shm_pool_create_buffer(pool->pool, offset, w, h,
|
||||
(w * sizeof(int)), wl_format);
|
||||
if (!data->buffer)
|
||||
{
|
||||
ERR("Could not create buffer from pool: %m");
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
_shm_data_create(Shm_Pool *alt_pool, Shm_Data **ret, Shm_Surface *surface, int w, int h)
|
||||
{
|
||||
Shm_Pool *pool;
|
||||
Shm_Data *data;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (alt_pool)
|
||||
{
|
||||
_shm_pool_reset(alt_pool);
|
||||
if ((data = _shm_data_create_from_pool(alt_pool, w, h, surface->alpha)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(pool = _shm_pool_create(surface->shm, ((w * sizeof(int)) * h))))
|
||||
{
|
||||
ERR("Could not create shm pool");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(data = _shm_data_create_from_pool(pool, w, h, surface->alpha)))
|
||||
{
|
||||
ERR("Could not create data from pool");
|
||||
_shm_pool_destroy(pool);
|
||||
goto err;
|
||||
}
|
||||
|
||||
data->pool = pool;
|
||||
|
||||
out:
|
||||
if (ret) *ret = data;
|
||||
return;
|
||||
err:
|
||||
if (ret) *ret = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_shm_data_destroy(Shm_Data *data)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (data->buffer) wl_buffer_destroy(data->buffer);
|
||||
if (data->pool) _shm_pool_destroy(data->pool);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
_shm_leaf_release(Shm_Leaf *leaf)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (leaf->data) _shm_data_destroy(leaf->data);
|
||||
if (leaf->resize_pool) _shm_pool_destroy(leaf->resize_pool);
|
||||
memset(leaf, 0, sizeof(*leaf));
|
||||
}
|
||||
|
||||
static void
|
||||
_shm_buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
Shm_Surface *surf;
|
||||
Shm_Leaf *leaf;
|
||||
int i = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
surf = data;
|
||||
|
||||
for (; i < surf->num_buff; i++)
|
||||
{
|
||||
leaf = &surf->leaf[i];
|
||||
if ((leaf->data) && (leaf->data->buffer == buffer))
|
||||
{
|
||||
leaf->busy = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener _shm_buffer_listener =
|
||||
{
|
||||
_shm_buffer_release
|
||||
};
|
||||
|
||||
Shm_Surface *
|
||||
_evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w, int h, Eina_Bool alpha)
|
||||
{
|
||||
Shm_Surface *surf;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!(surf = calloc(1, sizeof(Shm_Surface)))) return NULL;
|
||||
|
||||
surf->dx = 0;
|
||||
surf->dy = 0;
|
||||
surf->w = w;
|
||||
surf->h = h;
|
||||
surf->shm = shm;
|
||||
surf->surface = surface;
|
||||
surf->alpha = alpha;
|
||||
surf->flags = 0;
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
void
|
||||
_evas_shm_surface_destroy(Shm_Surface *surface)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
for (; i < surface->num_buff; i++)
|
||||
_shm_leaf_release(&surface->leaf[i]);
|
||||
|
||||
free(surface);
|
||||
}
|
||||
|
||||
void
|
||||
_evas_shm_surface_prepare(Shm_Surface *surface, int dx, int dy, int w, int h, int num_buff, uint32_t flags)
|
||||
{
|
||||
Shm_Leaf *leaf = NULL;
|
||||
int i = 0, resize = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
resize = !!(flags & SURFACE_HINT_RESIZING);
|
||||
|
||||
/* update surface properties */
|
||||
surface->w = w;
|
||||
surface->h = h;
|
||||
surface->dx = dx;
|
||||
surface->dy = dy;
|
||||
surface->num_buff = num_buff;
|
||||
|
||||
for (; i < num_buff; i++)
|
||||
{
|
||||
if (surface->leaf[i].busy) continue;
|
||||
if ((!leaf) || (leaf->valid))
|
||||
{
|
||||
leaf = &surface->leaf[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!leaf)
|
||||
{
|
||||
CRI("All buffers held by server");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!resize) && (leaf->resize_pool))
|
||||
{
|
||||
_shm_data_destroy(leaf->data);
|
||||
leaf->data = NULL;
|
||||
|
||||
_shm_pool_destroy(leaf->resize_pool);
|
||||
leaf->resize_pool = NULL;
|
||||
}
|
||||
|
||||
if (leaf->valid)
|
||||
{
|
||||
if ((leaf->w == w) && (leaf->h == h)) goto out;
|
||||
}
|
||||
|
||||
if (leaf->data) _shm_data_destroy(leaf->data);
|
||||
leaf->data = NULL;
|
||||
|
||||
if ((resize) && (!leaf->resize_pool))
|
||||
{
|
||||
leaf->resize_pool =
|
||||
_shm_pool_create(surface->shm, 6 * 1024 * 1024);
|
||||
}
|
||||
|
||||
_shm_data_create(leaf->resize_pool, &leaf->data, surface, w, h);
|
||||
if (!leaf->data)
|
||||
{
|
||||
CRI("Failed to create leaf data");
|
||||
abort();
|
||||
}
|
||||
|
||||
leaf->w = w;
|
||||
leaf->h = h;
|
||||
leaf->valid = EINA_TRUE;
|
||||
|
||||
wl_buffer_add_listener(leaf->data->buffer, &_shm_buffer_listener, surface);
|
||||
|
||||
out:
|
||||
surface->current = leaf;
|
||||
}
|
||||
|
||||
void
|
||||
_evas_shm_surface_swap(Shm_Surface *surface, Eina_Rectangle *rects, unsigned int count)
|
||||
{
|
||||
Shm_Leaf *leaf;
|
||||
Eina_Rectangle *rect;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!(leaf = surface->current))
|
||||
{
|
||||
ERR("No Current Leaf");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!leaf->valid)
|
||||
{
|
||||
ERR("Leaf Not Valid");
|
||||
return;
|
||||
}
|
||||
|
||||
rect = eina_rectangle_new(0, 0, 0, 0);
|
||||
if ((rects) && (count > 0))
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (; i < count; i++)
|
||||
eina_rectangle_union(rect, &rects[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Eina_Rectangle r;
|
||||
|
||||
r.x = 0; r.y = 0;
|
||||
r.w = leaf->w; r.h = leaf->h;
|
||||
|
||||
eina_rectangle_union(rect, &r);
|
||||
}
|
||||
|
||||
wl_surface_attach(surface->surface, leaf->data->buffer, 0, 0);
|
||||
wl_surface_damage(surface->surface, rect->x, rect->y, rect->w, rect->h);
|
||||
wl_surface_commit(surface->surface);
|
||||
|
||||
eina_rectangle_free(rect);
|
||||
|
||||
leaf->busy = 1;
|
||||
surface->dx = 0;
|
||||
surface->dy = 0;
|
||||
surface->redraw = EINA_TRUE;
|
||||
}
|
||||
|
||||
void *
|
||||
_evas_shm_surface_data_get(Shm_Surface *surface, int *bw, int *bh)
|
||||
{
|
||||
Shm_Leaf *leaf;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (bw) *bw = 0;
|
||||
if (bh) *bh = 0;
|
||||
|
||||
if (!(leaf = surface->current))
|
||||
{
|
||||
_evas_shm_surface_prepare(surface, 0, 0, surface->w, surface->h,
|
||||
surface->num_buff, surface->flags);
|
||||
|
||||
if (!(leaf = surface->current))
|
||||
{
|
||||
CRI("NO Current Surface");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (bw) *bw = leaf->w;
|
||||
if (bh) *bh = leaf->h;
|
||||
|
||||
return leaf->data->map;
|
||||
}
|
||||
|
||||
void
|
||||
_evas_shm_surface_redraw(Shm_Surface *surface)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (surface->frame_cb)
|
||||
{
|
||||
if (!surface->redraw) return;
|
||||
wl_callback_destroy(surface->frame_cb);
|
||||
}
|
||||
|
||||
if (!surface->surface) return;
|
||||
|
||||
surface->frame_cb = wl_surface_frame(surface->surface);
|
||||
wl_callback_add_listener(surface->frame_cb, &_frame_listener, surface);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef _EVAS_SWAPBUF_H
|
||||
# define _EVAS_SWAPBUF_H
|
||||
|
||||
# include "evas_engine.h"
|
||||
|
||||
Outbuf *evas_swapbuf_setup(Evas_Engine_Info_Wayland_Shm *info, int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *wl_shm, struct wl_surface *wl_surface);
|
||||
void evas_swapbuf_free(Outbuf *ob);
|
||||
void evas_swapbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rotation, Outbuf_Depth depth, Eina_Bool alpha);
|
||||
void *evas_swapbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
|
||||
void evas_swapbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
|
||||
void evas_swapbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
|
||||
void evas_swapbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
|
||||
void evas_swapbuf_idle_flush(Outbuf *ob EINA_UNUSED);
|
||||
Render_Engine_Swap_Mode evas_swapbuf_state_get(Outbuf *ob);
|
||||
int evas_swapbuf_rotation_get(Outbuf *ob);
|
||||
|
||||
#endif
|
|
@ -1,541 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef EVAS_CSERVE2
|
||||
# include "evas_cs2_private.h"
|
||||
#endif
|
||||
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_macros.h"
|
||||
#include "evas_engine.h"
|
||||
#include "evas_swapper.h"
|
||||
|
||||
/* local structures */
|
||||
typedef struct _Wl_Buffer Wl_Buffer;
|
||||
struct _Wl_Buffer
|
||||
{
|
||||
Wl_Swapper *ws;
|
||||
int w, h;
|
||||
struct wl_buffer *buffer;
|
||||
void *data;
|
||||
int offset;
|
||||
size_t size;
|
||||
Eina_Bool valid : 1;
|
||||
};
|
||||
|
||||
struct _Wl_Swapper
|
||||
{
|
||||
Wl_Buffer buff[3];
|
||||
Wl_Buffer *buffer_sent;
|
||||
int in_use;
|
||||
int dx, dy, w, h, depth;
|
||||
int buff_cur, buff_num, buff_last;
|
||||
struct wl_shm *shm;
|
||||
struct wl_surface *surface;
|
||||
struct wl_shm_pool *pool;
|
||||
size_t pool_size;
|
||||
size_t used_size;
|
||||
void *data;
|
||||
Eina_Bool alpha : 1;
|
||||
Eina_Bool mapped : 1;
|
||||
Eina_Bool delete_me : 1;
|
||||
};
|
||||
|
||||
/* local function prototypes */
|
||||
static Eina_Bool _evas_swapper_shm_pool_new(Wl_Swapper *ws);
|
||||
static void _evas_swapper_shm_pool_free(Wl_Swapper *ws);
|
||||
static Eina_Bool _evas_swapper_buffer_new(Wl_Swapper *ws, Wl_Buffer *wb);
|
||||
static void _evas_swapper_buffer_free(Wl_Buffer *wb);
|
||||
static void _evas_swapper_buffer_put(Wl_Swapper *ws, Wl_Buffer *wb, Eina_Rectangle *rects, unsigned int count);
|
||||
static void _evas_swapper_buffer_release(void *data, struct wl_buffer *buffer);
|
||||
|
||||
static const struct wl_buffer_listener _evas_swapper_buffer_listener =
|
||||
{
|
||||
_evas_swapper_buffer_release
|
||||
};
|
||||
|
||||
/* local variables */
|
||||
|
||||
Wl_Swapper *
|
||||
evas_swapper_setup(int dx, int dy, int w, int h, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *shm, struct wl_surface *surface)
|
||||
{
|
||||
Wl_Swapper *ws;
|
||||
int i = 0;
|
||||
char *num_buffers;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to allocate a new swapper */
|
||||
if (!(ws = calloc(1, sizeof(Wl_Swapper))))
|
||||
return NULL;
|
||||
|
||||
/* set some properties */
|
||||
ws->dx = dx;
|
||||
ws->dy = dy;
|
||||
ws->w = w;
|
||||
ws->h = h;
|
||||
ws->depth = depth;
|
||||
ws->alpha = alpha;
|
||||
ws->shm = shm;
|
||||
ws->surface = surface;
|
||||
|
||||
/* double buffer by default */
|
||||
ws->buff_num = 2;
|
||||
|
||||
/* check for buffer override number */
|
||||
if ((num_buffers = getenv("EVAS_WAYLAND_SHM_BUFFERS")))
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
num = atoi(num_buffers);
|
||||
|
||||
if (num <= 0) num = 1;
|
||||
if (num > 3) num = 3;
|
||||
|
||||
ws->buff_num = num;
|
||||
}
|
||||
|
||||
/* create the shm pool */
|
||||
if (!_evas_swapper_shm_pool_new(ws))
|
||||
{
|
||||
evas_swapper_free(ws);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ws->buff_num; i++)
|
||||
{
|
||||
/* try to create new internal Wl_Buffer */
|
||||
if (!_evas_swapper_buffer_new(ws, &(ws->buff[i])))
|
||||
{
|
||||
/* failed to create wl_buffer. free the swapper */
|
||||
evas_swapper_free(ws);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* return allocated swapper */
|
||||
return ws;
|
||||
}
|
||||
|
||||
Wl_Swapper *
|
||||
evas_swapper_reconfigure(Wl_Swapper *ws, int dx, int dy, int w, int h, Outbuf_Depth depth, Eina_Bool alpha)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
if (!ws)
|
||||
{
|
||||
ERR("No swapper to reconfigure.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* loop the swapper's buffers and free them */
|
||||
for (i = 0; i < ws->buff_num; i++)
|
||||
_evas_swapper_buffer_free(&(ws->buff[i]));
|
||||
|
||||
/* free the shm pool */
|
||||
_evas_swapper_shm_pool_free(ws);
|
||||
|
||||
ws->dx += dx;
|
||||
ws->dy += dy;
|
||||
ws->w = w;
|
||||
ws->h = h;
|
||||
ws->depth = depth;
|
||||
ws->alpha = alpha;
|
||||
|
||||
/* create the shm pool */
|
||||
if (!_evas_swapper_shm_pool_new(ws))
|
||||
{
|
||||
ERR("Could not allocate new shm pool.");
|
||||
evas_swapper_free(ws);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ws->buff_num; i++)
|
||||
{
|
||||
/* try to create new internal Wl_Buffer */
|
||||
if (!_evas_swapper_buffer_new(ws, &(ws->buff[i])))
|
||||
{
|
||||
ERR("failed to create wl_buffer. free the swapper.");
|
||||
evas_swapper_free(ws);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* return reconfigured swapper */
|
||||
return ws;
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapper_swap(Wl_Swapper *ws, Eina_Rectangle *rects, unsigned int count)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return;
|
||||
|
||||
ws->buff_last = n = ws->buff_cur;
|
||||
_evas_swapper_buffer_put(ws, &(ws->buff[n]), rects, count);
|
||||
ws->buff[n].valid = EINA_TRUE;
|
||||
ws->in_use++;
|
||||
ws->buff_cur = (ws->buff_cur + 1) % ws->buff_num;
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapper_free(Wl_Swapper *ws)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return;
|
||||
|
||||
/* loop the swapper's buffers and free them */
|
||||
for (i = 0; i < ws->buff_num; i++)
|
||||
_evas_swapper_buffer_free(&(ws->buff[i]));
|
||||
|
||||
if (ws->in_use)
|
||||
{
|
||||
ws->delete_me = EINA_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* free the shm pool */
|
||||
_evas_swapper_shm_pool_free(ws);
|
||||
|
||||
/* free the allocated structure */
|
||||
free(ws);
|
||||
}
|
||||
|
||||
void *
|
||||
evas_swapper_buffer_map(Wl_Swapper *ws, int *w, int *h)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return NULL;
|
||||
|
||||
/* set mapped property */
|
||||
ws->mapped = EINA_TRUE;
|
||||
if (w) *w = ws->w;
|
||||
if (h) *h = ws->h;
|
||||
|
||||
/* return wl_buffer data */
|
||||
return ws->buff[ws->buff_cur].data;
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapper_buffer_unmap(Wl_Swapper *ws)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return;
|
||||
|
||||
ws->mapped = EINA_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
evas_swapper_buffer_state_get(Wl_Swapper *ws)
|
||||
{
|
||||
int delta;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
delta = (ws->buff_last - ws->buff_cur +
|
||||
(ws->buff_last > ws->buff_last ?
|
||||
0 : ws->buff_num)) % ws->buff_num;
|
||||
|
||||
/* This is the number of frame since last frame */
|
||||
switch (delta)
|
||||
{
|
||||
case 0:
|
||||
return MODE_COPY;
|
||||
case 1:
|
||||
return MODE_DOUBLE;
|
||||
case 2:
|
||||
return MODE_TRIPLE;
|
||||
default:
|
||||
return MODE_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evas_swapper_buffer_idle_flush(Wl_Swapper *ws)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return;
|
||||
|
||||
/* loop the swapper's buffers and free them */
|
||||
for (i = 0; i < ws->buff_num; i++)
|
||||
{
|
||||
Wl_Buffer *wb = NULL;
|
||||
|
||||
/* try to get out Wl_Buffer struct */
|
||||
if (!(wb = (&(ws->buff[i])))) continue;
|
||||
|
||||
/* if this buffer is not valid, then unmap data */
|
||||
if (!wb->valid) _evas_swapper_buffer_free(wb);
|
||||
}
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
static Eina_Bool
|
||||
_evas_swapper_shm_pool_new(Wl_Swapper *ws)
|
||||
{
|
||||
static const char tmp[] = "/evas-wayland_shm-XXXXXX";
|
||||
const char *path;
|
||||
char *name;
|
||||
size_t size;
|
||||
int fd = 0;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* make sure swapper has a shm */
|
||||
if (!ws->shm) return EINA_FALSE;
|
||||
|
||||
/* calculate new required size */
|
||||
size = (((ws->w * sizeof(int)) * ws->h) * ws->buff_num);
|
||||
|
||||
/* check pool size to see if we need to realloc the pool */
|
||||
if (size <= ws->pool_size) return EINA_TRUE;
|
||||
|
||||
/* create tmp file, trying to use XDG_RUNTIME if set */
|
||||
if ((path = getenv("XDG_RUNTIME_DIR")))
|
||||
{
|
||||
if ((name = malloc(strlen(path) + sizeof(tmp))))
|
||||
strcpy(name, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((name = malloc(strlen("/tmp") + sizeof(tmp))))
|
||||
strcpy(name, "/tmp");
|
||||
}
|
||||
|
||||
if (!name) return EINA_FALSE;
|
||||
|
||||
strcat(name, tmp);
|
||||
|
||||
/* try to create the tmp file */
|
||||
if ((fd = mkstemp(name)) < 0)
|
||||
{
|
||||
ERR("Could not create temporary file.");
|
||||
free(name);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
/* unlink the temp file */
|
||||
unlink(name);
|
||||
free(name);
|
||||
|
||||
/* try to truncate the tmp file to requested size */
|
||||
if (ftruncate(fd, size) < 0)
|
||||
{
|
||||
ERR("Could not truncate temporary file.");
|
||||
close(fd);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
/* mem map the file */
|
||||
ws->data = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
|
||||
|
||||
/* if we failed to mem map the file, return an error */
|
||||
if (ws->data == MAP_FAILED)
|
||||
{
|
||||
ERR("Could not mmap temporary file.");
|
||||
close(fd);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
/* actually create the shm pool */
|
||||
ws->pool = wl_shm_create_pool(ws->shm, fd, size);
|
||||
|
||||
ws->pool_size = size;
|
||||
ws->used_size = 0;
|
||||
|
||||
/* close the file */
|
||||
close(fd);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_swapper_shm_pool_free(Wl_Swapper *ws)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return;
|
||||
|
||||
/* check for valid pool */
|
||||
if (!ws->pool) return;
|
||||
|
||||
/* unmap any existing data */
|
||||
if (ws->data) munmap(ws->data, ws->pool_size);
|
||||
|
||||
/* destroy the shm pool */
|
||||
wl_shm_pool_destroy(ws->pool);
|
||||
|
||||
ws->pool_size = 0;
|
||||
ws->used_size = 0;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_evas_swapper_buffer_new(Wl_Swapper *ws, Wl_Buffer *wb)
|
||||
{
|
||||
unsigned int format = WL_SHM_FORMAT_XRGB8888;
|
||||
size_t size;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* make sure swapper has a shm */
|
||||
if (!ws->shm) return EINA_FALSE;
|
||||
|
||||
wb->w = ws->w;
|
||||
wb->h = ws->h;
|
||||
|
||||
/* calculate new required size */
|
||||
size = ((wb->w * sizeof(int)) * wb->h);
|
||||
|
||||
/* check pool size to see if we need to realloc the pool */
|
||||
if (ws->used_size + size > ws->pool_size)
|
||||
{
|
||||
size_t newsize;
|
||||
|
||||
/* calculate new required size */
|
||||
newsize = (ws->pool_size + size);
|
||||
|
||||
/* resize the shm pool */
|
||||
wl_shm_pool_resize(ws->pool, newsize);
|
||||
|
||||
ws->pool_size = newsize;
|
||||
}
|
||||
|
||||
/* check if this buffer needs argb and set format */
|
||||
if (ws->alpha) format = WL_SHM_FORMAT_ARGB8888;
|
||||
|
||||
/* create actual wl_buffer */
|
||||
wb->buffer =
|
||||
wl_shm_pool_create_buffer(ws->pool, ws->used_size, wb->w, wb->h,
|
||||
(wb->w * sizeof(int)), format);
|
||||
|
||||
/* add wayland buffer listener */
|
||||
wl_buffer_add_listener(wb->buffer, &_evas_swapper_buffer_listener, wb);
|
||||
|
||||
wb->data = (char *)ws->data + ws->used_size;
|
||||
wb->size = size;
|
||||
|
||||
ws->used_size += size;
|
||||
|
||||
wb->ws = ws;
|
||||
|
||||
/* return allocated buffer */
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_swapper_buffer_free(Wl_Buffer *wb)
|
||||
{
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid buffer */
|
||||
if ((!wb) || (wb->valid)) return;
|
||||
|
||||
/* kill the wl_buffer */
|
||||
if (wb->buffer) wl_buffer_destroy(wb->buffer);
|
||||
wb->buffer = NULL;
|
||||
|
||||
/* unmap the buffer data */
|
||||
/* if (wb->data) munmap(wb->data, wb->size); */
|
||||
wb->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_swapper_buffer_put(Wl_Swapper *ws, Wl_Buffer *wb, Eina_Rectangle *rects, unsigned int count)
|
||||
{
|
||||
Eina_Rectangle *rect;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* check for valid swapper */
|
||||
if (!ws) return;
|
||||
|
||||
/* make sure swapper has a surface */
|
||||
if (!ws->surface) return;
|
||||
|
||||
/* check for valid buffer */
|
||||
if (!wb) return;
|
||||
|
||||
/* make sure buffer has mapped data */
|
||||
if ((!wb->data) || (!wb->buffer))
|
||||
{
|
||||
/* call function to mmap buffer data */
|
||||
/* if (!_evas_swapper_buffer_new(ws, wb)) */
|
||||
return;
|
||||
}
|
||||
|
||||
rect = eina_rectangle_new(0, 0, 0, 0);
|
||||
if ((rects) && (count > 0))
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
eina_rectangle_union(rect, &rects[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Eina_Rectangle r;
|
||||
|
||||
r.x = 0; r.y = 0;
|
||||
r.w = wb->w; r.h = wb->h;
|
||||
|
||||
eina_rectangle_union(rect, &r);
|
||||
}
|
||||
|
||||
/* surface attach */
|
||||
if (ws->buffer_sent != wb)
|
||||
{
|
||||
wl_surface_attach(ws->surface, wb->buffer, ws->dx, ws->dy);
|
||||
ws->dx = 0;
|
||||
ws->dy = 0;
|
||||
ws->buffer_sent = wb;
|
||||
}
|
||||
|
||||
wl_surface_damage(ws->surface, rect->x, rect->y, rect->w, rect->h);
|
||||
|
||||
/* surface commit */
|
||||
wl_surface_commit(ws->surface);
|
||||
|
||||
eina_rectangle_free(rect);
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_swapper_buffer_release(void *data, struct wl_buffer *buffer EINA_UNUSED)
|
||||
{
|
||||
Wl_Buffer *wb = NULL;
|
||||
Wl_Swapper *ws = NULL;
|
||||
|
||||
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
/* try to get out Wl_Buffer struct */
|
||||
if (!(wb = data)) return;
|
||||
|
||||
/* invalidate buffer */
|
||||
wb->valid = EINA_FALSE;
|
||||
|
||||
ws = wb->ws;
|
||||
ws->in_use--;
|
||||
if (ws->delete_me && (ws->in_use <= 0))
|
||||
evas_swapper_free(ws);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef _EVAS_SWAPPER_H
|
||||
# define _EVAS_SWAPPER_H
|
||||
|
||||
#include "evas_engine.h"
|
||||
|
||||
typedef struct _Wl_Swapper Wl_Swapper;
|
||||
|
||||
Wl_Swapper *evas_swapper_setup(int dx, int dy, int w, int h, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *shm, struct wl_surface *surface);
|
||||
Wl_Swapper *evas_swapper_reconfigure(Wl_Swapper *ws, int dx, int dy, int w, int h, Outbuf_Depth depth, Eina_Bool alpha);
|
||||
void evas_swapper_swap(Wl_Swapper *ws, Eina_Rectangle *rects, unsigned int count);
|
||||
void evas_swapper_free(Wl_Swapper *ws);
|
||||
void *evas_swapper_buffer_map(Wl_Swapper *ws, int *w, int *h);
|
||||
void evas_swapper_buffer_unmap(Wl_Swapper *ws);
|
||||
int evas_swapper_buffer_state_get(Wl_Swapper *ws);
|
||||
void evas_swapper_buffer_idle_flush(Wl_Swapper *ws);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue