forked from enlightenment/efl
Add start of new wayland_egl engine code.
Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
parent
ae9246beae
commit
c5355d32ee
|
@ -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
|
Loading…
Reference in New Issue