Add start of new wayland_egl engine code.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2013-05-30 06:53:50 +01:00
parent ae9246beae
commit c5355d32ee
1 changed files with 374 additions and 0 deletions

View File

@ -0,0 +1,374 @@
#include "evas_common.h"
#include "evas_engine.h"
#include "evas_gl_core_private.h"
#ifdef HAVE_DLSYM
# include <dlfcn.h>
#endif
#define EVAS_GL_NO_GL_H_CHECK 1
#include "Evas_GL.h"
enum
{
MERGE_BOUNDING,
MERGE_FULL
};
enum
{
MODE_FULL,
MODE_COPY,
MODE_DOUBLE,
MODE_TRIPLE
};
/* local structures */
typedef struct _Render_Engine Render_Engine;
struct _Render_Engine
{
Tilebuf *tb;
Tilebuf_Rect *rects;
Tilebuf_Rect *rects_prev[3];
Eina_Inlist *cur_rect;
Evas_GL_Wl_Window *win;
Evas_Engine_Info_Wayland_Egl *info;
Evas *Evas;
int w, h;
int end, mode, vsync;
int lost_back, prev_age;
Eina_Bool evgl_initted : 1;
};
/* local function prototypes */
typedef void (*_eng_fn) (void);
typedef _eng_fn (*glsym_func_eng_fn) ();
typedef void (*glsym_func_void) ();
typedef void *(*glsym_func_void_ptr) ();
typedef int (*glsym_func_int) ();
typedef unsigned int (*glsym_func_uint) ();
typedef const char *(*glsym_func_const_char_ptr) ();
static int evgl_init(Render_Engine *re);
#define EVGLINIT(_re, _ret) if (!evgl_init(_re)) return _ret;
/* local variables */
static int initted = 0;
static int gl_wins = 0;
static int have_buffer_age = 1;
/* function tables - filled in later (func and parent func) */
static Evas_Func func, pfunc;
/* external variables */
int _evas_engine_wl_egl_log_dom = -1;
#ifdef GL_GLES
# ifndef EGL_NATIVE_PIXMAP_KHR
# define EGL_NATIVE_PIXMAP_KHR 0x30b0
# endif
# ifndef EGL_BUFFER_AGE_EXT
# define EGL_BUFFER_AGE_EXT 0x313d
# endif
_eng_fn (*glsym_eglGetProcAddress) (const char *a) = NULL;
void *(*glsym_eglCreateImage) (EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL;
void (*glsym_eglDestroyImage) (EGLDisplay a, void *b) = NULL;
void (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL;
void *(*glsym_eglMapImageSEC) (void *a, void *b, int c, int d) = NULL;
unsigned int (*glsym_eglUnmapImageSEC) (void *a, void *b, int c) = NULL;
const char *(*glsym_eglQueryString) (EGLDisplay a, int name) = NULL;
void (*glsym_eglSwapBuffersRegion) (EGLDisplay a, void *b, EGLint c, const EGLint *d) = NULL;
#endif
/* local functions */
/* engine specific override functions */
static void *
eng_info(Evas *evas EINA_UNUSED)
{
Evas_Engine_Info_Wayland_Egl *info;
/* try to allocate space for our engine info */
if (!(info = calloc(1, sizeof(Evas_Engine_Info_Wayland_Egl))))
return NULL;
info->magic.magic = rand();
info->render_mode = EVAS_RENDER_MODE_BLOCKING;
return info;
}
static void
eng_info_free(Evas *evas EINA_UNUSED, void *info)
{
Evas_Engine_Info_Wayland_Egl *inf;
inf = (Evas_Engine_Info_Wayland_Egl *)info;
free(inf);
}
static int
eng_setup(Evas *evas, void *info)
{
Evas_Engine_Info_Wayland_Egl *inf;
Evas_Public_Data *epd;
Render_Engine *re;
inf = (Evas_Engine_Info_Wayland_Egl *)info;
epd = eo_data_scope_get(evas, EVAS_CLASS);
/* check for existing engine output */
if (!epd->engine.data.output)
{
/* try to allocate space for a new render engine */
if (!(re = calloc(1, sizeof(Render_Engine))))
return 0;
/* set some properties of the render engine */
re->info = inf;
re->evas = evas;
re->w = epd->output.w;
re->h = epd->output.h;
/* try to create a new window */
re->win = eng_window_new(inf->display, inf->surface, inf->screen,
inf->depth, re->w, re->h, inf->indirect,
inf->destination_alpha, inf->rotation);
if (!re->win)
{
free(re);
return 0;
}
/* tell the engine to use this render_engine for output */
epd->engine.data.output = re;
gl_wins++;
/* if we have not initialize gl & evas, do it */
if (!initted)
{
gl_symbols();
evas_common_cpu_init();
evas_common_blend_init();
evas_common_image_init();
evas_common_convert_init();
evas_common_scale_init();
evas_common_rectangle_init();
evas_common_polygon_init();
evas_common_line_init();
evas_common_font_init();
evas_common_draw_init();
evas_common_tilebuf_init();
gl_extn_veto(re);
initted = 1;
}
}
else
{
re = epd->engine.data.output;
if (_re_wincheck(re))
{
if ((re->info->info.display != re->win->disp) ||
(re->info->info.surface != re->win->surface) ||
(re->info->info.screen != re->win->screen) ||
(re->info->info.depth != re->win->depth) ||
(re->info->info.rotation != re->win->rot) ||
(re->info->info.destination_alpha != re->win->alpha))
{
Eina_Bool inc = EINA_FALSE;
if (re->win)
{
re->win->gl_context->references++;
eng_window_free(re->win);
inc = EINA_TRUE;
gl_wins--;
}
re->w = epd->output.w;
re->h = epd->output.h;
re->win = eng_window_new(re->info->info.display,
re->info->info.surface,
re->info->info.screen,
re->info->info.depth,
re->w, re->h,
re->info->info.indirect,
re->info->info.destination_alpha,
re->info->info.rotation);
eng_window_use(re->win);
if (re->win) gl_wins++;
if ((re->win) && (inc))
re->win->gl_context->references--;
}
else if ((re->win->w != epd->output.w) ||
(re->win->h != epd->output.h))
{
re->w = epd->output.w;
re->h = epd->output.h;
re->win->w = epd->output.w;
re->win->h = epd->output.h;
eng_window_use(re->win);
evas_gl_common_context_resize(re->win->gl_context,
re->win->w, re->win->h,
re->win->rot);
}
}
}
if ((s = getenv("EVAS_GL_SWAP_MODE")))
{
if ((!strcasecmp(s, "full")) || (!strcasecmp(s, "f")))
re->mode = MODE_FULL;
else if ((!strcasecmp(s, "copy")) || (!strcasecmp(s, "c")))
re->mode = MODE_COPY;
else if ((!strcasecmp(s, "double")) || (!strcasecmp(s, "d")) ||
(!strcasecmp(s, "2")))
re->mode = MODE_DOUBLE;
else if ((!strcasecmp(s, "triple")) || (!strcasecmp(s, "t")) ||
(!strcasecmp(s, "3")))
re->mode = MODE_TRIPLE;
}
else
{
// in most gl implementations - egl and glx here that we care about the TEND
// to either swap or copy backbuffer and front buffer, but strictly that is
// not true. technically backbuffer content is totally undefined after a swap
// and thus you MUST re-render all of it, thus MODE_FULL
re->mode = MODE_FULL;
// BUT... reality is that lmost every implementation copies or swaps so
// triple buffer mode can be used as it is a superset of double buffer and
// copy (though using those explicitly is more efficient). so let's play with
// triple buffer mdoe as a default and see.
// re->mode = MODE_TRIPLE;
// XXX: note - the above seems to break on some older intel chipsets and
// drivers. it seems we CANT depend on backbuffer staying around. bugger!
switch (info->swap_mode)
{
case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_FULL:
re->mode = MODE_FULL;
break;
case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_COPY:
re->mode = MODE_COPY;
break;
case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_DOUBLE:
re->mode = MODE_DOUBLE;
break;
case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_TRIPLE:
re->mode = MODE_TRIPLE;
break;
default:
break;
}
}
if (!re->win)
{
free(re);
return 0;
}
if (!epd->engine.data.output)
{
if (re->win)
{
eng_window_free(re->win);
gl_wins--;
}
free(re);
return 0;
}
re->tb = evas_common_tilebuf_new(re->win->w, re->win->h);
if (!re->tb)
{
if (re->win)
{
eng_window_free(re->win);
gl_wins--;
}
free(re);
return 0;
}
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
evas_common_tilebuf_tile_strict_set(re->tb, EINA_TRUE);
if (!epd->engine.data.context)
{
epd->engine.data.context =
epd->engine.func->context_new(epd->engine.data.output);
}
eng_window_use(re->win);
re->vsync = 0;
return 1;
}
/* evas module functions */
static int
module_open(Evas_Module *em)
{
/* check for valid module */
if (!em) return 0;
/* try to init evas_gl_common */
if (!evas_gl_common_module_open()) return 0;
/* get whatever engine module we inherit from */
if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
/* setup logging domain */
if (_evas_engine_wl_egl_log_dom < 0)
{
_evas_engine_wl_egl_log_dom =
eina_log_domain_register("evas-wayland_egl", EVAS_DEFAULT_LOG_COLOR);
}
if (_evas_engine_wl_egl_log_dom < 0)
{
EINA_LOG_ERR("Can not create a module log domain.");
return 0;
}
/* store functions for later use */
func = pfunc;
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
ORD(info);
ORD(info_free);
ORD(setup);
/* advertise out which functions we support */
em->functions = (void *)(&func);
return 1;
}
static void
module_close(Evas_Module *em EINA_UNUSED)
{
eina_log_domain_unregister(_evas_engine_wl_egl_log_dom);
evas_gl_common_module_close();
}
static Evas_Module_Api evas_modapi =
{
EVAS_MODULE_API_VERSION, "wayland_egl", "none", {module_open, module_close}
};
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, wayland_egl);
#ifndef EVAS_STATIC_BUILD_WAYLAND_EGL
EVAS_EINA_MODULE_DEFINE(engine, wayland_egl);
#endif