Evas GL: Use EGL image to share between Evas GL and GL backend

Summary:
When the context version between Evas GL and GL backend differs,
we cannot share texture between them.
So, when the driver has support for KHR_gl_texture_2D_image extension,
use EGL image to share between Evas GL and GL backend

Test Plan: Local Evas GL tests for 1.1, 2.0 and 3.0

Reviewers: jpeg

Subscribers: mythri, mer.kim, wonsik, cedric

Differential Revision: https://phab.enlightenment.org/D2115
This commit is contained in:
Dongyeon Kim 2015-03-09 17:25:20 +09:00 committed by Jean-Philippe Andre
parent eae786917c
commit d8fc60e0e6
9 changed files with 330 additions and 128 deletions

View File

@ -461,7 +461,7 @@ struct _Evas_Pixel_Import_Source
* Magic version number to know what the native surface struct looks like
*/
#define EVAS_NATIVE_SURFACE_VERSION 3
#define EVAS_NATIVE_SURFACE_VERSION 4
/**
* Native surface types that image object supports
@ -476,6 +476,7 @@ typedef enum _Evas_Native_Surface_Type
EVAS_NATIVE_SURFACE_OPENGL, /**< OpenGL system based type. texture or framebuffer id*/
EVAS_NATIVE_SURFACE_WL, /**< Wayland system based type. buffer of surface */
EVAS_NATIVE_SURFACE_TBM, /**< Tizen system based type. tbm surface */
EVAS_NATIVE_SURFACE_EVASGL, /**< Evas GL based type. evas gl surface */
} Evas_Native_Surface_Type;
/**
@ -532,6 +533,10 @@ struct _Evas_Native_Surface
{
void *buffer; /**< tbm surface buffer to use */
} tbm; /**< Set this struct fields if surface data is Tizen based. */
struct
{
void *surface; /**< evas gl surface to use */
} evasgl; /**< Set this struct fields if surface data is Evas GL based. */
} data; /**< Choose one union data according to your surface. */
};

View File

@ -50,14 +50,18 @@
#undef _EVASGL_EXT_FUNCTION_DRVFUNC_PROCADDR
/////////////////////////////////////////////////////////////////////////////////////////////////////
#define EXT_FUNC(fname) gl_ext_sym_##fname
#define EXT_FUNC_GLES1(fname) gles1_ext_sym_##fname
#define EXT_FUNC_GLES3(fname) gles3_ext_sym_##fname
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Extension HEADER
/////////////////////////////////////////////////////////////////////////////////////////////////////
#define _EVASGL_EXT_CHECK_SUPPORT(name)
#define _EVASGL_EXT_DISCARD_SUPPORT()
#define _EVASGL_EXT_BEGIN(name) extern int _gl_ext_support_##name;
#define _EVASGL_EXT_BEGIN(name) \
extern int _gl_ext_support_##name; \
extern int _gles1_ext_support_##name; \
extern int _gles3_ext_support_##name;
#define _EVASGL_EXT_END()
#define _EVASGL_EXT_DRVNAME(name)
#define _EVASGL_EXT_DRVNAME_PRIVATE(name)
@ -86,6 +90,8 @@
#undef _EVASGL_EXT_FUNCTION_DRVFUNC_PROCADDR
/////////////////////////////////////////////////////////////////////////////////////////////////////
#define EXTENSION_SUPPORT(name) (_gl_ext_support_##name == 1)
#define EXTENSION_SUPPORT_GLES1(name) (_gles1_ext_support_##name == 1)
#define EXTENSION_SUPPORT_GLES3(name) (_gles3_ext_support_##name == 1)
extern Eina_Bool evgl_api_ext_init(void *getproc, const char *glueexts);
extern void evgl_api_ext_get(Evas_GL_API *gl_funcs);

View File

@ -390,6 +390,7 @@ struct _Evas_GL_Shared
Eina_Hash *native_tex_hash;
Eina_Hash *native_wl_hash;
Eina_Hash *native_tbm_hash;
Eina_Hash *native_evasgl_hash;
#ifdef GL_GLES
// FIXME: hack.

View File

@ -965,6 +965,7 @@ evas_gl_common_context_new(void)
shared->native_tex_hash = eina_hash_int32_new(NULL);
shared->native_wl_hash = eina_hash_pointer_new(NULL);
shared->native_tbm_hash = eina_hash_pointer_new(NULL);
shared->native_evasgl_hash = eina_hash_pointer_new(NULL);
}
gc->shared = shared;
gc->shared->references++;
@ -1040,6 +1041,7 @@ evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
eina_hash_free(gc->shared->native_tex_hash);
eina_hash_free(gc->shared->native_wl_hash);
eina_hash_free(gc->shared->native_tbm_hash);
eina_hash_free(gc->shared->native_evasgl_hash);
free(gc->shared);
shared = NULL;
}

View File

@ -56,6 +56,14 @@ _internal_resources_create(void *eng_data)
return NULL;
}
// Get display
rsc->display = evgl_engine->funcs->display_get(eng_data);
if (!rsc->display)
{
ERR("Error getting display");
goto error;
}
// Create resource surface
rsc->window = evgl_engine->funcs->native_window_create(eng_data);
if (!rsc->window)
@ -75,7 +83,7 @@ _internal_resources_create(void *eng_data)
rsc->context = evgl_engine->funcs->context_create(eng_data, NULL, EVAS_GL_GLES_2_X);
if (!rsc->context)
{
ERR("Internal resource context creations failed.");
ERR("Internal resource context creation failed.");
goto error;
}
@ -168,7 +176,7 @@ _texture_allocate_2d(GLuint tex, GLint ifmt, GLenum fmt, GLenum type, int w, int
{
//if (!(*tex))
// glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_2D, tex );
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -191,8 +199,11 @@ _texture_destroy(GLuint *tex)
// Attach 2D texture with the given format to already bound FBO
// *NOTE: attach2 here is used for depth_stencil attachment in GLES env.
void
_texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples)
_texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Eina_Bool use_ext)
{
#define FBO_FUNC(name, param) \
(use_ext)?(gles1_funcs->name##OES param):((name) param)
if (samples)
{
#ifdef GL_GLES
@ -213,12 +224,38 @@ _texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples)
}
else
{
glFramebufferTexture2D(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0);
FBO_FUNC(glFramebufferTexture2D, (GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0));
if (attach2)
glFramebufferTexture2D(GL_FRAMEBUFFER, attach2, GL_TEXTURE_2D, tex, 0);
FBO_FUNC(glFramebufferTexture2D, (GL_FRAMEBUFFER, attach2, GL_TEXTURE_2D, tex, 0));
}
#undef FBO_FUNC
}
void
_egl_image_attach_texture(EVGL_Context *context, EvasGLImage *image, GLuint tex)
{
EVGLNative_Display dpy = EGL_NO_DISPLAY;
EVGLNative_Context ctx = EGL_NO_CONTEXT;
EVGL_Resource *rsc = NULL;
int attribs[] = {
EVAS_GL_TEXTURE_LEVEL, 0,
EVAS_GL_IMAGE_PRESERVED, 0,
EVAS_GL_NONE
};
// Retrieve the resource object
if (!(rsc = _evgl_tls_resource_get()))
{
ERR("Error creating resources in tls.");
return;
}
dpy = (EVGLNative_Display)rsc->display;
ctx = context->context;
*image = EXT_FUNC(eglCreateImage)(dpy, ctx, EVAS_GL_TEXTURE_2D, (EGLClientBuffer)tex, attribs);
}
// Gen Renderbuffer
@ -260,9 +297,13 @@ _renderbuffer_destroy(GLuint *buf)
// Attach a renderbuffer with the given format to already bound FBO
void
_renderbuffer_attach(GLuint buf, GLenum attach)
_renderbuffer_attach(GLuint buf, GLenum attach, Eina_Bool use_ext)
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf);
#define FBO_FUNC(name, param) \
(use_ext)?(gles1_funcs->name##OES param):((name) param)
FBO_FUNC(glFramebufferRenderbuffer, (GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf));
#undef FBO_FUNC
}
// Check whether the given FBO surface config is supported by the driver
@ -288,7 +329,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
{
_texture_create(&color_buf);
_texture_allocate_2d(color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h);
_texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples);
_texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, EINA_FALSE);
}
// Check Depth_Stencil Format First
@ -299,7 +340,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
_texture_allocate_2d(depth_stencil_buf, depth_fmt,
depth_fmt, GL_UNSIGNED_INT_24_8_OES, w, h);
_texture_attach_2d(depth_stencil_buf, GL_DEPTH_ATTACHMENT,
GL_STENCIL_ATTACHMENT, mult_samples);
GL_STENCIL_ATTACHMENT, mult_samples, EINA_FALSE);
depth_stencil = 1;
}
#else
@ -307,7 +348,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
{
_renderbuffer_create(&depth_stencil_buf);
_renderbuffer_allocate(depth_stencil_buf, depth_fmt, w, h, mult_samples);
_renderbuffer_attach(depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT);
_renderbuffer_attach(depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, EINA_FALSE);
depth_stencil = 1;
}
#endif
@ -317,7 +358,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
{
_renderbuffer_create(&depth_buf);
_renderbuffer_allocate(depth_buf, depth_fmt, w, h, mult_samples);
_renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT);
_renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT, EINA_FALSE);
}
// Stencil Attachment
@ -325,7 +366,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
{
_renderbuffer_create(&stencil_buf);
_renderbuffer_allocate(stencil_buf, stencil_fmt, w, h, mult_samples);
_renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT);
_renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT, EINA_FALSE);
}
// Check FBO for completeness
@ -730,6 +771,42 @@ _surface_cap_init(void *eng_data)
}
}
static int
_context_ext_check(EVGL_Context *ctx)
{
int fbo_supported = 0;
int egl_image_supported = 0;
if (!ctx)
return 0;
if (ctx->extension_checked)
return 1;
switch (ctx->version)
{
case EVAS_GL_GLES_1_X:
if (EXTENSION_SUPPORT_GLES1(framebuffer_object))
fbo_supported = 1;
break;
case EVAS_GL_GLES_3_X:
case EVAS_GL_GLES_2_X:
default:
fbo_supported = 1;
}
if (EXTENSION_SUPPORT(EGL_KHR_image_base)
&& EXTENSION_SUPPORT(EGL_KHR_gl_texture_2D_image))
egl_image_supported = 1;
if (fbo_supported && egl_image_supported)
ctx->extension_supported = 1;
ctx->extension_checked = 1;
return 1;
}
static const char *
_glenum_string_get(GLenum e)
{
@ -909,54 +986,58 @@ _surface_context_list_print()
// Start from here.....
//--------------------------------------------------------//
static int
_surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo)
_surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo, Eina_Bool use_ext)
{
int status;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
#define FBO_FUNC(name, param) \
(use_ext)?(gles1_funcs->name##OES param):((name) param)
FBO_FUNC(glBindFramebuffer, (GL_FRAMEBUFFER, fbo));
// Detach any previously attached buffers
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, 0, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
FBO_FUNC(glFramebufferTexture2D, (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0));
FBO_FUNC(glFramebufferRenderbuffer, (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0));
FBO_FUNC(glFramebufferRenderbuffer, (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0));
#ifdef GL_GLES
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
FBO_FUNC(glFramebufferTexture2D, (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0));
FBO_FUNC(glFramebufferTexture2D, (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0));
#else
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
FBO_FUNC(glFramebufferRenderbuffer, (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0));
#endif
// Render Target Texture
if (sfc->color_buf)
_texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples);
_texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples, use_ext);
// Depth Stencil RenderBuffer - Attach it to FBO
if (sfc->depth_stencil_buf)
{
#ifdef GL_GLES
_texture_attach_2d(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT,
GL_STENCIL_ATTACHMENT, sfc->msaa_samples);
GL_STENCIL_ATTACHMENT, sfc->msaa_samples, use_ext);
#else
_renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT);
_renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, use_ext);
#endif
}
// Depth RenderBuffer - Attach it to FBO
if (sfc->depth_buf)
_renderbuffer_attach(sfc->depth_buf, GL_DEPTH_ATTACHMENT);
_renderbuffer_attach(sfc->depth_buf, GL_DEPTH_ATTACHMENT, use_ext);
// Stencil RenderBuffer - Attach it to FBO
if (sfc->stencil_buf)
_renderbuffer_attach(sfc->stencil_buf, GL_STENCIL_ATTACHMENT);
_renderbuffer_attach(sfc->stencil_buf, GL_STENCIL_ATTACHMENT, use_ext);
// Check FBO for completeness
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
status = FBO_FUNC(glCheckFramebufferStatus, (GL_FRAMEBUFFER));
if (status != GL_FRAMEBUFFER_COMPLETE)
{
ERR("FBO not complete. Error Code: %x!", status);
return 0;
}
#undef FBO_FUNC
return 1;
}
@ -1011,6 +1092,8 @@ _surface_buffers_allocate(void *eng_data, EVGL_Surface *sfc, int w, int h, int m
{
_texture_allocate_2d(sfc->color_buf, sfc->color_ifmt, sfc->color_fmt,
GL_UNSIGNED_BYTE, w, h);
if ((sfc->current_ctx) && (sfc->current_ctx->extension_supported))
_egl_image_attach_texture(sfc->current_ctx, &sfc->egl_image, sfc->color_buf);
sfc->buffer_mem[0] = w * h * 4;
}
@ -1616,56 +1699,6 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
goto error;
}
// Set the context current with resource context/surface
if (!_internal_resource_make_current(eng_data, NULL))
{
ERR("Error doing an internal resource make current");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
goto error;
}
// Allocate indirect surface for fallback rendering
if ((cfg->gles_version == EVAS_GL_GLES_1_X) ||
(cfg->gles_version == EVAS_GL_GLES_3_X))
{
if (!evgl_engine->funcs->indirect_surface_create)
{
ERR("Cannot create indirect surface");
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
goto error;
}
INF("Creating indirect surface for fallback rendering");
evgl_engine->funcs->indirect_surface_create(evgl_engine, eng_data, sfc, cfg, w, h);
}
// Create internal buffers
if (!_surface_buffers_create(sfc))
{
ERR("Unable Create Specificed Surfaces.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
goto error;
};
// Allocate resources for fallback unless the flag is on
if (!sfc->direct_mem_opt)
{
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
{
ERR("Unable Create Allocate Memory for Surface.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
goto error;
}
}
if (dbg) DBG("Calling make_current(NULL, NULL)");
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
{
ERR("Error doing make_current(NULL, NULL).");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
goto error;
}
// Keep track of all the created surfaces
LKL(evgl_engine->resource_lock);
evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
@ -1819,7 +1852,6 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
{
EVGL_Resource *rsc;
Eina_Bool dbg;
GLuint texid;
// FIXME: This does some make_current(0,0) which may have side effects
@ -1889,7 +1921,6 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
// Destroy created buffers
texid = sfc->color_buf;
if (!_surface_buffers_destroy(sfc))
{
ERR("Error deleting surface resources.");
@ -1925,8 +1956,16 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
if (sfc->direct_fb_opt)
{
eina_hash_del(evgl_engine->direct_surfaces, &texid, sfc);
DBG("Removed tex %d from the direct surface: %p", texid, sfc);
if (!sfc->indirect)
{
eina_hash_del(evgl_engine->direct_surfaces, &sfc->color_buf, sfc);
DBG("Removed tex %d as direct surface: %p", sfc->color_buf, sfc);
}
else
{
eina_hash_del(evgl_engine->direct_surfaces, &sfc->indirect_sfc_native, sfc);
DBG("Removed native %p as direct surface: %p", sfc->indirect_sfc_native, sfc);
}
}
LKU(evgl_engine->resource_lock);
@ -1944,6 +1983,7 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
Evas_GL_Context_Version version)
{
EVGL_Context *ctx = NULL;
EVGL_Resource *rsc = NULL;
// Check the input
if (!evgl_engine)
@ -1963,6 +2003,12 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
if (evgl_engine->api_debug_mode)
DBG("Creating context GLESv%d (eng = %p, shctx = %p)", version, eng_data, share_ctx);
if (!(rsc = _evgl_tls_resource_get()))
{
ERR("Error creating resources in tls.");
return NULL;
}
// Allocate context object
ctx = calloc(1, sizeof(EVGL_Context));
if (!ctx)
@ -2096,7 +2142,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!rsc)
{
DBG("Creating new TLS for this thread: %lu", eina_thread_self());
DBG("Creating new TLS for this thread: %x", eina_thread_self());
rsc = _evgl_tls_resource_create(eng_data);
if (!rsc) return 0;
}
@ -2144,6 +2190,42 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
rsc->current_ctx->partial_render = 0;
}
// Do a make current
if (!_internal_resource_make_current(eng_data, ctx))
{
ERR("Error doing a make current with internal surface. Context: %p", ctx);
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
return 0;
}
sfc->current_ctx = ctx;
rsc->current_ctx = ctx;
rsc->current_eng = eng_data;
// Check whether extensions are supported for the current context version
// to use fbo & egl image passing to evas
if (!ctx->extension_checked)
{
if (!evgl_api_get(ctx->version))
{
ERR("Unable to get the list of GL APIs for version %d", ctx->version);
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
if (!_context_ext_check(ctx))
{
ERR("Unable to check required extension for the current context");
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
}
if (!sfc->color_buf && !_surface_buffers_create(sfc))
{
ERR("Unable to create specified surfaces.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
return 0;
};
// Allocate or free resources depending on what mode (direct of fbo) it's
// running only if the env var EVAS_GL_DIRECT_MEM_OPT is set.
if (evgl_engine->direct_mem_opt)
@ -2187,17 +2269,21 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
}
}
}
// Do a make current
if (!_internal_resource_make_current(eng_data, ctx))
else
{
ERR("Error doing a make current with internal surface. Context: %p", ctx);
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
return 0;
if (!sfc->buffers_allocated)
{
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
{
ERR("Unable Create Allocate Memory for Surface.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
return 0;
}
sfc->buffers_allocated = 1;
}
}
// GLES 1.x and 3.x
if ((ctx->version == EVAS_GL_GLES_1_X) || (ctx->version == EVAS_GL_GLES_3_X))
if (!ctx->extension_supported)
{
if (dbg) DBG("ctx %p is GLES %d", ctx, ctx->version);
if (_evgl_direct_renderable(rsc, sfc))
@ -2239,26 +2325,16 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
ctx->current_fbo = 0;
rsc->direct.rendered = 0;
}
// Update GLESv1 extension functions after GLESv1 context is bound
if (ctx->version == EVAS_GL_GLES_1_X)
{
evgl_api_gles1_ext_get(gles1_funcs);
}
else if (ctx->version == EVAS_GL_GLES_3_X)
{
evgl_api_gles3_ext_get(gles3_funcs);
}
}
else
{
// GLES 2+ below
#define FBO_FUNC(name, param) \
((ctx->version == EVAS_GL_GLES_1_X) && (ctx->extension_supported))?(gles1_funcs->name##OES param):((name) param)
// Normal FBO Rendering
// Create FBO if it hasn't been created
if (!ctx->surface_fbo)
glGenFramebuffers(1, &ctx->surface_fbo);
FBO_FUNC(glGenFramebuffers, (1, &ctx->surface_fbo));
// Direct Rendering
if (_evgl_direct_renderable(rsc, sfc))
@ -2269,13 +2345,13 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
if (ctx->surface_fbo == (GLuint)curr_fbo)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
FBO_FUNC(glBindFramebuffer, (GL_FRAMEBUFFER, 0));
ctx->current_fbo = 0;
}
else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
{
// Using the same context, we were rendering on a pbuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
FBO_FUNC(glBindFramebuffer, (GL_FRAMEBUFFER, 0));
ctx->current_fbo = 0;
}
@ -2304,7 +2380,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (sfc->color_buf)
{
if (!_surface_buffers_fbo_set(sfc, sfc->color_buf))
if (!_surface_buffers_fbo_set(sfc, sfc->color_buf, EINA_FALSE))
ERR("Could not detach current FBO");
}
@ -2314,7 +2390,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
// Bind to the previously bound buffer (may be 0)
if (ctx->current_fbo)
glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
FBO_FUNC(glBindFramebuffer, (GL_FRAMEBUFFER, ctx->current_fbo));
rsc->direct.rendered = 0;
}
@ -2337,7 +2413,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (rsc->direct.partial.enabled)
evgl_direct_partial_render_end();
if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo))
if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo, EINA_FALSE))
{
ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo);
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
@ -2347,10 +2423,11 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
// Bind to the previously bound buffer
if (ctx->current_fbo)
glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
FBO_FUNC(glBindFramebuffer, (GL_FRAMEBUFFER, ctx->current_fbo));
}
rsc->direct.rendered = 0;
}
#undef FBO_FUNC
}
ctx->current_sfc = sfc;
@ -2428,6 +2505,18 @@ evgl_safe_extension_get(const char *name, void **pfuncptr)
return EINA_TRUE;
}
void *
evgl_native_surface_egl_image_get(EVGL_Surface *sfc)
{
if (!evgl_engine)
{
ERR("Invalid input data. Engine: %p", evgl_engine);
return NULL;
}
return sfc->egl_image;
}
int
evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns)
{
@ -2440,14 +2529,9 @@ evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns)
if (!sfc->indirect)
{
ns->type = EVAS_NATIVE_SURFACE_OPENGL;
ns->type = EVAS_NATIVE_SURFACE_EVASGL;
ns->version = EVAS_NATIVE_SURFACE_VERSION;
ns->data.opengl.texture_id = sfc->color_buf;
ns->data.opengl.framebuffer_id = sfc->color_buf;
ns->data.opengl.x = 0;
ns->data.opengl.y = 0;
ns->data.opengl.w = sfc->w;
ns->data.opengl.h = sfc->h;
ns->data.evasgl.surface = sfc;
}
else
{
@ -2456,7 +2540,6 @@ evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns)
ns->data.x11.pixmap = (unsigned long)(intptr_t)sfc->indirect_sfc_native;
ns->data.x11.visual = sfc->indirect_sfc_visual;
}
return 1;
}
@ -2514,6 +2597,11 @@ evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns,
return EINA_FALSE;
}
}
else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL &&
ns->data.evasgl.surface)
{
sfc = ns->data.evasgl.surface;
}
else
{
ERR("Only EVAS_NATIVE_SURFACE_OPENGL or EVAS_NATIVE_SURFACE_X11 can be used for direct rendering");
@ -2537,10 +2625,10 @@ void
evgl_direct_info_set(int win_w, int win_h, int rot,
int img_x, int img_y, int img_w, int img_h,
int clip_x, int clip_y, int clip_w, int clip_h,
unsigned int texid)
void *surface)
{
EVGL_Resource *rsc;
EVGL_Surface *sfc;
EVGL_Surface *sfc = surface;
if (!(rsc = _evgl_tls_resource_get()))
return;
@ -2555,8 +2643,6 @@ evgl_direct_info_set(int win_w, int win_h, int rot,
* If the surface is not found, we assume indirect rendering.
*/
sfc = eina_hash_find(evgl_engine->direct_surfaces, &texid);
if (sfc &&
((rot == 0) || sfc->client_side_rotation || sfc->direct_override))
{

View File

@ -21,6 +21,11 @@ EAPI void evgl_engine_shutdown(void *eng_data);
typedef void (*EVGL_Engine_Call)(void *eng_data);
EAPI void *evgl_native_surface_egl_image_get(EVGL_Surface *sfc);
typedef void *(*EVGL_Native_Surface_Call)(void *sfc);
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);
@ -41,7 +46,7 @@ void evgl_direct_override_get(Eina_Bool *override, Eina_Bool *force_off)
void evgl_direct_info_set(int win_w, int win_h, int rot,
int img_x, int img_y, int img_w, int img_h,
int clip_x, int clip_y, int clip_w, int clip_h,
unsigned int texid);
void *hash_key);
void evgl_direct_info_clear(void);
void evgl_get_pixels_pre(void);
void evgl_get_pixels_post(void);

View File

@ -137,6 +137,7 @@ struct _EVGL_Surface
void *indirect_sfc_native;
void *indirect_sfc_visual;
void *indirect_sfc_config;
void *egl_image;
//-------------------------//
// Related to PBuffer Surface
@ -171,6 +172,8 @@ struct _EVGL_Context
int scissor_updated : 1;
int direct_scissor : 1;
int viewport_updated : 1;
int extension_checked : 1;
int extension_supported : 1;
int scissor_coord[4];
int viewport_coord[4];

View File

@ -821,7 +821,7 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
if (eng_gl_image_direct_get(data, image))
{
unsigned int texid;
void *surface;
gl_context->dc = context;
if ((gl_context->master_clip.enabled) &&
@ -833,9 +833,11 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
}
if (n->type == EVAS_NATIVE_SURFACE_OPENGL)
texid = n->data.opengl.texture_id;
surface = eina_hash_find(evgl_engine->direct_surfaces, &n->data.opengl.texture_id);
else if (n->type == EVAS_NATIVE_SURFACE_X11)
texid = n->data.x11.pixmap;
surface = eina_hash_find(evgl_engine->direct_surfaces, &n->data.x11.pixmap);
else if (n->type == EVAS_NATIVE_SURFACE_EVASGL)
surface = n->data.evasgl.surface;
else
{
ERR("This native surface type is not supported for direct rendering");
@ -851,7 +853,7 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
gl_context->dc->clip.y,
gl_context->dc->clip.w,
gl_context->dc->clip.h,
texid);
surface);
// Call pixel get function
evgl_get_pixels_pre();

View File

@ -59,6 +59,7 @@ Evas_GL_Common_Context_Call glsym_evas_gl_common_image_all_unload = NULL;
Evas_GL_Preload glsym_evas_gl_preload_init = NULL;
Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL;
EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL;
EVGL_Native_Surface_Call glsym_evgl_native_surface_egl_image_get = NULL;
Evas_Gl_Symbols glsym_evas_gl_symbols = NULL;
Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL;
@ -1274,6 +1275,7 @@ gl_symbols(void)
LINK2GENERIC(evas_gl_preload_init);
LINK2GENERIC(evas_gl_preload_shutdown);
LINK2GENERIC(evgl_engine_shutdown);
LINK2GENERIC(evgl_native_surface_egl_image_get);
LINK2GENERIC(evas_gl_symbols);
LINK2GENERIC(evas_gl_common_error_get);
LINK2GENERIC(evas_gl_common_error_set);
@ -2003,6 +2005,25 @@ _native_bind_cb(void *data EINA_UNUSED, void *image)
else
ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
}
#endif
}
else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
{
#ifdef GL_GLES
if (n->egl_surface)
{
void *surface = glsym_evgl_native_surface_egl_image_get(n->egl_surface);
if (glsym_glEGLImageTargetTexture2DOES)
{
glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, surface);
if (eglGetError() != EGL_SUCCESS)
ERR("glEGLImageTargetTexture2DOES() failed.");
}
else
ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
}
#else
// TODO
#endif
}
}
@ -2039,6 +2060,10 @@ _native_unbind_cb(void *data EINA_UNUSED, void *image)
{
// nothing
}
else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
{
// nothing
}
}
static void
@ -2123,6 +2148,10 @@ _native_free_cb(void *data, void *image)
}
#endif
}
else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
{
eina_hash_del(eng_get_ob(re)->gl_context->shared->native_evasgl_hash, &n->ns.data.evasgl.surface, im);
}
im->native.data = NULL;
im->native.func.data = NULL;
im->native.func.bind = NULL;
@ -2195,6 +2224,16 @@ eng_image_native_set(void *data, void *image, void *native)
return im;
}
}
else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
{
buffer = ns->data.evasgl.surface;
if (im->native.data)
{
Evas_Native_Surface *ens = im->native.data;
if (ens->data.evasgl.surface == buffer)
return im;
}
}
}
if ((!ns) && (!im->native.data)) return im;
@ -2257,6 +2296,21 @@ eng_image_native_set(void *data, void *image, void *native)
}
}
}
else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
{
im2 = eina_hash_find(eng_get_ob(re)->gl_context->shared->native_evasgl_hash, &buffer);
if (im2 == im) return im;
if (im2)
{
n = im2->native.data;
if (n)
{
glsym_evas_gl_common_image_ref(im2);
glsym_evas_gl_common_image_free(im);
return im2;
}
}
}
im2 = glsym_evas_gl_common_image_new_from_data(eng_get_ob(re)->gl_context,
im->w, im->h, NULL, im->alpha,
EVAS_COLORSPACE_ARGB8888);
@ -2625,6 +2679,44 @@ eng_image_native_set(void *data, void *image, void *native)
}
}
#endif
}
else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
{
if (native)
{
n = calloc(1, sizeof(Native));
if (n)
{
memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
eina_hash_add(eng_get_ob(re)->gl_context->shared->native_evasgl_hash, &buffer, im);
n->pixmap = 0;
n->visual = 0;
#ifdef GL_GLES
n->egl_surface = ns->data.evasgl.surface;
#else
n->fbc = 0;
n->glx_pixmap = 0;
#endif
im->native.yinvert = 0;
im->native.loose = 0;
im->native.data = n;
im->native.func.data = re;
im->native.func.bind = _native_bind_cb;
im->native.func.unbind = _native_unbind_cb;
im->native.func.free = _native_free_cb;
im->native.target = GL_TEXTURE_2D;
im->native.mipmap = 0;
// FIXME: need to implement mapping sub texture regions
// x, y, w, h for possible texture atlasing
glsym_evas_gl_common_image_native_enable(im);
}
}
}
return im;
}