Evas GL: Fix sync, wlbuffer and image egl ext functions

Before this patch, those EGL/EvasGL functions can not work
without a current context. But EGL does not require any
current context for those to work, or at least, this should
be left to the driver to decide.

Evas GL was only able to get a pointer to the display
if a context was current.

The display pointer should be infered from Evas_GL unless
we can find a current display. EGL does not require a
context to be current in most of these function calls.

This should bring evasgl a little bit closer to EGL in terms
of behaviour (those are EGL-only extensions, btw).

Thanks @spacegrapher for the quick review

@fix
This commit is contained in:
Jean-Philippe Andre 2015-07-16 22:25:36 +09:00
parent 51b097c014
commit 8942c0c29b
8 changed files with 91 additions and 53 deletions

View File

@ -326,7 +326,7 @@ evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
surf = NULL;
}
// Internal function - called from evas_gl_core.c
// Internal functions - called from evas_gl_core.c
static void *
evas_gl_native_context_get(void *context)
{
@ -335,6 +335,17 @@ evas_gl_native_context_get(void *context)
return ctx->data;
}
static void *
evas_gl_engine_data_get(void *evgl)
{
Evas_GL *evasgl = evgl;
if (!evasgl) return NULL;
if (!evasgl->evas) return NULL;
return evasgl->evas->engine.data.output;
}
EAPI Evas_GL_Context *
evas_gl_context_version_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx,
Evas_GL_Context_Version version)
@ -367,7 +378,7 @@ evas_gl_context_version_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx,
ctx->version = version;
ctx->data = evas_gl->evas->engine.func->gl_context_create
(evas_gl->evas->engine.data.output, share_ctx ? share_ctx->data : NULL,
version, &evas_gl_native_context_get);
version, &evas_gl_native_context_get, &evas_gl_engine_data_get);
// Set a few variables
if (!ctx->data)

View File

@ -1370,7 +1370,7 @@ struct _Evas_Func
void *(*gl_surface_create) (void *data, void *config, int w, int h);
void *(*gl_pbuffer_surface_create) (void *data, void *config, int w, int h, int const *attrib_list);
int (*gl_surface_destroy) (void *data, void *surface);
void *(*gl_context_create) (void *data, void *share_context, int version, void *(*native_context_get)(void *ctx));
void *(*gl_context_create) (void *data, void *share_context, int version, void *(*native_context_get)(void *ctx), void *(*engine_data_get)(void *evasgl));
int (*gl_context_destroy) (void *data, void *context);
int (*gl_make_current) (void *data, void *surface, void *context);
const char *(*gl_string_query) (void *data, int name);

View File

@ -115,7 +115,7 @@ struct wl_resource;
// Evas extensions from EGL extensions
#ifdef GL_GLES
#define EGLDISPLAY_GET() _evgl_egl_display_get(__FUNCTION__)
#define EGLDISPLAY_GET(a) _evgl_egl_display_get(__FUNCTION__, a)
// this struct defines an EvasGLImage when using EGL
typedef struct _EvasGLImage {
@ -124,13 +124,21 @@ typedef struct _EvasGLImage {
} EvasGLImage_EGL;
static EGLDisplay
_evgl_egl_display_get(const char *function)
_evgl_egl_display_get(const char *function, Evas_GL *evgl)
{
EGLDisplay dpy = EGL_NO_DISPLAY;
EVGL_Resource *rsc;
if (!evgl_engine || !evgl_engine->funcs || !evgl_engine->funcs->display_get)
{
ERR("%s: Invalid Engine... (Can't acccess EGL Display)\n", function);
evas_gl_common_error_set(NULL, EVAS_GL_BAD_DISPLAY);
return EGL_NO_DISPLAY;
}
if (!(rsc=_evgl_tls_resource_get()))
{
if (evgl) goto fallback;
ERR("%s: Unable to execute GL command. Error retrieving tls", function);
evas_gl_common_error_set(NULL, EVAS_GL_NOT_INITIALIZED);
return EGL_NO_DISPLAY;
@ -138,22 +146,18 @@ _evgl_egl_display_get(const char *function)
if (!rsc->current_eng)
{
if (evgl) goto fallback;
ERR("%s: no current engine set; ensure you've called evas_gl_make_current()", function);
evas_gl_common_error_set(NULL, EVAS_GL_NOT_INITIALIZED);
return EGL_NO_DISPLAY;
}
if ((evgl_engine) && (evgl_engine->funcs->display_get))
{
dpy = (EGLDisplay)evgl_engine->funcs->display_get(rsc->current_eng);
return dpy;
}
else
{
ERR("%s: Invalid Engine... (Can't acccess EGL Display)\n", function);
evas_gl_common_error_set(NULL, EVAS_GL_BAD_DISPLAY);
return EGL_NO_DISPLAY;
}
dpy = (EGLDisplay) evgl_engine->funcs->display_get(rsc->current_eng);
return dpy;
fallback:
dpy = (EGLDisplay) evgl_engine->funcs->display_get(_evgl_engine_data_get(evgl));
return dpy;
}
static void *
@ -198,29 +202,38 @@ _evgl_eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx,
static void *
evgl_evasglCreateImage(int target, void* buffer, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(NULL);
EGLContext ctx = EGL_NO_CONTEXT;
if (!dpy) return NULL;
if (!dpy)
{
WRN("No display found, use evasglCreateImageForContext instead.");
return NULL;
}
/* EGL_NO_CONTEXT will always fail for TEXTURE_2D */
if (target == EVAS_GL_TEXTURE_2D)
{
ctx = eglGetCurrentContext();
INF("Creating EGL image based on the current context: %p", ctx);
DBG("Creating EGL image based on the current context: %p", ctx);
}
return _evgl_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
}
static void *
evgl_evasglCreateImageForContext(Evas_GL *evasgl EINA_UNUSED, Evas_GL_Context *evasctx,
evgl_evasglCreateImageForContext(Evas_GL *evasgl, Evas_GL_Context *evasctx,
int target, void* buffer, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evasgl);
EGLContext ctx = EGL_NO_CONTEXT;
if (!evasgl || !dpy) return NULL;
if (!dpy || !evasgl)
{
ERR("Evas_GL can not be NULL here.");
evas_gl_common_error_set(NULL, EVAS_GL_BAD_DISPLAY);
return NULL;
}
ctx = _evgl_native_context_get(evasctx);
return _evgl_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
@ -229,13 +242,9 @@ evgl_evasglCreateImageForContext(Evas_GL *evasgl EINA_UNUSED, Evas_GL_Context *e
static void
evgl_evasglDestroyImage(EvasGLImage image)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EvasGLImage_EGL *img = image;
if (dpy)
EXT_FUNC_EGL(eglDestroyImage)(dpy, img->img);
else
EXT_FUNC_EGL(eglDestroyImage)(img->dpy, img->img);
EXT_FUNC_EGL(eglDestroyImage)(img->dpy, img->img);
free(img);
}
@ -256,81 +265,81 @@ evgl_glEvasGLImageTargetRenderbufferStorage(GLenum target, EvasGLImage image)
}
static EvasGLSync
evgl_evasglCreateSync(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglCreateSync(Evas_GL *evas_gl,
unsigned int type, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return NULL;
return EXT_FUNC_EGL(eglCreateSyncKHR)(dpy, type, attrib_list);
}
static Eina_Bool
evgl_evasglDestroySync(Evas_GL *evas_gl EINA_UNUSED, EvasGLSync sync)
evgl_evasglDestroySync(Evas_GL *evas_gl, EvasGLSync sync)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglDestroySyncKHR)(dpy, sync);
}
static int
evgl_evasglClientWaitSync(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglClientWaitSync(Evas_GL *evas_gl,
EvasGLSync sync, int flags, EvasGLTime timeout)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglClientWaitSyncKHR)(dpy, sync, flags, timeout);
}
static Eina_Bool
evgl_evasglSignalSync(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglSignalSync(Evas_GL *evas_gl,
EvasGLSync sync, unsigned mode)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglSignalSyncKHR)(dpy, sync, mode);
}
static Eina_Bool
evgl_evasglGetSyncAttrib(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglGetSyncAttrib(Evas_GL *evas_gl,
EvasGLSync sync, int attribute, int *value)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglGetSyncAttribKHR)(dpy, sync, attribute, value);
}
static int
evgl_evasglWaitSync(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglWaitSync(Evas_GL *evas_gl,
EvasGLSync sync, int flags)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglWaitSyncKHR)(dpy, sync, flags);
}
static Eina_Bool
evgl_evasglBindWaylandDisplay(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglBindWaylandDisplay(Evas_GL *evas_gl,
void *wl_display)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglBindWaylandDisplayWL)(dpy, wl_display);
}
static Eina_Bool
evgl_evasglUnbindWaylandDisplay(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglUnbindWaylandDisplay(Evas_GL *evas_gl,
void *wl_display)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglUnbindWaylandDisplayWL)(dpy, wl_display);
}
static Eina_Bool
evgl_evasglQueryWaylandBuffer(Evas_GL *evas_gl EINA_UNUSED,
evgl_evasglQueryWaylandBuffer(Evas_GL *evas_gl,
void *buffer, int attribute, int *value)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(evas_gl);
if (!dpy) return EINA_FALSE;
return EXT_FUNC_EGL(eglQueryWaylandBufferWL)(dpy, buffer, attribute, value);
}
@ -835,7 +844,7 @@ _evgl_api_gles1_ext_init(void *getproc, const char *glueexts)
#ifdef GL_GLES
EVGL_Resource *rsc;
EGLint context_version;
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(NULL);
/* glGetString returns the information for the currently bound context
* So, update glexts only if GLES1 context is currently bound.
@ -1119,7 +1128,7 @@ _evgl_api_gles3_ext_init(void *getproc, const char *glueexts)
#ifdef GL_GLES
EVGL_Resource *rsc;
EGLint context_version;
EGLDisplay dpy = EGLDISPLAY_GET();
EGLDisplay dpy = EGLDISPLAY_GET(NULL);
/* glGetString returns the information for the currently bound context
* So, update gles3_exts only if GLES3 context is currently bound.

View File

@ -20,6 +20,7 @@ int _evas_gl_log_level = -1;
typedef void *(*glsym_func_void_ptr) ();
glsym_func_void_ptr glsym_evas_gl_native_context_get = NULL;
glsym_func_void_ptr glsym_evas_gl_engine_data_get = NULL;
static void _surface_cap_print(int error);
static void _surface_context_list_print();
@ -1616,7 +1617,19 @@ _evgl_native_context_get(Evas_GL_Context *ctx)
evglctx = glsym_evas_gl_native_context_get(ctx);
if (!evglctx) return NULL;
return evgl_current_native_context_get(evglctx);;
return evgl_current_native_context_get(evglctx);
}
void *
_evgl_engine_data_get(Evas_GL *evasgl)
{
if (!glsym_evas_gl_engine_data_get)
{
ERR("Engine can't get a pointer to the native display");
return NULL;
}
return glsym_evas_gl_engine_data_get(evasgl);
}
//---------------------------------------------------------------//
@ -2071,13 +2084,15 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
void *
evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
Evas_GL_Context_Version version,
void *(*native_context_get)(void *))
void *(*native_context_get)(void *),
void *(*engine_data_get)(void *))
{
EVGL_Context *ctx = NULL;
EVGL_Resource *rsc = NULL;
// A little bit ugly. But it works even when dlsym(DEFAULT) doesn't work.
glsym_evas_gl_native_context_get = native_context_get;
glsym_evas_gl_engine_data_get = engine_data_get;
// Check the input
if (!evgl_engine)

View File

@ -58,7 +58,7 @@ EVGL_Engine *evgl_engine_init(void *eng_data, const EVGL_Interface *efunc);
void *evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h);
void *evgl_pbuffer_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h, const int *attrib_list);
int evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc);
void *evgl_context_create(void *eng_data, EVGL_Context *share_ctx, Evas_GL_Context_Version version, void *(*native_context_get)(void *));
void *evgl_context_create(void *eng_data, EVGL_Context *share_ctx, Evas_GL_Context_Version version, void *(*native_context_get)(void *), void *(*engine_data_get)(void *));
int evgl_context_destroy(void *eng_data, EVGL_Context *ctx);
int evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx);

View File

@ -351,6 +351,7 @@ extern EVGL_Context *_evgl_current_context_get(void);
extern int _evgl_not_in_pixel_get(void);
extern int _evgl_direct_enabled(void);
extern EVGLNative_Context _evgl_native_context_get(Evas_GL_Context *ctx);
extern void *_evgl_engine_data_get(Evas_GL *evasgl);
Eina_Bool _evgl_api_gles2_ext_init(void *getproc, const char *glueexts);
Eina_Bool _evgl_api_gles1_ext_init(void *getproc, const char *glueexts);
Eina_Bool _evgl_api_gles3_ext_init(void *getproc, const char *glueexts);

View File

@ -1425,12 +1425,13 @@ eng_gl_surface_destroy(void *data, void *surface)
static void *
eng_gl_context_create(void *data, void *share_context, int version,
void *(*native_context_get)(void *))
void *(*native_context_get)(void *),
void *(*engine_data_get)(void *))
{
EVGL_Context *sctx = (EVGL_Context *)share_context;
EVGLINIT(data, NULL);
return evgl_context_create(data, sctx, version, native_context_get);
return evgl_context_create(data, sctx, version, native_context_get, engine_data_get);
}
static int

View File

@ -2938,7 +2938,8 @@ eng_gl_surface_destroy(void *data EINA_UNUSED, void *surface)
static void *
eng_gl_context_create(void *data EINA_UNUSED, void *share_context, int version,
void *(*native_context_get)(void *) EINA_UNUSED)
void *(*native_context_get)(void *) EINA_UNUSED,
void *(*engine_data_get)(void *) EINA_UNUSED)
{
#ifdef EVAS_GL
Render_Engine_GL_Context *ctx;