summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongyeon Kim <dy5.kim@samsung.com>2015-07-30 09:14:08 +0900
committerDongyeon Kim <dy5.kim@samsung.com>2015-10-19 17:10:01 +0900
commit1f88f93453a4cef9c7d811bb5568fa75f6140788 (patch)
treea5410b3493a12c06d400452c090e5dcb6a91305a
parent2eaf33d9cf05662d504166aad1bdcd9d9ccf5491 (diff)
downloadefl-devs/spacegrapher/evasgl.tar.gz
Evas GL: Minimize internal resource creationdevs/spacegrapher/evasgl
Summary: Evas GL maintains internal resource (XWindow, EGL Window Surface, EGL Context) per thread to be used for make current when indirect rendering is used. Currently this internal resource is created regardless of current rendering mode, and always created when a new Evas GL thread is created by the application. Internal resource created in a new thread is not freed until evas shuts down in the main thread, so this causes memory/fd leak. This can be fixed by creating internal resource only in necessary cases (ie. indirect rendering), and adding tls resource destructor to be called when thread exits.
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_api.c5
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_api_ext.c2
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core.c440
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core.h2
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core_private.h5
-rw-r--r--src/modules/evas/engines/gl_generic/evas_engine.c15
6 files changed, 274 insertions, 195 deletions
diff --git a/src/modules/evas/engines/gl_common/evas_gl_api.c b/src/modules/evas/engines/gl_common/evas_gl_api.c
index a97204e087..f384fc2854 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_api.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_api.c
@@ -971,6 +971,11 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
glViewport(nc[0], nc[1], nc[2], nc[3]);
}
+ ctx->viewport_direct[0] = nc[0];
+ ctx->viewport_direct[1] = nc[1];
+ ctx->viewport_direct[2] = nc[2];
+ ctx->viewport_direct[3] = nc[3];
+
// Keep a copy of the original coordinates
ctx->viewport_coord[0] = x;
ctx->viewport_coord[1] = y;
diff --git a/src/modules/evas/engines/gl_common/evas_gl_api_ext.c b/src/modules/evas/engines/gl_common/evas_gl_api_ext.c
index eb6f1564e7..1960ec56b1 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_api_ext.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_api_ext.c
@@ -502,7 +502,7 @@ evgl_api_egl_ext_init(void *getproc, const char *glueexts)
Eina_Strbuf *sb = NULL;
if (_evgl_api_ext_status & EVASGL_API_EGL_EXT_INITIALIZED)
- return EINA_TRUE;
+ return EINA_TRUE;
sb = eina_strbuf_new();
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c
index f59d34e1b0..09f1568cbc 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.c
@@ -25,6 +25,9 @@ glsym_func_void_ptr glsym_evas_gl_engine_data_get = NULL;
static void _surface_cap_print(int error);
static void _surface_context_list_print();
static void _internal_resources_destroy(void *eng_data, EVGL_Resource *rsc);
+static void *_egl_image_create(EVGL_Context *context, int target, void *buffer);
+static void _egl_image_destroy(void *image);
+static int _evgl_direct_renderable(EVGL_Resource *rsc, EVGL_Surface *sfc);
// NOTE: These constants are "hidden", kinda non public API. They should not
// be used unless you know exactly what you are doing.
@@ -37,6 +40,7 @@ extern void (*EXT_FUNC_GLES1(glBindFramebufferOES)) (GLenum target, GLuint frame
extern void (*EXT_FUNC_GLES1(glFramebufferTexture2DOES)) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
extern void (*EXT_FUNC_GLES1(glFramebufferRenderbufferOES)) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
extern GLenum (*EXT_FUNC_GLES1(glCheckFramebufferStatusOES)) (GLenum target);
+
//---------------------------------------------------------------//
// Internal Resources:
// - Surface and Context used for internal buffer creation
@@ -60,6 +64,8 @@ _internal_resources_create(void *eng_data)
ERR("Error allocating EVGL_Resource");
return NULL;
}
+ rsc->id = eina_thread_self();
+ rsc->error_state = EVAS_GL_SUCCESS;
// Get display
rsc->display = evgl_engine->funcs->display_get(eng_data);
@@ -69,31 +75,6 @@ _internal_resources_create(void *eng_data)
goto error;
}
- // Create resource surface
- rsc->window = evgl_engine->funcs->native_window_create(eng_data);
- if (!rsc->window)
- {
- ERR("Error creating native window");
- goto error;
- }
-
- rsc->surface = evgl_engine->funcs->surface_create(eng_data, rsc->window);
- if (!rsc->surface)
- {
- ERR("Error creating native surface");
- goto error;
- }
-
- // Create a resource context
- rsc->context = evgl_engine->funcs->context_create(eng_data, NULL, EVAS_GL_GLES_2_X);
- if (!rsc->context)
- {
- ERR("Internal resource context creation failed.");
- goto error;
- }
-
- rsc->error_state = EVAS_GL_SUCCESS;
-
return rsc;
error:
@@ -107,17 +88,17 @@ _internal_resources_destroy(void *eng_data, EVGL_Resource *rsc)
if ((!eng_data) || (!rsc)) return;
if (rsc->context)
- evgl_engine->funcs->context_destroy(eng_data, rsc->context);
+ evgl_engine->funcs->context_destroy(eng_data, rsc->context);
if (rsc->surface)
- evgl_engine->funcs->surface_destroy(eng_data, rsc->surface);
+ evgl_engine->funcs->surface_destroy(eng_data, rsc->surface);
if (rsc->window)
- evgl_engine->funcs->native_window_destroy(eng_data, rsc->window);
+ evgl_engine->funcs->native_window_destroy(eng_data, rsc->window);
free(rsc);
}
static int
-_internal_resource_make_current(void *eng_data, EVGL_Context *ctx)
+_internal_resource_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
{
EVGL_Resource *rsc = NULL;
void *surface = NULL;
@@ -129,25 +110,94 @@ _internal_resource_make_current(void *eng_data, EVGL_Context *ctx)
{
if (!(rsc = _evgl_tls_resource_create(eng_data)))
{
- ERR("Error creting resources in tls.");
+ ERR("Error creating resources in tls.");
return 0;
}
}
// Set context from input or from resource
if (ctx)
- context = ctx->context;
+ context = ctx->context;
else
- context = (void*)rsc->context;
+ {
+ if (!rsc->context)
+ {
+ // Create a resource context
+ rsc->context = evgl_engine->funcs->context_create(eng_data, NULL, EVAS_GL_GLES_2_X);
+ if (!rsc->context)
+ {
+ ERR("Internal resource context creation failed.");
+ return 0;
+ }
+ }
- // Set the surface to evas surface if it's there
- if (rsc->id == evgl_engine->main_tid)
- rsc->direct.surface = evgl_engine->funcs->evas_surface_get(eng_data);
+ context = (void*)rsc->context;
+ }
- if (rsc->direct.surface)
- surface = (void*)rsc->direct.surface;
- else
- surface = (void*)rsc->surface;
+ if (sfc)
+ {
+ if (_evgl_direct_renderable(rsc, sfc)) // Direct rendering
+ {
+ // Do Nothing
+ }
+ else if (ctx->pixmap_image_supported) // Pixmap surface
+ {
+ if (!sfc->indirect_sfc)
+ {
+ evgl_engine->funcs->indirect_surface_create(evgl_engine, eng_data, sfc, sfc->cfg, sfc->w, sfc->h);
+ if (sfc->egl_image) _egl_image_destroy(sfc->egl_image);
+ sfc->egl_image = _egl_image_create(NULL, EVAS_GL_NATIVE_PIXMAP, sfc->indirect_sfc_native);
+ }
+ surface = (void*)sfc->indirect_sfc;
+
+ if (!ctx->indirect_context)
+ ctx->indirect_context = evgl_engine->funcs->gles_context_create(eng_data, ctx, sfc);
+ context = (void*)ctx->indirect_context;
+ }
+ else if (sfc->pbuffer.native_surface) // Pbuffer surface
+ {
+ surface = (void*)sfc->pbuffer.native_surface;
+ }
+ else // FBO
+ {
+ // Do Nothing
+ }
+ }
+
+ if (!surface)
+ {
+ // Set the surface to evas surface if it's there
+ if (rsc->id == evgl_engine->main_tid)
+ rsc->direct.surface = evgl_engine->funcs->evas_surface_get(eng_data);
+
+ if (rsc->direct.surface)
+ surface = (void*)rsc->direct.surface;
+ else
+ {
+ if (!rsc->window)
+ {
+ // Create resource surface
+ rsc->window = evgl_engine->funcs->native_window_create(eng_data);
+ if (!rsc->window)
+ {
+ ERR("Error creating native window");
+ return 0;
+ }
+ }
+
+ if (!rsc->surface)
+ {
+ rsc->surface = evgl_engine->funcs->surface_create(eng_data, rsc->window);
+ if (!rsc->surface)
+ {
+ ERR("Error creating native surface");
+ return 0;
+ }
+ }
+
+ surface = (void*)rsc->surface;
+ }
+ }
// Do the make current
if (evgl_engine->api_debug_mode)
@@ -798,13 +848,14 @@ error:
static int
_surface_cap_init(void *eng_data)
{
+ int ret = 0;
int max_size = 0;
// Do internal make current
- if (!_internal_resource_make_current(eng_data, NULL))
+ if (!_internal_resource_make_current(eng_data, NULL, NULL))
{
ERR("Error doing an internal resource make current");
- return 0;
+ return ret;
}
// Query the max width and height of the surface
@@ -853,13 +904,17 @@ _surface_cap_init(void *eng_data)
{
_surface_cap_print(0);
DBG("Number of supported surface formats: %d", evgl_engine->caps.num_fbo_fmts);
- return 1;
+ ret = 1;
}
else
{
ERR("There are no available surface formats. Error!");
- return 0;
}
+
+ // Destroy internal resources
+ _evgl_tls_resource_destroy(eng_data);
+
+ return ret;
}
static int
@@ -1173,16 +1228,8 @@ _surface_buffers_create(EVGL_Surface *sfc)
static int
-_surface_buffers_allocate(void *eng_data, EVGL_Surface *sfc, int w, int h, int mc)
+_surface_buffers_allocate(void *eng_data EINA_UNUSED, EVGL_Surface *sfc, int w, int h)
{
- // Set the context current with resource context/surface
- if (mc)
- if (!_internal_resource_make_current(eng_data, NULL))
- {
- ERR("Error doing an internal resource make current");
- return 0;
- }
-
// Create buffers
if (sfc->color_fmt)
{
@@ -1438,12 +1485,22 @@ _evgl_tls_resource_get(void)
return NULL;
}
- rsc = eina_tls_get(evgl_engine->resource_key);
+ if (evgl_engine->resource_key)
+ rsc = eina_tls_get(evgl_engine->resource_key);
- if (!rsc)
- return NULL;
- else
- return rsc;
+ return rsc;
+}
+
+static void
+_evgl_tls_resource_destroy_cb(void *data)
+{
+ EVGL_Resource *rsc = data;
+
+ LKL(evgl_engine->resource_lock);
+ evgl_engine->resource_list = eina_list_remove(evgl_engine->resource_list, rsc);
+ LKU(evgl_engine->resource_lock);
+
+ _internal_resources_destroy(rsc->current_eng, rsc);
}
EVGL_Resource *
@@ -1458,6 +1515,14 @@ _evgl_tls_resource_create(void *eng_data)
return NULL;
}
+ // Initialize Resource TLS
+ if (!evgl_engine->resource_key && eina_tls_cb_new(&evgl_engine->resource_key, _evgl_tls_resource_destroy_cb) == EINA_FALSE)
+ {
+ ERR("Error creating tls key");
+ return NULL;
+ }
+ DBG("TLS KEY created: %d", evgl_engine->resource_key);
+
// Create internal resources if it hasn't been created already
if (!(rsc = _internal_resources_create(eng_data)))
{
@@ -1470,7 +1535,6 @@ _evgl_tls_resource_create(void *eng_data)
{
// Add to the resource resource list for cleanup
LKL(evgl_engine->resource_lock);
- rsc->id = evgl_engine->resource_count++;
evgl_engine->resource_list = eina_list_prepend(evgl_engine->resource_list, rsc);
LKU(evgl_engine->resource_lock);
return rsc;
@@ -1488,6 +1552,8 @@ _evgl_tls_resource_destroy(void *eng_data)
{
Eina_List *l;
EVGL_Resource *rsc;
+ EVGL_Surface *sfc;
+ EVGL_Context *ctx;
// Check if engine is valid
if (!evgl_engine)
@@ -1496,18 +1562,30 @@ _evgl_tls_resource_destroy(void *eng_data)
return;
}
- if (!_evgl_tls_resource_get())
+ EINA_LIST_FOREACH(evgl_engine->surfaces, l, sfc)
{
- ERR("Error retrieving resource from TLS");
- return;
+ evgl_surface_destroy(eng_data, sfc);
+ }
+ EINA_LIST_FOREACH(evgl_engine->contexts, l, ctx)
+ {
+ evgl_context_destroy(eng_data, ctx);
}
LKL(evgl_engine->resource_lock);
+
+ eina_list_free(evgl_engine->surfaces);
+ evgl_engine->surfaces = NULL;
+
+ eina_list_free(evgl_engine->contexts);
+ evgl_engine->contexts = NULL;
+
EINA_LIST_FOREACH(evgl_engine->resource_list, l, rsc)
{
_internal_resources_destroy(eng_data, rsc);
}
eina_list_free(evgl_engine->resource_list);
+ evgl_engine->resource_list = NULL;
+
LKU(evgl_engine->resource_lock);
// Destroy TLS
@@ -1691,17 +1769,11 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
// Assign functions
evgl_engine->funcs = efunc;
-
- // Initialize Resource TLS
- if (eina_tls_new(&evgl_engine->resource_key) == EINA_FALSE)
- {
- ERR("Error creating tls key");
- goto error;
- }
- DBG("TLS KEY created: %d", evgl_engine->resource_key);
-
evgl_engine->safe_extensions = eina_hash_string_small_new(NULL);
+ // Main Thread ID
+ evgl_engine->main_tid = eina_thread_self();
+
// Surface Caps
if (!_surface_cap_init(eng_data))
{
@@ -1747,9 +1819,6 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
if (debug_mode == 1)
evgl_engine->api_debug_mode = 1;
- // Maint Thread ID (get tid not available in eina thread yet)
- evgl_engine->main_tid = 0;
-
return evgl_engine;
error:
@@ -1783,15 +1852,19 @@ evgl_engine_shutdown(void *eng_data)
eina_hash_free(evgl_engine->safe_extensions);
evgl_engine->safe_extensions = NULL;
- // Log
- eina_log_domain_unregister(_evas_gl_log_dom);
- _evas_gl_log_dom = -1;
+ if (gles1_funcs) free(gles1_funcs);
+ if (gles2_funcs) free(gles2_funcs);
+ if (gles3_funcs) free(gles3_funcs);
// Destroy internal resources
_evgl_tls_resource_destroy(eng_data);
LKD(evgl_engine->resource_lock);
+ // Log
+ eina_log_domain_unregister(_evas_gl_log_dom);
+ _evas_gl_log_dom = -1;
+
// Free engine
free(evgl_engine);
evgl_engine = NULL;
@@ -1982,43 +2055,41 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
return 0;
}
- // Retrieve the resource object
- if (!(rsc = _evgl_tls_resource_get()))
- {
- ERR("Error retrieving resource from TLS");
- return 0;
- }
-
if ((dbg = evgl_engine->api_debug_mode))
DBG("Destroying surface sfc %p (eng %p)", sfc, eng_data);
- if ((rsc->current_ctx) && (rsc->current_ctx->current_sfc == sfc) )
+ // Retrieve the resource object
+ rsc = _evgl_tls_resource_get();
+ if (rsc && rsc->current_ctx)
{
- if (evgl_engine->api_debug_mode)
+ // Make current to current context to destroy surface buffers
+ if (!_internal_resource_make_current(eng_data, sfc, rsc->current_ctx))
{
- ERR("The context is still current before it's being destroyed. "
- "Calling make_current(NULL, NULL)");
+ ERR("Error doing an internal resource make current");
+ return 0;
}
- else
+
+ // Destroy created buffers
+ if (!_surface_buffers_destroy(sfc))
{
- WRN("The context is still current before it's being destroyed. "
- "Calling make_current(NULL, NULL)");
+ ERR("Error deleting surface resources.");
+ return 0;
}
- evgl_make_current(eng_data, NULL, NULL);
- }
- // Make current to current context to destroy surface buffers
- if (!_internal_resource_make_current(eng_data, rsc->current_ctx))
- {
- ERR("Error doing an internal resource make current");
- return 0;
- }
-
- // Destroy created buffers
- if (!_surface_buffers_destroy(sfc))
- {
- ERR("Error deleting surface resources.");
- return 0;
+ if (rsc->current_ctx->current_sfc == sfc)
+ {
+ if (evgl_engine->api_debug_mode)
+ {
+ ERR("The surface is still current before it's being destroyed.");
+ ERR("Doing make_current(NULL, NULL)");
+ }
+ else
+ {
+ WRN("The surface is still current before it's being destroyed.");
+ WRN("Doing make_current(NULL, NULL)");
+ }
+ evgl_make_current(eng_data, NULL, NULL);
+ }
}
// Destroy indirect surface
@@ -2065,8 +2136,12 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
}
}
- if (sfc->current_ctx && sfc->current_ctx->current_sfc == sfc)
- sfc->current_ctx->current_sfc = NULL;
+ 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).");
+ return 0;
+ }
// Remove it from the list
LKL(evgl_engine->resource_lock);
@@ -2088,7 +2163,6 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
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;
@@ -2112,12 +2186,6 @@ 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)
@@ -2200,16 +2268,31 @@ evgl_context_destroy(void *eng_data, EVGL_Context *ctx)
if (ctx->current_sfc && (ctx->current_sfc->current_ctx == ctx))
ctx->current_sfc->current_ctx = NULL;
- // Set the context current with resource context/surface
- if (!_internal_resource_make_current(eng_data, rsc->current_ctx))
+ // Delete the FBO
+ if (ctx->surface_fbo)
{
- ERR("Error doing an internal resource make current");
- return 0;
+ // Set the context current with resource context/surface
+ if (!_internal_resource_make_current(eng_data, ctx->current_sfc, ctx))
+ {
+ ERR("Error doing an internal resource make current");
+ return 0;
+ }
+ glDeleteFramebuffers(1, &ctx->surface_fbo);
}
- // Delete the FBO
- if (ctx->surface_fbo)
- glDeleteFramebuffers(1, &ctx->surface_fbo);
+ // Retrieve the resource object
+ rsc = _evgl_tls_resource_get();
+ if (rsc && rsc->current_ctx == ctx)
+ {
+ // Unset the currrent context
+ 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).");
+ return 0;
+ }
+ rsc->current_ctx = NULL;
+ }
// Destroy indirect rendering context
if (ctx->indirect_context &&
@@ -2245,23 +2328,18 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
EVGL_Resource *rsc;
int curr_fbo = 0;
- // Check the input validity. If either sfc or ctx is NULL, it's also error.
- if ( (!evgl_engine) ||
- (sfc && (!ctx)) )
+ // Check the input validity. If either sfc is valid but ctx is NULL, it's also error.
+ // sfc can be NULL as evas gl supports surfaceless make current
+ if ( (!evgl_engine) || ((sfc) && (!ctx)) )
{
- ERR("Invalid Inputs. Engine: %p Surface: %p Context: %p!", evgl_engine, sfc, ctx);
- if(!sfc) evas_gl_common_error_set(eng_data, EVAS_GL_BAD_SURFACE);
- if(!ctx) evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
+ ERR("Invalid Input: Engine: %p, Surface: %p, Context: %p", evgl_engine, sfc, ctx);
+ if (!evgl_engine) evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
+ if (!ctx) evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
return 0;
}
// Get TLS Resources
rsc = _evgl_tls_resource_get();
-
- // Abuse debug mode - extra tracing for make_current and friends
- dbg = evgl_engine->api_debug_mode;
- if (dbg) DBG("(eng = %p, sfc = %p, ctx = %p), rsc = %p", eng_data, sfc, ctx, rsc);
-
if (!rsc)
{
DBG("Creating new TLS for this thread: %lu", (unsigned long)eina_thread_self());
@@ -2269,13 +2347,17 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!rsc) return 0;
}
+ // Abuse debug mode - extra tracing for make_current and friends
+ dbg = evgl_engine->api_debug_mode;
+ if (dbg) DBG("(eng = %p, sfc = %p, ctx = %p), rsc = %p", eng_data, sfc, ctx, rsc);
+
// Unset
if ((!sfc) && (!ctx))
{
if (rsc->current_ctx)
{
if (rsc->direct.partial.enabled)
- evgl_direct_partial_render_end();
+ evgl_direct_partial_render_end();
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
if ((rsc->current_ctx->surface_fbo == (GLuint) curr_fbo) ||
@@ -2313,7 +2395,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
}
// Do a make current
- if (!_internal_resource_make_current(eng_data, ctx))
+ if (!_internal_resource_make_current(eng_data, sfc, ctx))
{
ERR("Error doing a make current with internal surface. Context: %p", ctx);
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
@@ -2326,7 +2408,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
// to use fbo & egl image passing to evas
if (!ctx->extension_checked)
{
- if (!evgl_api_get(eng_data, ctx->version))
+ if (!evgl_api_get(eng_data, ctx->version, EINA_FALSE))
{
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);
@@ -2371,7 +2453,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
// Destroy created resources
if (sfc->buffers_allocated)
{
- if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, 0))
+ if (!_surface_buffers_allocate(eng_data, sfc, 0, 0))
{
ERR("Unable to destroy surface buffers!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
@@ -2392,7 +2474,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!sfc->buffers_allocated)
{
if (dbg) DBG("Allocating buffers for sfc %p", sfc);
- if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
+ if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h))
{
ERR("Unable Create Specificed Surfaces. Unsupported format!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
@@ -2407,7 +2489,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
{
if (!sfc->buffers_allocated)
{
- if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
+ if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h))
{
ERR("Unable Create Allocate Memory for Surface.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
@@ -2436,24 +2518,6 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
}
else
{
- if (!sfc->indirect_sfc)
- {
- evgl_engine->funcs->indirect_surface_create(evgl_engine, eng_data, sfc, sfc->cfg, sfc->w, sfc->h);
- sfc->egl_image = _egl_image_create(NULL, EVAS_GL_NATIVE_PIXMAP, sfc->indirect_sfc_native);
- }
- if (!ctx->indirect_context)
- {
- ctx->indirect_context =
- evgl_engine->funcs->gles_context_create(eng_data, ctx, sfc);
- }
- if (dbg) DBG("Calling make_current(%p, %p)", sfc->indirect_sfc, ctx->indirect_context);
- if (!evgl_engine->funcs->make_current(eng_data, sfc->indirect_sfc,
- ctx->indirect_context, EINA_TRUE))
- {
- ERR("Failed to make current with indirect surface.");
- return 0;
- }
-
// Transition from direct rendering to indirect rendering
if (rsc->direct.rendered)
{
@@ -2474,16 +2538,15 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
use_extension = EINA_TRUE;
#endif
- // Normal FBO Rendering
- // Create FBO if it hasn't been created
- if (!ctx->surface_fbo)
- _framebuffer_create(&ctx->surface_fbo, use_extension);
-
// Direct Rendering
if (_evgl_direct_renderable(rsc, sfc))
{
if (dbg) DBG("sfc %p is direct renderable.", sfc);
+ // Create FBO if it hasn't been created
+ if (!ctx->surface_fbo)
+ _framebuffer_create(&ctx->surface_fbo, use_extension);
+
// This is to transition from FBO rendering to direct rendering
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
if (ctx->surface_fbo == (GLuint)curr_fbo)
@@ -2527,10 +2590,6 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
ERR("Could not detach current FBO");
}
- if (dbg) DBG("Calling make_current(%p, %p)", sfc->pbuffer.native_surface, ctx->context);
- evgl_engine->funcs->make_current(eng_data, sfc->pbuffer.native_surface,
- ctx->context, EINA_TRUE);
-
// Bind to the previously bound buffer (may be 0)
if (ctx->current_fbo)
_framebuffer_bind(ctx->current_fbo, use_extension);
@@ -2541,6 +2600,10 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
{
if (dbg) DBG("Surface sfc %p is a normal surface.", sfc);
+ // Create FBO if it hasn't been created
+ if (!ctx->surface_fbo)
+ _framebuffer_create(&ctx->surface_fbo, use_extension);
+
// Attach fbo and the buffers
if ((rsc->current_ctx != ctx) || (ctx->current_sfc != sfc) || (rsc->direct.rendered))
{
@@ -2852,8 +2915,28 @@ evgl_get_pixels_post(void)
}
Evas_GL_API *
-evgl_api_get(void *eng_data, Evas_GL_Context_Version version)
+evgl_api_get(void *eng_data, Evas_GL_Context_Version version, Eina_Bool alloc_only)
{
+ Evas_GL_API *api = NULL;
+
+ if (version == EVAS_GL_GLES_2_X)
+ {
+ if (!gles2_funcs) gles2_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
+ api = gles2_funcs;
+ }
+ else if (version == EVAS_GL_GLES_1_X)
+ {
+ if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
+ api = gles1_funcs;
+ }
+ else if (version == EVAS_GL_GLES_3_X)
+ {
+ if (!gles3_funcs) gles3_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
+ api = gles3_funcs;
+ }
+ else return NULL;
+ if (alloc_only) return api;
+
#ifdef GL_GLES
if (!evgl_api_egl_ext_init(evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data)))
{
@@ -2862,32 +2945,21 @@ evgl_api_get(void *eng_data, Evas_GL_Context_Version version)
#endif
if (version == EVAS_GL_GLES_2_X)
{
- if (!gles2_funcs) gles2_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
-
- _evgl_api_gles2_get(gles2_funcs, evgl_engine->api_debug_mode);
- evgl_api_gles2_ext_get(gles2_funcs, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
-
- return gles2_funcs;
+ _evgl_api_gles2_get(api, evgl_engine->api_debug_mode);
+ evgl_api_gles2_ext_get(api, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
}
else if (version == EVAS_GL_GLES_1_X)
{
- if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
-
- _evgl_api_gles1_get(gles1_funcs, evgl_engine->api_debug_mode);
- evgl_api_gles1_ext_get(gles1_funcs, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
-
- return gles1_funcs;
+ _evgl_api_gles1_get(api, evgl_engine->api_debug_mode);
+ evgl_api_gles1_ext_get(api, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
}
else if (version == EVAS_GL_GLES_3_X)
{
- if (!gles3_funcs) gles3_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
-
- _evgl_api_gles3_get(gles3_funcs, evgl_engine->api_debug_mode);
- evgl_api_gles3_ext_get(gles3_funcs, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
-
- return gles3_funcs;
+ _evgl_api_gles3_get(api, evgl_engine->api_debug_mode);
+ evgl_api_gles3_ext_get(api, evgl_engine->funcs->proc_address_get, evgl_engine->funcs->ext_string_get(eng_data));
}
- else return NULL;
+
+ return api;
}
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.h b/src/modules/evas/engines/gl_common/evas_gl_core.h
index 7c321e2d3f..ba8f5beb78 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.h
@@ -64,7 +64,7 @@ int evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *
const char *evgl_string_query(int name);
int evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns);
-Evas_GL_API *evgl_api_get(void *eng_data, Evas_GL_Context_Version version);
+Evas_GL_API *evgl_api_get(void *eng_data, Evas_GL_Context_Version version, Eina_Bool alloc_only);
void evgl_safe_extension_add(const char *name, void *funcptr);
Eina_Bool evgl_safe_extension_get(const char *name, void **pfuncptr);
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core_private.h b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
index 87c74d245a..d7e9932eab 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
@@ -254,7 +254,7 @@ struct _EVGL_Cap
struct _EVGL_Resource
{
- int id;
+ Eina_Thread id;
EVGLNative_Display display;
EVGLNative_Context context;
@@ -317,8 +317,7 @@ struct _EVGL_Engine
LK(resource_lock);
Eina_TLS resource_key;
Eina_List *resource_list;
- int resource_count;
- int main_tid;
+ Eina_Thread main_tid;
// Add more debug logs (DBG levels 4 and 6)
int api_debug_mode;
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c
index 2cf26ab235..4845c7a47c 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -63,7 +63,8 @@ _context_restore(void)
{
if (rsc->id == evgl_engine->main_tid)
{
- evgl_make_current(rsc->stored.data, rsc->stored.surface, rsc->stored.context);
+ if (rsc->stored.data)
+ evgl_make_current(rsc->stored.data, rsc->stored.surface, rsc->stored.context);
_need_context_restore = EINA_FALSE;
}
}
@@ -1503,14 +1504,13 @@ eng_gl_make_current(void *data, void *surface, void *context)
Render_Engine_GL_Generic *re = data;
EVGL_Surface *sfc = (EVGL_Surface *)surface;
EVGL_Context *ctx = (EVGL_Context *)context;
+ int ret = 0;
// TODO: Add check for main thread before flush
- EVGLINIT(data, 0);
- if (ctx)
+ if ((sfc) && (ctx))
{
Evas_Engine_GL_Context *gl_context;
- CONTEXT_STORE(data, surface, context);
gl_context = re->window_gl_context_get(re->software.ob);
if ((gl_context->havestuff) ||
@@ -1523,7 +1523,10 @@ eng_gl_make_current(void *data, void *surface, void *context)
}
}
- return evgl_make_current(data, sfc, ctx);
+ ret = evgl_make_current(data, sfc, ctx);
+ CONTEXT_STORE(data, surface, context);
+
+ return ret;
}
static void *
@@ -1606,7 +1609,7 @@ eng_gl_api_get(void *data, int version)
ERR("Version not supported!");
return NULL;
}
- ret = evgl_api_get(data, version);
+ ret = evgl_api_get(data, version, EINA_TRUE);
//Disable GLES3 support if symbols not present
if ((!ret) && (version == EVAS_GL_GLES_3_X))