Begin work on getting evas drm engine to actually render

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2014-01-10 07:28:43 +00:00
parent a7376722f7
commit 1984303de1
5 changed files with 1439 additions and 97 deletions

View File

@ -11,6 +11,9 @@ struct _Evas_Engine_Info_Drm
struct
{
void *gbm;
unsigned int format;
unsigned int rotation, depth;
Eina_Bool destination_alpha : 1;
} info;

View File

@ -1,6 +1,3 @@
#include "evas_common_private.h"
#include "evas_private.h"
#include "Evas_Engine_Drm.h"
#include "evas_engine.h"
/* local structures */
@ -9,112 +6,207 @@ typedef struct _Render_Engine Render_Engine;
struct _Render_Engine
{
Evas_Engine_Info_Drm *info;
Outbuf *ob;
Tilebuf *tb;
Tilebuf_Rect *rects;
Tilebuf_Rect *prev_rects[3];
Outbuf *ob;
Eina_Inlist *cur_rect;
short mode;
Eina_Inlist *cur_rect;
Eina_Bool end : 1;
Eina_Bool lost_back : 1;
/* function pointers for output buffer functions that we can
* override based on if we are swapping or not */
void (*outbuf_free)(Outbuf *ob);
void (*outbuf_reconfigure)(Outbuf *ob, int x, int y, int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha);
RGBA_Image *(*outbuf_update_region_new)(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
void (*outbuf_update_region_push)(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
void (*outbuf_update_region_free)(Outbuf *ob, RGBA_Image *update);
void (*outbuf_flush)(Outbuf *ob);
void (*outbuf_idle_flush)(Outbuf *ob);
};
/* local function prototypes */
static void *_output_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha, int swap);
static void *_output_engine_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool destination_alpha, int try_swap);
static Tilebuf_Rect *_merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3);
/* function tables - filled in later (func and parent func) */
/* 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);
static void eng_output_resize(void *data, int w, int h);
static void eng_output_tile_size_set(void *data, int w, int h);
static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
static void eng_output_redraws_clear(void *data);
static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch);
static void eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h, Evas_Render_Mode render_mode);
static void eng_output_flush(void *data, Evas_Render_Mode render_mode);
static void eng_output_idle_flush(void *data);
/* local variables */
static Evas_Func func, pfunc;
/* external variables */
int _evas_engine_drm_log_dom;
int _evas_engine_drm_log_dom = -1;
/* local functions */
static void *
_output_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha, int swap)
_output_engine_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool destination_alpha, int try_swap)
{
Render_Engine *re;
Render_Engine *re = NULL;
/* try to allocate space for our render engine structure */
if (!(re = calloc(1, sizeof(Render_Engine))))
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* try to allocate a new render engine */
if (!(re = calloc(1, sizeof(Render_Engine))))
return NULL;
/* try to create a new tilebuffer */
/* try to create a new tilebuf first */
if (!(re->tb = evas_common_tilebuf_new(w, h)))
{
free(re);
return NULL;
}
/* set tilesize */
/* set tile size for the tile buffer */
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
if (swap)
if (try_swap)
{
/* free any existing outbuf */
if (re->ob) evas_outbuf_free(re->ob);
/* try to create new outbuf */
if (!(re->ob = evas_outbuf_setup(w, h, rotation, depth, alpha)))
if ((re->ob = evas_swapbuf_setup(w, h, rotation, depth,
destination_alpha)))
{
if (re->tb) evas_common_tilebuf_free(re->tb);
free(re);
return NULL;
re->outbuf_free = evas_swapbuf_free;
re->outbuf_reconfigure = evas_swapbuf_reconfigure;
re->outbuf_update_region_new = evas_swapbuf_update_region_new;
re->outbuf_update_region_push = evas_swapbuf_update_region_push;
re->outbuf_update_region_free = evas_swapbuf_update_region_free;
re->outbuf_flush = evas_swapbuf_flush;
re->outbuf_idle_flush = evas_swapbuf_idle_flush;
}
}
/* return the allocated render_engine structure */
/* if creating an output buffer failed, then return NULL */
if (!re->ob)
{
if (re->tb) evas_common_tilebuf_free(re->tb);
free(re);
return NULL;
}
/* return allocated render engine */
return re;
}
/* engine api functions */
static Tilebuf_Rect *
_merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3)
{
Tilebuf_Rect *r, *rects;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (r1)
{
EINA_INLIST_FOREACH(EINA_INLIST_GET(r1), r)
evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
}
if (r2)
{
EINA_INLIST_FOREACH(EINA_INLIST_GET(r2), r)
evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
}
if (r3)
{
EINA_INLIST_FOREACH(EINA_INLIST_GET(r3), r)
evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h);
}
rects = evas_common_tilebuf_get_render_rects(tb);
/*
// bounding box -> make a bounding box single region update of all regions.
// yes we could try and be smart and figure out size of regions, how far
// apart etc. etc. to try and figure out an optimal "set". this is a tradeoff
// between multiple update regions to render and total pixels to render.
if (rects)
{
px1 = rects->x; py1 = rects->y;
px2 = rects->x + rects->w; py2 = rects->y + rects->h;
EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
{
if (r->x < x1) px1 = r->x;
if (r->y < y1) py1 = r->y;
if ((r->x + r->w) > x2) px2 = r->x + r->w;
if ((r->y + r->h) > y2) py2 = r->y + r->h;
}
evas_common_tilebuf_free_render_rects(rects);
rects = calloc(1, sizeof(Tilebuf_Rect));
if (rects)
{
rects->x = px1;
rects->y = py1;
rects->w = px2 - px1;
rects->h = py2 - py1;
}
}
*/
evas_common_tilebuf_clear(tb);
return rects;
}
/* engine functions */
static void *
eng_info(Evas *evas EINA_UNUSED)
eng_info(Evas *eo_evas EINA_UNUSED)
{
Evas_Engine_Info_Drm *info;
/* try to allocate space for our engine info structure */
/* try to allocate space for engine info */
if (!(info = calloc(1, sizeof(Evas_Engine_Info_Drm))))
return NULL;
/* set some engine default properties */
/* fill in default engine info fields */
info->magic.magic = rand();
info->render_mode = EVAS_RENDER_MODE_BLOCKING;
/* return allocated engine info */
return info;
}
static void
eng_info_free(Evas *evas EINA_UNUSED, void *einfo)
eng_info_free(Evas *eo_evas EINA_UNUSED, void *einfo)
{
Evas_Engine_Info_Drm *info;
/* free the engine info */
/* try to free previously allocated engine info */
if ((info = (Evas_Engine_Info_Drm *)einfo))
free(info);
}
static int
eng_setup(Evas *evas, void *einfo)
eng_setup(Evas *eo_evas, void *einfo)
{
Evas_Engine_Info_Drm *info;
Evas_Public_Data *epd;
Render_Engine *re;
Render_Engine *re = NULL;
/* try to cast to our engine info structure */
if (!(info = (Evas_Engine_Info_Drm *)einfo)) return 0;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* try to get the evas public data */
if (!(epd = eo_data_scope_get(evas, EVAS_CLASS))) return 0;
/* try to cast the engine info to our engine info */
if (!(info = (Evas_Engine_Info_Drm *)einfo))
return 0;
/* check for valid engine output */
/* try to get evas public data from the canvas */
if (!(epd = eo_data_scope_get(eo_evas, EVAS_CLASS)))
return 0;
/* test for valid engine output */
if (!(re = epd->engine.data.output))
{
static int swap = -1;
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 */
@ -130,47 +222,66 @@ eng_setup(Evas *evas, void *einfo)
evas_common_draw_init();
evas_common_tilebuf_init();
/* check if swapping is disabled */
if (swap == -1)
if (try_swap == -1)
{
if (getenv("EVAS_DRM_NO_SWAP")) swap = 0;
else swap = 1;
/* check for env var to see if we should try swapping */
if (getenv("EVAS_NO_DRM_SWAPBUF")) try_swap = 0;
else try_swap = 1;
}
/* try to create a new render_engine */
if (!(re = _output_setup(epd->output.w, epd->output.h,
info->info.rotation, info->info.depth,
info->info.destination_alpha, swap)))
if (!(re =
_output_engine_setup(epd->output.w, epd->output.h,
info->info.rotation, info->info.depth,
info->info.destination_alpha,
try_swap)))
return 0;
re->info = info;
}
else
{
/* if we have an existing outbuf, free it */
if (re->ob) evas_outbuf_free(re->ob);
int ponebuf = 0;
/* try to create a new outbuf */
if (!(re->ob =
evas_outbuf_setup(epd->output.w, epd->output.h,
info->info.rotation, info->info.depth,
info->info.destination_alpha)))
return 0;
if ((re) && (re->ob)) ponebuf = re->ob->onebuf;
/* free any existing tile buffer */
if (re->tb) evas_common_tilebuf_free(re->tb);
/* we have an existing output buffer, free it */
if (re->ob) re->outbuf_free(re->ob);
/* create new tile buffer */
if ((re->tb = evas_common_tilebuf_new(epd->output.w, epd->output.h)))
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
if ((re->ob = evas_swapbuf_setup(epd->output.w, epd->output.h,
info->info.rotation,
info->info.depth,
info->info.destination_alpha)))
{
re->outbuf_free = evas_swapbuf_free;
re->outbuf_reconfigure = evas_swapbuf_reconfigure;
re->outbuf_update_region_new = evas_swapbuf_update_region_new;
re->outbuf_update_region_push = evas_swapbuf_update_region_push;
re->outbuf_update_region_free = evas_swapbuf_update_region_free;
re->outbuf_flush = evas_swapbuf_flush;
re->outbuf_idle_flush = evas_swapbuf_idle_flush;
}
re->info = info;
if ((re) && (re->ob)) re->ob->onebuf = ponebuf;
}
/* update the info structure pointer */
re->info = info;
/* reassign engine output */
/* reassign render engine to output */
epd->engine.data.output = re;
if (!epd->engine.data.output) return 0;
/* check for valid engine context */
if (!epd->engine.data.context)
{
/* create a context if needed */
epd->engine.data.context =
epd->engine.func->context_new(epd->engine.data.output);
}
/* return success */
return 1;
}
@ -179,16 +290,19 @@ eng_output_free(void *data)
{
Render_Engine *re;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if ((re = data))
{
if (re->ob) evas_outbuf_free(re->ob);
if (re->tb) evas_common_tilebuf_free(re->tb);
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
if (re->prev_rects[0])
re->outbuf_free(re->ob);
evas_common_tilebuf_free(re->tb);
if (re->rects)
evas_common_tilebuf_free_render_rects(re->rects);
if (re->prev_rects[0])
evas_common_tilebuf_free_render_rects(re->prev_rects[0]);
if (re->prev_rects[1])
if (re->prev_rects[1])
evas_common_tilebuf_free_render_rects(re->prev_rects[1]);
if (re->prev_rects[2])
if (re->prev_rects[2])
evas_common_tilebuf_free_render_rects(re->prev_rects[2]);
free(re);
}
@ -197,52 +311,305 @@ eng_output_free(void *data)
evas_common_image_shutdown();
}
/* module api functions */
static int
static void
eng_output_resize(void *data, int w, int h)
{
Render_Engine *re;
Evas_Engine_Info_Drm *info;
/* int dx = 0, dy = 0; */
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!(re = (Render_Engine *)data)) return;
if (!(info = re->info)) return;
/* if (info->info.edges & 4) */
/* { */
/* if ((info->info.rotation == 90) || (info->info.rotation == 270)) */
/* dx = re->ob->h - h; */
/* else */
/* dx = re->ob->w - w; */
/* } */
/* if (info->info.edges & 1) */
/* { */
/* if ((info->info.rotation == 90) || (info->info.rotation == 270)) */
/* dy = re->ob->w - w; */
/* else */
/* dy = re->ob->h - h; */
/* } */
re->outbuf_reconfigure(re->ob, 0, 0, w, h,
info->info.rotation, info->info.depth,
info->info.destination_alpha);
evas_common_tilebuf_free(re->tb);
if ((re->tb = evas_common_tilebuf_new(w, h)))
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
}
static void
eng_output_tile_size_set(void *data, int w, int h)
{
Render_Engine *re;
if (!(re = (Render_Engine *)data)) return;
if (re->tb) evas_common_tilebuf_set_tile_size(re->tb, w, h);
}
static void
eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
{
Render_Engine *re;
if (!(re = (Render_Engine *)data)) return;
evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
}
static void
eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
{
Render_Engine *re;
if (!(re = (Render_Engine *)data)) return;
if (re->tb) evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
}
static void
eng_output_redraws_clear(void *data)
{
Render_Engine *re;
if (!(re = (Render_Engine *)data)) return;
if (re->tb) evas_common_tilebuf_clear(re->tb);
}
static void *
eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
{
Render_Engine *re;
RGBA_Image *surface;
Tilebuf_Rect *rect;
Eina_Bool first_rect = EINA_FALSE;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
#define CLEAR_PREV_RECTS(x) \
do { \
if (re->prev_rects[x]) \
evas_common_tilebuf_free_render_rects(re->prev_rects[x]); \
re->prev_rects[x] = NULL; \
} while (0)
re = (Render_Engine *)data;
if (re->end)
{
re->end = 0;
return NULL;
}
if (!re->rects)
{
re->mode = evas_swapbuf_state_get(re->ob);
re->rects = evas_common_tilebuf_get_render_rects(re->tb);
if (re->rects)
{
if ((re->lost_back) || (re->mode == MODE_FULL))
{
/* if we lost our backbuffer since the last frame redraw all */
re->lost_back = 0;
evas_common_tilebuf_add_redraw(re->tb, 0, 0, re->ob->w, re->ob->h);
evas_common_tilebuf_free_render_rects(re->rects);
re->rects = evas_common_tilebuf_get_render_rects(re->tb);
}
/* ensure we get rid of previous rect lists we dont need if mode
* changed/is appropriate */
evas_common_tilebuf_clear(re->tb);
CLEAR_PREV_RECTS(2);
re->prev_rects[2] = re->prev_rects[1];
re->prev_rects[1] = re->prev_rects[0];
re->prev_rects[0] = re->rects;
re->rects = NULL;
switch (re->mode)
{
case MODE_FULL:
case MODE_COPY: // no prev rects needed
re->rects =
_merge_rects(re->tb, re->prev_rects[0], NULL, NULL);
break;
case MODE_DOUBLE: // double mode - only 1 level of prev rect
re->rects =
_merge_rects(re->tb, re->prev_rects[0], re->prev_rects[1], NULL);
break;
case MODE_TRIPLE: // keep all
re->rects =
_merge_rects(re->tb, re->prev_rects[0], re->prev_rects[1], re->prev_rects[2]);
break;
default:
break;
}
first_rect = EINA_TRUE;
}
evas_common_tilebuf_clear(re->tb);
re->cur_rect = EINA_INLIST_GET(re->rects);
}
if (!re->cur_rect) return NULL;
rect = (Tilebuf_Rect *)re->cur_rect;
if (re->rects)
{
switch (re->mode)
{
case MODE_COPY:
case MODE_DOUBLE:
case MODE_TRIPLE:
rect = (Tilebuf_Rect *)re->cur_rect;
*x = rect->x;
*y = rect->y;
*w = rect->w;
*h = rect->h;
*cx = rect->x;
*cy = rect->y;
*cw = rect->w;
*ch = rect->h;
re->cur_rect = re->cur_rect->next;
break;
case MODE_FULL:
re->cur_rect = NULL;
if (x) *x = 0;
if (y) *y = 0;
if (w) *w = re->ob->w;
if (h) *h = re->ob->h;
if (cx) *cx = 0;
if (cy) *cy = 0;
if (cw) *cw = re->ob->w;
if (ch) *ch = re->ob->h;
break;
default:
break;
}
if (first_rect)
{
// do anything needed for the first frame
}
surface =
re->outbuf_update_region_new(re->ob,
*x, *y, *w, *h,
cx, cy, cw, ch);
if (!re->cur_rect) re->end = EINA_TRUE;
return surface;
}
return NULL;
}
static void
eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h, Evas_Render_Mode render_mode)
{
Render_Engine *re;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
if (!(re = (Render_Engine *)data)) return;
#if defined(BUILD_PIPE_RENDER)
evas_common_pipe_map_begin(surface);
#endif
re->outbuf_update_region_push(re->ob, surface, x, y, w, h);
re->outbuf_update_region_free(re->ob, surface);
evas_common_cpu_end_opt();
}
static void
eng_output_flush(void *data, Evas_Render_Mode render_mode)
{
Render_Engine *re;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
if (!(re = (Render_Engine *)data)) return;
re->outbuf_flush(re->ob);
if (re->rects)
{
evas_common_tilebuf_free_render_rects(re->rects);
re->rects = NULL;
}
}
static void
eng_output_idle_flush(void *data)
{
Render_Engine *re;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!(re = (Render_Engine *)data)) return;
re->outbuf_idle_flush(re->ob);
}
/* module functions */
static int
module_open(Evas_Module *em)
{
/* check for valid evas module */
if (!em) return 0;
/* try to inherit functions from software_generic engine */
if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
/* try to create eina logging domain */
/* try to create our logging domain */
_evas_engine_drm_log_dom =
eina_log_domain_register("evas-drm", EVAS_DEFAULT_LOG_COLOR);
/* if we could not create a logging domain, error out */
if (_evas_engine_drm_log_dom < 0)
{
EINA_LOG_ERR("Can not create a module log domain.");
/* creating the logging domain failed. notify user */
EINA_LOG_ERR("Could not create a module log domain.");
/* return failure */
return 0;
}
/* store parent functions */
/* 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 */
func = pfunc;
/* override the methods we provide */
EVAS_API_OVERRIDE(info, &func, eng_);
EVAS_API_OVERRIDE(info_free, &func, eng_);
EVAS_API_OVERRIDE(setup, &func, eng_);
EVAS_API_OVERRIDE(output_free, &func, eng_);
/* override any engine specific functions that we provide */
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
ORD(info);
ORD(info_free);
ORD(setup);
ORD(output_free);
ORD(output_resize);
ORD(output_tile_size_set);
ORD(output_redraws_rect_add);
ORD(output_redraws_rect_del);
ORD(output_redraws_clear);
ORD(output_redraws_next_update_get);
ORD(output_redraws_next_update_push);
ORD(output_flush);
ORD(output_idle_flush);
/* advertise our engine functions */
/* advertise out our own api */
em->functions = (void *)(&func);
/* return success */
return 1;
}
static void
module_close(Evas_Module *em EINA_UNUSED)
{
/* unregister the eina log domain for this engine */
eina_log_domain_unregister(_evas_engine_drm_log_dom);
/* if we have the log domain, unregister it */
if (_evas_engine_drm_log_dom > -1)
eina_log_domain_unregister(_evas_engine_drm_log_dom);
}
static Evas_Module_Api evas_modapi =
static Evas_Module_Api evas_modapi =
{
EVAS_MODULE_API_VERSION, "drm", "none", { module_open, module_close }
EVAS_MODULE_API_VERSION, "drm", "none", {module_open, module_close}
};
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, drm);

View File

@ -1,5 +1,29 @@
#ifndef EVAS_ENGINE_H
# define EVAS_ENGINE_H
#ifndef _EVAS_ENGINE_H
# define _EVAS_ENGINE_H
# define LOGFNS 1
# ifdef LOGFNS
# include <stdio.h>
# define LOGFN(fl, ln, fn) printf("-EVAS-DRM: %25s: %5i - %s\n", fl, ln, fn);
# else
# define LOGFN(fl, ln, fn)
# endif
# include "evas_common_private.h"
# include "evas_macros.h"
# include "evas_private.h"
# include "Evas.h"
# include "Evas_Engine_Drm.h"
# include <xf86drm.h>
# include <xf86drmMode.h>
# include <drm_fourcc.h>
# ifdef GL_GLES
# include <EGL/egl.h>
# define GL_GLEXT_PROTOTYPES
# endif
extern int _evas_engine_drm_log_dom;
@ -28,9 +52,19 @@ extern int _evas_engine_drm_log_dom;
# endif
# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_drm_log_dom, __VA_ARGS__)
typedef enum _Outbuf_Depth Outbuf_Depth;
typedef struct _Wl_Swapper Wl_Swapper;
typedef struct _Outbuf Outbuf;
enum
enum _Outbuf_Depth
{
OUTBUF_DEPTH_NONE,
OUTBUF_DEPTH_ARGB_32BPP_8888_8888,
OUTBUF_DEPTH_RGB_32BPP_8888_8888,
OUTBUF_DEPTH_LAST
};
enum
{
MODE_FULL,
MODE_COPY,
@ -41,12 +75,49 @@ enum
struct _Outbuf
{
int w, h;
unsigned int rotation, depth;
Eina_Bool destination_alpha : 1;
unsigned int rotation;
Outbuf_Depth depth;
int onebuf;
struct
{
/* struct gbm_device *gbm; */
/* unsigned int format; */
/* swapper */
void *swapper;
/* one big buffer for updates. flushed on idle_flush */
RGBA_Image *onebuf;
Eina_Array onebuf_regions;
/* a list of pending regions to write out */
Eina_List *pending_writes;
/* list of previous frame pending regions to write out */
Eina_List *prev_pending_writes;
Eina_Bool destination_alpha : 1;
} priv;
};
Outbuf *evas_outbuf_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha);
void evas_outbuf_free(Outbuf *ob);
void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha);
Outbuf *evas_swapbuf_setup(int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha);
void evas_swapbuf_free(Outbuf *ob);
void evas_swapbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha);
RGBA_Image *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);
void evas_swapbuf_idle_flush(Outbuf *ob EINA_UNUSED);
int evas_swapbuf_state_get(Outbuf *ob);
Wl_Swapper *evas_swapper_setup(int dx, int dy, int w, int h, Outbuf_Depth depth, Eina_Bool alpha, int fd);
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

View File

@ -0,0 +1,521 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
//#include <sys/mman.h>
#ifdef EVAS_CSERVE2
# include "evas_cs2_private.h"
#endif
#include "evas_engine.h"
#define RED_MASK 0x00ff0000
#define GREEN_MASK 0x0000ff00
#define BLUE_MASK 0x000000ff
/* local function prototypes */
Outbuf *
evas_swapbuf_setup(int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha)
{
Outbuf *ob = NULL;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* try to allocate a new Outbuf */
if (!(ob = calloc(1, sizeof(Outbuf))))
return NULL;
/* set some properties */
ob->w = w;
ob->h = h;
ob->rotation = rotation;
ob->depth = depth;
ob->priv.destination_alpha = alpha;
if ((ob->rotation == 0) || (ob->rotation == 180))
{
ob->priv.swapper =
evas_swapper_setup(0, 0, w, h, depth, alpha);
}
else if ((ob->rotation == 90) || (ob->rotation == 270))
{
ob->priv.swapper =
evas_swapper_setup(0, 0, h, w, depth, alpha);
}
/* check that a swapper was created */
if (!ob->priv.swapper)
{
/* free the Outbuf structure allocation */
free(ob);
return NULL;
}
/* 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);
evas_swapbuf_idle_flush(ob);
evas_swapper_free(ob->priv.swapper);
eina_array_flush(&ob->priv.onebuf_regions);
/* free the allocated structure */
free(ob);
}
void
evas_swapbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, unsigned int rotation, Outbuf_Depth depth, Eina_Bool alpha)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* check for valid output buffer */
if (!ob) return;
/* 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);
}
else if ((ob->rotation == 90) || (ob->rotation == 270))
{
ob->priv.swapper =
evas_swapper_setup(x, y, h, w, depth, alpha);
}
}
RGBA_Image *
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;
if (!(data = evas_swapper_buffer_map(ob->priv.swapper, &bw, &bh)))
{
ERR("NO BUFFER 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;
}
/* 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)
{
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_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);
}
void
evas_swapbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
{
/* NB: nothing to do, they are cleaned up on flush */
}
void
evas_swapbuf_flush(Outbuf *ob)
{
Eina_Rectangle *rects;
RGBA_Image *img;
unsigned int n = 0, i = 0;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* check for valid output buffer */
if (!ob) return;
/* check for pending writes */
if (!ob->priv.pending_writes)
{
Eina_Rectangle *rect;
Eina_Array_Iterator it;
/* get number of buffer regions */
n = eina_array_count_get(&ob->priv.onebuf_regions);
if (n == 0) return;
/* allocate rectangles */
if (!(rects = alloca(n * sizeof(Eina_Rectangle)))) return;
/* loop the buffer regions and assign to rects */
EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
rects[i] = *rect;
/* unmap the buffer */
evas_swapper_buffer_unmap(ob->priv.swapper);
/* force a buffer swap */
evas_swapper_swap(ob->priv.swapper, rects, n);
/* clean array */
eina_array_clean(&ob->priv.onebuf_regions);
img = ob->priv.onebuf;
ob->priv.onebuf = NULL;
if (img)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_close(&img->cache_entry);
else
#endif
evas_cache_image_drop(&img->cache_entry);
}
}
else
{
/* get number of pending writes */
n = eina_list_count(ob->priv.pending_writes);
if (n == 0) return;
/* allocate rectangles */
if (!(rects = alloca(n * sizeof(Eina_Rectangle)))) return;
/* loop the pending writes */
EINA_LIST_FREE(ob->priv.pending_writes, img)
{
Eina_Rectangle *rect;
int x = 0, y = 0, w = 0, h = 0;
if (!(rect = img->extended_info)) continue;
x = rect->x; y = rect->y; w = rect->w; h = rect->h;
/* based on rotation, set rectangle position */
if (ob->rotation == 0)
{
rects[i].x = x;
rects[i].y = y;
}
else if (ob->rotation == 90)
{
rects[i].x = y;
rects[i].y = (ob->w - x - w);
}
else if (ob->rotation == 180)
{
rects[i].x = (ob->w - x - w);
rects[i].y = (ob->h - y - h);
}
else if (ob->rotation == 270)
{
rects[i].x = (ob->h - y - h);
rects[i].y = x;
}
/* based on rotation, set rectangle size */
if ((ob->rotation == 0) || (ob->rotation == 180))
{
rects[i].w = w;
rects[i].h = h;
}
else if ((ob->rotation == 90) || (ob->rotation == 270))
{
rects[i].w = h;
rects[i].h = w;
}
eina_rectangle_free(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);
i++;
}
/* unmap the buffer */
evas_swapper_buffer_unmap(ob->priv.swapper);
/* force a buffer swap */
evas_swapper_swap(ob->priv.swapper, rects, n);
}
}
void
evas_swapbuf_idle_flush(Outbuf *ob EINA_UNUSED)
{
// 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); */
}
int
evas_swapbuf_state_get(Outbuf *ob)
{
int mode = 0;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ob->priv.swapper) return MODE_FULL;
mode = evas_swapper_buffer_state_get(ob->priv.swapper);
return mode;
}
/* local functions */

View File

@ -0,0 +1,380 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/mman.h>
#ifdef EVAS_CSERVE2
# include "evas_cs2_private.h"
#endif
#include "evas_engine.h"
/* local structures */
typedef struct _Wl_Buffer Wl_Buffer;
struct _Wl_Buffer
{
Wl_Swapper *ws;
int w, h;
/* struct gbm_bo *bo; */
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, drm_fd;
int dx, dy, w, h, depth;
int buff_cur, buff_num;
/* struct gbm_device *gbm; */
/* unsigned int format; */
/* 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);
/* local variables */
Wl_Swapper *
evas_swapper_setup(int dx, int dy, int w, int h, Outbuf_Depth depth, Eina_Bool alpha, int fd)
{
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->drm_fd = fd;
/* double buffer by default */
ws->buff_num = 2;
/* check for buffer override number */
if ((num_buffers = getenv("EVAS_DRM_BUFFERS")))
{
int num = 0;
num = atoi(num_buffers);
if (num <= 0) num = 1;
if (num > 3) num = 3;
ws->buff_num = num;
}
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]));
ws->dx += dx;
ws->dy += dy;
ws->w = w;
ws->h = h;
ws->depth = depth;
ws->alpha = alpha;
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;
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 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 i = 0, n = 0, count = 0;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
for (i = 0; i < ws->buff_num; i++)
{
n = (ws->buff_num + ws->buff_cur - (i)) % ws->buff_num;
if (ws->buff[n].valid) count++;
else break;
}
if (count == ws->buff_num)
{
if (count == 1) return MODE_COPY;
else if (count == 2) return MODE_DOUBLE;
else if (count == 3) return MODE_TRIPLE;
}
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_buffer_new(Wl_Swapper *ws, Wl_Buffer *wb)
{
int id;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
wb->w = ws->w;
wb->h = ws->h;
struct drm_mode_create_dumb carg;
struct drm_mode_destroy_dumb darg;
struct drm_mode_map_dump marg;
memset(&carg, 0, sizeof(struct drm_mode_create_dumb));
carb.bpp = 32;
carg.width = wb->w;
carg.height = wb->h;
drmIoctl(ws->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg);
drmModeAddFB(ws->drm_fd, wb->w, wb->h, 24, 32, carg.pitch, carg.handle, &id);
memset(&marg, 0, sizeof(struct drm_mode_map_dumb));
marg.handle = carg.handle;
drmIoctl(ws->drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
wb->data = mmap(0, carg.size, PROT_WRITE, MAP_SHARED,
ws->drm_fd, marg.offset);
memset(wb->data, 0, carg.size);
/* 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->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))
{
/* 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); */
}