Evas GL: Add support for OpenGL-ES 1.1 and some new APIs

This adds support for the following features:
- OpenGL-ES 1.1 (works only with EGL right now),
- PBuffer (basic support),
- Multithreading safety in gl_x11,
- EGL fence_sync extension,
- Improve direct rendering,
- And a few other evas_gl_ APIs.

Merge branch 'devs/jpeg/evasgl'
This commit is contained in:
Jean-Philippe Andre 2014-10-20 13:24:49 +09:00
commit fb3564304e
21 changed files with 9309 additions and 562 deletions

View File

@ -575,6 +575,7 @@ modules/evas/engines/gl_common/evas_gl_api_ext_def.h \
modules/evas/engines/gl_common/evas_gl_core.h \
modules/evas/engines/gl_common/evas_gl_core_private.h \
modules/evas/engines/gl_common/evas_gl_api.c \
modules/evas/engines/gl_common/evas_gl_api_gles1.c \
modules/evas/engines/gl_common/evas_gl_api_ext.c \
modules/evas/engines/gl_common/shader/font_frag.h \
modules/evas/engines/gl_common/shader/font_vert.h \

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,8 @@
#include "evas_private.h"
#include "Evas_GL.h"
typedef struct _Evas_GL_TLS_data Evas_GL_TLS_data;
struct _Evas_GL
{
DATA32 magic;
@ -10,11 +12,15 @@ struct _Evas_GL
Eina_List *contexts;
Eina_List *surfaces;
Eina_Lock lck;
Eina_TLS resource_key;
Eina_List *resource_list;
};
struct _Evas_GL_Context
{
void *data;
Evas_GL_Context_Version version;
};
struct _Evas_GL_Surface
@ -22,6 +28,95 @@ struct _Evas_GL_Surface
void *data;
};
struct _Evas_GL_TLS_data
{
int error_state;
};
Evas_GL_TLS_data *
_evas_gl_internal_tls_get(Evas_GL *evas_gl)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return NULL;
if (!(tls_data = eina_tls_get(evas_gl->resource_key)))
{
tls_data = (Evas_GL_TLS_data*) calloc(1, sizeof(Evas_GL_TLS_data));
if (!tls_data)
{
ERR("Evas_GL: Could not set error!");
return NULL;
}
tls_data->error_state = EVAS_GL_SUCCESS;
if (eina_tls_set(evas_gl->resource_key, (void*)tls_data) == EINA_TRUE)
{
LKL(evas_gl->lck);
evas_gl->resource_list = eina_list_prepend(evas_gl->resource_list, tls_data);
LKU(evas_gl->lck);
return tls_data;
}
else
{
ERR("Evas_GL: Failed setting TLS data!");
free(tls_data);
return NULL;
}
}
return tls_data;
}
void
_evas_gl_internal_tls_destroy(Evas_GL *evas_gl)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return;
if (!(tls_data = eina_tls_get(evas_gl->resource_key)))
{
WRN("Destructor: TLS data was never set!");
return;
}
LKL(evas_gl->lck);
EINA_LIST_FREE(evas_gl->resource_list, tls_data)
free(tls_data);
if (evas_gl->resource_key)
eina_tls_free(evas_gl->resource_key);
evas_gl->resource_key = 0;
LKU(evas_gl->lck);
}
void
_evas_gl_internal_error_set(Evas_GL *evas_gl, int error_enum)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return;
tls_data = _evas_gl_internal_tls_get(evas_gl);
if (!tls_data) return;
tls_data->error_state = error_enum;
}
int
_evas_gl_internal_error_get(Evas_GL *evas_gl)
{
Evas_GL_TLS_data *tls_data;
if (!evas_gl) return EVAS_GL_NOT_INITIALIZED;
tls_data = _evas_gl_internal_tls_get(evas_gl);
if (!tls_data) return EVAS_GL_NOT_INITIALIZED;
return tls_data->error_state;
}
EAPI Evas_GL *
evas_gl_new(Evas *e)
{
@ -36,6 +131,7 @@ evas_gl_new(Evas *e)
evas_gl->magic = MAGIC_EVAS_GL;
evas_gl->evas = eo_data_ref(e, EVAS_CANVAS_CLASS);
LKI(evas_gl->lck);
if (!evas_gl->evas->engine.func->gl_context_create)
{
@ -44,6 +140,15 @@ evas_gl_new(Evas *e)
return NULL;
}
// Initialize tls resource key
if (eina_tls_new(&(evas_gl->resource_key)) == EINA_FALSE)
{
ERR("Error creating tls key");
free(evas_gl);
return NULL;
}
_evas_gl_internal_error_set(evas_gl, EVAS_GL_SUCCESS);
return evas_gl;
}
@ -54,7 +159,6 @@ evas_gl_free(Evas_GL *evas_gl)
return;
MAGIC_CHECK_END();
// Delete undeleted surfaces
while (evas_gl->surfaces)
evas_gl_surface_destroy(evas_gl, evas_gl->surfaces->data);
@ -63,8 +167,12 @@ evas_gl_free(Evas_GL *evas_gl)
while (evas_gl->contexts)
evas_gl_context_destroy(evas_gl, evas_gl->contexts->data);
// Destroy tls
_evas_gl_internal_tls_destroy(evas_gl);
eo_data_unref(evas_gl->evas->evas, evas_gl->evas);
evas_gl->magic = 0;
LKD(evas_gl->lck);
free(evas_gl);
}
@ -98,18 +206,24 @@ evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int
if (!config)
{
ERR("Invalid Config Pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_CONFIG);
return NULL;
}
if ( (width <= 0) || (height <= 0))
if ((width <= 0) || (height <= 0))
{
ERR("Invalid surface dimensions: %d, %d", width, height);
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return NULL;
}
surf = calloc(1, sizeof(Evas_GL_Surface));
if (!surf) return NULL;
if (!surf)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_ALLOC);
return NULL;
}
surf->data = evas_gl->evas->engine.func->gl_surface_create(evas_gl->evas->engine.data.output, config, width, height);
@ -121,7 +235,65 @@ evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int
}
// Keep track of the surface creations
LKL(evas_gl->lck);
evas_gl->surfaces = eina_list_prepend(evas_gl->surfaces, surf);
LKU(evas_gl->lck);
return surf;
}
EAPI Evas_GL_Surface *
evas_gl_pbuffer_surface_create(Evas_GL *evas_gl, Evas_GL_Config *cfg,
int w, int h, const int *attrib_list)
{
Evas_GL_Surface *surf;
// Magic
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
MAGIC_CHECK_END();
if (!cfg)
{
ERR("Invalid Config Pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_CONFIG);
return NULL;
}
if ((w <= 0) || (h <= 0))
{
ERR("Invalid surface dimensions: %d, %d", w, h);
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return NULL;
}
if (!evas_gl->evas->engine.func->gl_pbuffer_surface_create)
{
ERR("Engine does not support PBuffer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_NOT_INITIALIZED);
return NULL;
}
surf = calloc(1, sizeof(Evas_GL_Surface));
if (!surf)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_ALLOC);
return NULL;
}
surf->data = evas_gl->evas->engine.func->gl_pbuffer_surface_create
(evas_gl->evas->engine.data.output, cfg, w, h, attrib_list);
if (!surf->data)
{
ERR("Engine failed to create a PBuffer!");
free(surf);
return NULL;
}
// Keep track of the surface creations
LKL(evas_gl->lck);
evas_gl->surfaces = eina_list_prepend(evas_gl->surfaces, surf);
LKU(evas_gl->lck);
return surf;
}
@ -137,6 +309,7 @@ evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
if (!surf)
{
ERR("Trying to destroy a NULL surface pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_SURFACE);
return;
}
@ -144,7 +317,9 @@ evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
evas_gl->evas->engine.func->gl_surface_destroy(evas_gl->evas->engine.data.output, surf->data);
// Remove it from the list
LKL(evas_gl->lck);
evas_gl->surfaces = eina_list_remove(evas_gl->surfaces, surf);
LKU(evas_gl->lck);
// Delete the object
free(surf);
@ -152,7 +327,8 @@ evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
}
EAPI Evas_GL_Context *
evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
evas_gl_context_version_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx,
Evas_GL_Context_Version version)
{
Evas_GL_Context *ctx;
@ -161,23 +337,29 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
return NULL;
MAGIC_CHECK_END();
if ((version != EVAS_GL_GLES_1_X) && (version != EVAS_GL_GLES_2_X))
{
ERR("Can not create an OpenGL-ES %d.x context (not supported).",
(int) version);
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return NULL;
}
// Allocate a context object
ctx = calloc(1, sizeof(Evas_GL_Context));
if (!ctx)
{
ERR("Unable to create a Evas_GL_Context object");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_ALLOC);
return NULL;
}
// Call engine->gl_create_context
ctx->version = version;
if (share_ctx)
{
ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, share_ctx->data);
}
ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, share_ctx->data, version);
else
{
ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, NULL);
}
ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, NULL, version);
// Set a few variables
if (!ctx->data)
@ -188,10 +370,17 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
}
// Keep track of the context creations
LKL(evas_gl->lck);
evas_gl->contexts = eina_list_prepend(evas_gl->contexts, ctx);
LKU(evas_gl->lck);
return ctx;
}
EAPI Evas_GL_Context *
evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
{
return evas_gl_context_version_create(evas_gl, share_ctx, EVAS_GL_GLES_2_X);
}
EAPI void
@ -205,6 +394,7 @@ evas_gl_context_destroy(Evas_GL *evas_gl, Evas_GL_Context *ctx)
if (!ctx)
{
ERR("Trying to destroy a NULL context pointer!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_CONTEXT);
return;
}
@ -212,7 +402,9 @@ evas_gl_context_destroy(Evas_GL *evas_gl, Evas_GL_Context *ctx)
evas_gl->evas->engine.func->gl_context_destroy(evas_gl->evas->engine.data.output, ctx->data);
// Remove it from the list
LKL(evas_gl->lck);
evas_gl->contexts = eina_list_remove(evas_gl->contexts, ctx);
LKU(evas_gl->lck);
// Delete the object
free(ctx);
@ -227,7 +419,7 @@ evas_gl_make_current(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_GL_Context *c
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return EINA_FALSE;
MAGIC_CHECK_END();
if ((surf) && (ctx))
ret = (Eina_Bool)evas_gl->evas->engine.func->gl_make_current(evas_gl->evas->engine.data.output, surf->data, ctx->data);
else if ((!surf) && (!ctx))
@ -235,17 +427,94 @@ evas_gl_make_current(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_GL_Context *c
else
{
ERR("Bad match between surface: %p and context: %p", surf, ctx);
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_MATCH);
return EINA_FALSE;
}
return ret;
}
EAPI Evas_GL_Context *
evas_gl_current_context_get(Evas_GL *evas_gl)
{
Evas_GL_Context *comp;
void *internal_ctx;
Eina_List *li;
// Magic
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
MAGIC_CHECK_END();
if (!evas_gl->evas->engine.func->gl_current_context_get)
{
CRI("Can not get current context with this engine: %s",
evas_gl->evas->engine.module->definition->name);
return NULL;
}
internal_ctx = evas_gl->evas->engine.func->gl_current_context_get(evas_gl->evas->engine.data.output);
if (!internal_ctx)
return NULL;
LKL(evas_gl->lck);
EINA_LIST_FOREACH(evas_gl->contexts, li, comp)
{
if (comp->data == internal_ctx)
{
LKU(evas_gl->lck);
return comp;
}
}
ERR("The currently bound context could not be found.");
LKU(evas_gl->lck);
return NULL;
}
EAPI Evas_GL_Surface *
evas_gl_current_surface_get(Evas_GL *evas_gl)
{
Evas_GL_Surface *comp;
void *internal_sfc;
Eina_List *li;
// Magic
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
MAGIC_CHECK_END();
if (!evas_gl->evas->engine.func->gl_current_surface_get)
{
CRI("Can not get current surface with this engine: %s",
evas_gl->evas->engine.module->definition->name);
return NULL;
}
internal_sfc = evas_gl->evas->engine.func->gl_current_surface_get(evas_gl->evas->engine.data.output);
if (!internal_sfc)
return NULL;
LKL(evas_gl->lck);
EINA_LIST_FOREACH(evas_gl->surfaces, li, comp)
{
if (comp->data == internal_sfc)
{
LKU(evas_gl->lck);
return comp;
}
}
ERR("The currently bound surface could not be found.");
LKU(evas_gl->lck);
return NULL;
}
EAPI const char *
evas_gl_string_query(Evas_GL *evas_gl, int name)
{
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
return "";
MAGIC_CHECK_END();
return (const char *)evas_gl->evas->engine.func->gl_string_query(evas_gl->evas->engine.data.output, name);
@ -268,9 +537,17 @@ evas_gl_native_surface_get(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_Native_
return EINA_FALSE;
MAGIC_CHECK_END();
if ((!surf) || (!ns))
if (!surf)
{
ERR("Invalid surface!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_SURFACE);
return EINA_FALSE;
}
if (!ns)
{
ERR("Invalid input parameters!");
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return EINA_FALSE;
}
@ -285,6 +562,91 @@ evas_gl_api_get(Evas_GL *evas_gl)
return NULL;
MAGIC_CHECK_END();
return (Evas_GL_API*)evas_gl->evas->engine.func->gl_api_get(evas_gl->evas->engine.data.output);
return (Evas_GL_API*)evas_gl->evas->engine.func->gl_api_get(evas_gl->evas->engine.data.output, EVAS_GL_GLES_2_X);
}
EAPI Evas_GL_API *
evas_gl_context_api_get(Evas_GL *evas_gl, Evas_GL_Context *ctx)
{
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return NULL;
MAGIC_CHECK_END();
if (!ctx)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_CONTEXT);
return NULL;
}
return (Evas_GL_API*)evas_gl->evas->engine.func->gl_api_get(evas_gl->evas->engine.data.output, ctx->version);
}
EAPI int
evas_gl_rotation_get(Evas_GL *evas_gl)
{
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return 0;
MAGIC_CHECK_END();
if (!evas_gl->evas->engine.func->gl_rotation_angle_get)
return 0;
return evas_gl->evas->engine.func->gl_rotation_angle_get(evas_gl->evas->engine.data.output);
}
EAPI int
evas_gl_error_get(Evas_GL *evas_gl)
{
int err;
MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
return EVAS_GL_NOT_INITIALIZED;
MAGIC_CHECK_END();
if ((err = _evas_gl_internal_error_get(evas_gl)) != EVAS_GL_SUCCESS)
goto end;
if (!evas_gl->evas->engine.func->gl_error_get)
err = EVAS_GL_NOT_INITIALIZED;
else
err = evas_gl->evas->engine.func->gl_error_get(evas_gl->evas->engine.data.output);
end:
/* Call to evas_gl_error_get() should set error to EVAS_GL_SUCCESS */
_evas_gl_internal_error_set(evas_gl, EVAS_GL_SUCCESS);
return err;
}
EAPI Eina_Bool
evas_gl_surface_query(Evas_GL *evas_gl, Evas_GL_Surface *surface, int attribute, void *value)
{
if (!evas_gl) return EINA_FALSE;
if (!surface)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_SURFACE);
return EINA_FALSE;
}
if (!evas_gl->evas->engine.func->gl_surface_query)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_NOT_INITIALIZED);
return EINA_FALSE;
}
if (!value)
{
_evas_gl_internal_error_set(evas_gl, EVAS_GL_BAD_PARAMETER);
return EINA_FALSE;
}
return evas_gl->evas->engine.func->gl_surface_query
(evas_gl->evas->engine.data.output, surface->data, attribute, value);
}
// Internal function - called from evas_gl_core.c
EAPI void *
_evas_gl_native_context_get(Evas_GL_Context *ctx)
{
if (!ctx) return NULL;
return ctx->data;
}

View File

@ -2948,8 +2948,7 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
(obj->cur->color.g == 255) &&
(obj->cur->color.b == 255) &&
(obj->cur->color.a == 255) &&
(!obj->map->cur.map) &&
(!o->cur->has_alpha)) ||
(!obj->map->cur.map)) ||
(direct_override)) &&
(!direct_force_off) )
{

View File

@ -157,6 +157,7 @@ struct _Evas_3D_File_Eet
typedef Eina_Bool (*Evas_3D_Node_Func)(Evas_3D_Node *, void *data);
typedef enum _Evas_3D_Node_Traverse_Type
{
EVAS_3D_NODE_TRAVERSE_DOWNWARD,
@ -1231,19 +1232,25 @@ struct _Evas_Func
/* EFL-GL Glue Layer */
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);
void *(*gl_context_create) (void *data, void *share_context, int version);
int (*gl_context_destroy) (void *data, void *context);
int (*gl_make_current) (void *data, void *surface, void *context);
void *(*gl_string_query) (void *data, int name);
void *(*gl_proc_address_get) (void *data, const char *name);
int (*gl_native_surface_get) (void *data, void *surface, void *native_surface);
void *(*gl_api_get) (void *data);
void *(*gl_api_get) (void *data, int version);
void (*gl_direct_override_get) (void *data, int *override, int *force_off);
void (*gl_get_pixels_set) (void *data, void *get_pixels, void *get_pixels_data, void *obj);
Eina_Bool (*gl_surface_lock) (void *data, void *surface);
Eina_Bool (*gl_surface_read_pixels) (void *data, void *surface, int x, int y, int w, int h, Evas_Colorspace cspace, void *pixels);
Eina_Bool (*gl_surface_unlock) (void *data, void *surface);
int (*gl_error_get) (void *data);
void *(*gl_current_context_get) (void *data);
void *(*gl_current_surface_get) (void *data);
int (*gl_rotation_angle_get) (void *data);
Eina_Bool (*gl_surface_query) (void *data, void *surface, int attr, void *value);
int (*image_load_error_get) (void *data, void *image);
int (*font_run_end_get) (void *data, Evas_Font_Set *font, Evas_Font_Instance **script_fi, Evas_Font_Instance **cur_fi, Evas_Script_Type script, const Eina_Unicode *text, int run_len);

View File

@ -1160,7 +1160,7 @@ evgl_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const
#endif
static void *
eng_gl_api_get(void *data)
eng_gl_api_get(void *data, int version EINA_UNUSED)
{
Render_Engine *re;

View File

@ -16,12 +16,12 @@ void _make_current_check(const char* api)
{
EVGL_Context *ctx = NULL;
ctx = _evgl_current_context_get();
ctx = evas_gl_common_current_context_get();
if (!ctx)
{
CRI("\e[1;33m%s\e[m: Current Context NOT SET: GL Call Should NOT Be Called without MakeCurrent!!!", api);
}
CRI("\e[1;33m%s\e[m: Current Context NOT SET: GL Call Should NOT Be Called without MakeCurrent!!!", api);
else if (ctx->version != EVAS_GL_GLES_2_X)
CRI("\e[1;33m%s\e[m: This API is being called with the wrong context (invalid version).", api);
}
static
@ -29,7 +29,7 @@ void _direct_rendering_check(const char *api)
{
EVGL_Context *ctx = NULL;
ctx = _evgl_current_context_get();
ctx = evas_gl_common_current_context_get();
if (!ctx)
{
ERR("Current Context Not Set");
@ -59,7 +59,7 @@ _evgl_glBindFramebuffer(GLenum target, GLuint framebuffer)
EVGL_Resource *rsc;
rsc = _evgl_tls_resource_get();
ctx = _evgl_current_context_get();
ctx = evas_gl_common_current_context_get();
if (!ctx)
{
@ -185,7 +185,7 @@ _evgl_glReleaseShaderCompiler(void)
// returns: imgc[4] (oc[4]) original image object dimension in gl coord
// returns: objc[4] (nc[4]) tranformed (x, y, width, heigth) in gl coord
// returns: cc[4] cliped coordinate in original coordinate
static void
void
compute_gl_coordinates(int win_w, int win_h, int rot, int clip_image,
int x, int y, int width, int height,
int img_x, int img_y, int img_w, int img_h,
@ -307,6 +307,27 @@ compute_gl_coordinates(int win_w, int win_h, int rot, int clip_image,
//DBG( "\e[1;32m Img[%d %d %d %d] Original [%d %d %d %d] Transformed[%d %d %d %d] Clip[%d %d %d %d] Clipped[%d %d %d %d] \e[m", img_x, img_y, img_w, img_h, imgc[0], imgc[1], imgc[2], imgc[3], objc[0], objc[1], objc[2], objc[3], clip[0], clip[1], clip[2], clip[3], cc[0], cc[1], cc[2], cc[3]);
}
static void
_evgl_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
ERR("Unable to execute GL command. Error retrieving tls");
return;
}
if (_evgl_direct_enabled())
{
rsc->clear_color.a = alpha;
rsc->clear_color.r = red;
rsc->clear_color.g = green;
rsc->clear_color.b = blue;
}
glClearColor(red, green, blue, alpha);
}
static void
_evgl_glClear(GLbitfield mask)
{
@ -338,6 +359,29 @@ _evgl_glClear(GLbitfield mask)
{
if (!(rsc->current_ctx->current_fbo))
{
/* Skip glClear() if clearing with transparent color
* Note: There will be side effects if the object itself is not
* marked as having an alpha channel!
*/
if (ctx->current_sfc->alpha && (mask & GL_COLOR_BUFFER_BIT))
{
if ((rsc->clear_color.a == 0) &&
(rsc->clear_color.r == 0) &&
(rsc->clear_color.g == 0) &&
(rsc->clear_color.b == 0))
{
// Skip clear color as we don't want to write black
mask &= ~GL_COLOR_BUFFER_BIT;
}
else if (rsc->clear_color.a != 1.0)
{
// TODO: Draw a rectangle? This will never be the perfect solution though.
WRN("glClear() used with a semi-transparent color and direct rendering. "
"This will erase the previous contents of the evas!");
}
if (!mask) return;
}
if ((!ctx->direct_scissor))
{
glEnable(GL_SCISSOR_TEST);
@ -374,6 +418,8 @@ _evgl_glClear(GLbitfield mask)
}
glClear(mask);
// TODO/FIXME: Restore previous client-side scissors.
}
else
{
@ -403,7 +449,7 @@ _evgl_glEnable(GLenum cap)
{
EVGL_Context *ctx;
ctx = _evgl_current_context_get();
ctx = evas_gl_common_current_context_get();
if (cap == GL_SCISSOR_TEST)
if (ctx) ctx->scissor_enabled = 1;
@ -415,7 +461,7 @@ _evgl_glDisable(GLenum cap)
{
EVGL_Context *ctx;
ctx = _evgl_current_context_get();
ctx = evas_gl_common_current_context_get();
if (cap == GL_SCISSOR_TEST)
if (ctx) ctx->scissor_enabled = 0;
@ -887,7 +933,7 @@ void
_evgld_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
EVGL_FUNC_BEGIN();
glClearColor(red, green, blue, alpha);
_evgl_glClearColor(red, green, blue, alpha);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
EVGL_FUNC_END();
}
@ -2386,7 +2432,7 @@ _normal_gl_api_get(Evas_GL_API *funcs)
ORD(glBufferSubData);
ORD(glCheckFramebufferStatus);
// ORD(glClear);
ORD(glClearColor);
// ORD(glClearColor);
// ORD(glClearDepthf);
ORD(glClearStencil);
ORD(glColorMask);
@ -2525,6 +2571,7 @@ _normal_gl_api_get(Evas_GL_API *funcs)
// For Direct Rendering
ORD(glClear);
ORD(glClearColor);
ORD(glDisable);
ORD(glEnable);
ORD(glGetIntegerv);
@ -2551,6 +2598,7 @@ _direct_scissor_off_api_get(Evas_GL_API *funcs)
#define ORD(f) EVAS_API_OVERRIDE(f, funcs,)
// For Direct Rendering
ORD(glClear);
ORD(glClearColor);
ORD(glDisable);
ORD(glEnable);
ORD(glGetIntegerv);
@ -2719,6 +2767,8 @@ _debug_gl_api_get(Evas_GL_API *funcs)
void
_evgl_api_get(Evas_GL_API *funcs, int debug)
{
memset(funcs, 0, sizeof(Evas_GL_API));
if (debug)
_debug_gl_api_get(funcs);
else

View File

@ -63,61 +63,108 @@ char _gl_ext_string[10240] = { 0 };
// Evas extensions from EGL extensions
#ifdef GL_GLES
static void *
evgl_evasglCreateImage(int target, void* buffer, int *attrib_list)
#define EGLDISPLAY_GET() _evgl_egl_display_get(__FUNCTION__)
static EGLDisplay
_evgl_egl_display_get(const char *function)
{
EGLDisplay dpy = EGL_NO_DISPLAY;
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
ERR("Unable to execute GL command. Error retrieving tls");
return NULL;
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;
}
if (!rsc->current_eng)
{
ERR("Unable to retrive Current Engine");
return NULL;
ERR("%s: Unable to retrive Current Engine", 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 EXT_FUNC(eglCreateImage)(dpy, EGL_NO_CONTEXT, target, buffer, attrib_list);
return dpy;
}
else
{
ERR("Invalid Engine... (Can't acccess EGL Display)\n");
return NULL;
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;
}
}
static void *
_evgl_eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx,
int target, void* buffer, const int *attrib_list)
{
int *attribs = NULL;
/* Convert 0 terminator into a EGL_NONE terminator */
if (attrib_list)
{
int cnt = 0;
int *a;
for (a = (int *) attrib_list; (*a) && (*a != EGL_NONE); a += 2)
{
/* TODO: Verify supported attributes */
cnt += 2;
}
attribs = alloca(sizeof(int) * (cnt + 1));
for (a = attribs; (*attrib_list) && (*attrib_list != EGL_NONE);
a += 2, attrib_list += 2)
{
a[0] = attrib_list[0];
a[1] = attrib_list[1];
}
*a = EGL_NONE;
}
return EXT_FUNC(eglCreateImage)(dpy, ctx, target, buffer, attribs);
}
static void *
evgl_evasglCreateImage(int target, void* buffer, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLContext ctx = EGL_NO_CONTEXT;
if (!dpy) 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);
}
return _evgl_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
}
static void *
evgl_evasglCreateImageForContext(Evas_GL *evasgl EINA_UNUSED, Evas_GL_Context *evasctx,
int target, void* buffer, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
EGLContext ctx = EGL_NO_CONTEXT;
if (!evasgl || !dpy) return NULL;
ctx = _evgl_native_context_get(evasctx);
return _evgl_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
}
static void
evgl_evasglDestroyImage(EvasGLImage image)
{
EGLDisplay dpy = EGL_NO_DISPLAY;
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
ERR("Unable to execute GL command. Error retrieving tls");
return;
}
if (!rsc->current_eng)
{
ERR("Unable to retrive Current Engine");
return;
}
if ((evgl_engine) && (evgl_engine->funcs->display_get))
{
dpy = (EGLDisplay)evgl_engine->funcs->display_get(rsc->current_eng);
EXT_FUNC(eglDestroyImage)(dpy, image);
}
else
ERR("Invalid Engine... (Can't acccess EGL Display)\n");
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return;
EXT_FUNC(eglDestroyImage)(dpy, image);
}
static void
@ -129,9 +176,63 @@ evgl_glEvasGLImageTargetTexture2D(GLenum target, EvasGLImage image)
static void
evgl_glEvasGLImageTargetRenderbufferStorage(GLenum target, EvasGLImage image)
{
EXT_FUNC(glEGLImageTargetTexture2DOES)(target, image);
EXT_FUNC(glEGLImageTargetRenderbufferStorageOES)(target, image);
}
static EvasGLSync
evgl_evasglCreateSync(Evas_GL *evas_gl EINA_UNUSED,
unsigned int type, const int *attrib_list)
{
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return NULL;
return EXT_FUNC(eglCreateSyncKHR)(dpy, type, attrib_list);
}
static Eina_Bool
evgl_evasglDestroySync(Evas_GL *evas_gl EINA_UNUSED, EvasGLSync sync)
{
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return EINA_FALSE;
return EXT_FUNC(eglDestroySyncKHR)(dpy, sync);
}
static int
evgl_evasglClientWaitSync(Evas_GL *evas_gl EINA_UNUSED,
EvasGLSync sync, int flags, EvasGLTime timeout)
{
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return EINA_FALSE;
return EXT_FUNC(eglClientWaitSyncKHR)(dpy, sync, flags, timeout);
}
static Eina_Bool
evgl_evasglSignalSync(Evas_GL *evas_gl EINA_UNUSED,
EvasGLSync sync, unsigned mode)
{
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return EINA_FALSE;
return EXT_FUNC(eglSignalSyncKHR)(dpy, sync, mode);
}
static Eina_Bool
evgl_evasglGetSyncAttrib(Evas_GL *evas_gl EINA_UNUSED,
EvasGLSync sync, int attribute, int *value)
{
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return EINA_FALSE;
return EXT_FUNC(eglGetSyncAttribKHR)(dpy, sync, attribute, value);
}
static int
evgl_evasglWaitSync(Evas_GL *evas_gl EINA_UNUSED,
EvasGLSync sync, int flags)
{
EGLDisplay dpy = EGLDISPLAY_GET();
if (!dpy) return EINA_FALSE;
return EXT_FUNC(eglWaitSyncKHR)(dpy, sync, flags);
}
#else
#endif

View File

@ -446,12 +446,15 @@ _EVASGL_EXT_BEGIN(EGL_KHR_image_base)
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglDestroyImageKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_BEGIN(EvasGLImage, evasglCreateImage, (int target, void* buffer, int *attrib_list))
_EVASGL_EXT_FUNCTION_BEGIN(EvasGLImage, evasglCreateImage, (int target, void* buffer, const int *attrib_list))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglCreateImage)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_FUNCTION_BEGIN(void, evasglDestroyImage, (EvasGLImage image))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglDestroyImage)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_FUNCTION_BEGIN(EvasGLImage, evasglCreateImageForContext, (Evas_GL *evas_gl, Evas_GL_Context *ctx, int target, void* buffer, const int *attrib_list))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglCreateImageForContext)
_EVASGL_EXT_FUNCTION_END()
#ifdef _EVASGL_EXT_VERIFY
{
@ -562,6 +565,67 @@ _EVASGL_EXT_BEGIN(EGL_KHR_gl_renderbuffer_image)
#endif
_EVASGL_EXT_END()
_EVASGL_EXT_BEGIN(EGL_KHR_fence_sync)
_EVASGL_EXT_DRVNAME(EGL_KHR_fence_sync)
_EVASGL_EXT_FUNCTION_PRIVATE_BEGIN(void *, eglCreateSyncKHR, (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list))
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglCreateSyncKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_PRIVATE_BEGIN(EGLBoolean, eglDestroySyncKHR, (EGLDisplay dpy, EGLSyncKHR sync))
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglDestroySyncKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_PRIVATE_BEGIN(EGLint, eglClientWaitSyncKHR, (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout))
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglClientWaitSyncKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_PRIVATE_BEGIN(EGLBoolean, eglGetSyncAttribKHR, (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value))
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglGetSyncAttribKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_BEGIN(EvasGLSync, evasglCreateSync, (Evas_GL *evas_gl, unsigned int type, const int *attrib_list))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglCreateSync)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_FUNCTION_BEGIN(Eina_Bool, evasglDestroySync, (Evas_GL *evas_gl, EvasGLSync sync))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglDestroySync)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_FUNCTION_BEGIN(int, evasglClientWaitSync, (Evas_GL *evas_gl, EvasGLSync sync, int flags, EvasGLTime timeout))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglClientWaitSync)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_FUNCTION_BEGIN(Eina_Bool, evasglGetSyncAttrib, (Evas_GL *evas_gl, EvasGLSync sync, int attribute, int *value))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglGetSyncAttrib)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_END()
_EVASGL_EXT_BEGIN(EGL_KHR_reusable_sync)
_EVASGL_EXT_DRVNAME(EGL_KHR_reusable_sync)
_EVASGL_EXT_FUNCTION_PRIVATE_BEGIN(EGLBoolean, eglSignalSyncKHR, (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode))
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglSignalSyncKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_BEGIN(Eina_Bool, evasglSignalSync, (Evas_GL *evas_gl, EvasGLSync sync, unsigned mode))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglSignalSync)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_END()
_EVASGL_EXT_BEGIN(EGL_KHR_wait_sync)
_EVASGL_EXT_DRVNAME(EGL_KHR_wait_sync)
_EVASGL_EXT_FUNCTION_PRIVATE_BEGIN(EGLint, eglWaitSyncKHR, (EGLDisplay dpy, EGLSyncKHR sync, int flags))
_EVASGL_EXT_FUNCTION_DRVFUNC(GETPROCADDR("eglWaitSyncKHR"))
_EVASGL_EXT_FUNCTION_PRIVATE_END()
_EVASGL_EXT_FUNCTION_BEGIN(int, evasglWaitSync, (Evas_GL *evas_gl, EvasGLSync sync, int flags))
_EVASGL_EXT_FUNCTION_DRVFUNC(evgl_evasglWaitSync)
_EVASGL_EXT_FUNCTION_END()
_EVASGL_EXT_END()
#if 0
_EVASGL_EXT_BEGIN(EGL_SEC_map_image)
_EVASGL_EXT_DRVNAME(EGL_SEC_map_image)
@ -575,6 +639,7 @@ _EVASGL_EXT_BEGIN(EGL_SEC_map_image)
_EVASGL_EXT_END()
#endif
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -754,6 +754,10 @@ EAPI void evas_gl_preload_render_unlock(evas_gl_make_current_cb make_cur
EAPI void evas_gl_preload_render_relax(evas_gl_make_current_cb make_current, void *engine_data);
EAPI void evas_gl_symbols(void *(*GetProcAddress)(const char *name));
EAPI void evas_gl_common_error_set(void *data, int error_enum);
EAPI int evas_gl_common_error_get(void *data);
EAPI void *evas_gl_common_current_context_get(void);
typedef int (*Evas_GL_Preload)(void);
typedef void (*Evas_GL_Common_Image_Call)(Evas_GL_Image *im);
typedef void (*Evas_GL_Common_Context_Call)(Evas_Engine_GL_Context *gc);

View File

@ -10,10 +10,14 @@ typedef struct _GL_Format
// Globals
static Evas_GL_API gl_funcs;
static Evas_GL_API gles1_funcs;
EVGL_Engine *evgl_engine = NULL;
int _evas_gl_log_dom = -1;
int _evas_gl_log_level = -1;
typedef void *(*glsym_func_void_ptr) ();
glsym_func_void_ptr glsym_evas_gl_native_context_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);
@ -59,13 +63,15 @@ _internal_resources_create(void *eng_data)
}
// Create a resource context
rsc->context = evgl_engine->funcs->context_create(eng_data, NULL);
rsc->context = evgl_engine->funcs->context_create(eng_data, NULL, EVAS_GL_GLES_2_X);
if (!rsc->context)
{
ERR("Internal resource context creations failed.");
goto error;
}
rsc->error_state = EVAS_GL_SUCCESS;
return rsc;
error:
@ -817,6 +823,8 @@ _surface_context_list_print()
#define YELLOW "\e[1;33m"
#define RED "\e[1;31m"
LKL(evgl_engine->resource_lock);
DBG( YELLOW "-----------------------------------------------" RESET);
DBG("Total Number of active Evas GL Surfaces: %d", eina_list_count(evgl_engine->surfaces));
@ -864,6 +872,8 @@ _surface_context_list_print()
}
DBG( YELLOW "-----------------------------------------------" RESET);
LKU(evgl_engine->resource_lock);
#undef RESET
#undef GREEN
#undef YELLOW
@ -891,11 +901,9 @@ _surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo)
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);
// Depth Stencil RenderBuffer - Attach it to FBO
if (sfc->depth_stencil_buf)
@ -910,11 +918,11 @@ _surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo)
// 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);
// 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);
// Check FBO for completeness
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@ -1086,9 +1094,15 @@ _internal_config_set(EVGL_Surface *sfc, Evas_GL_Config *cfg)
sfc->depth_stencil_fmt = evgl_engine->caps.fbo_fmts[i].depth_stencil_fmt;
sfc->msaa_samples = evgl_engine->caps.fbo_fmts[i].samples;
// TODO: Implement surface reconfigure and add depth+stencil support
// Direct Rendering Option
if ( (!stencil_bit) || (evgl_engine->direct_override) )
sfc->direct_fb_opt = cfg->options_bits & EVAS_GL_OPTIONS_DIRECT;
if ((!depth_bit && !stencil_bit) || evgl_engine->direct_override)
sfc->direct_fb_opt = cfg->options_bits & EVAS_GL_OPTIONS_DIRECT;
// Extra flags for direct rendering
sfc->client_side_rotation = !!(cfg->options_bits & EVAS_GL_OPTIONS_CLIENT_SIDE_ROTATION);
sfc->alpha = (cfg->color_format == EVAS_GL_RGBA_8888);
cfg_index = i;
break;
@ -1110,6 +1124,7 @@ _internal_config_set(EVGL_Surface *sfc, Evas_GL_Config *cfg)
DBG(" D-Stencil Format : %s", _glenum_string_get(sfc->depth_stencil_fmt));
DBG(" MSAA Samples : %d", sfc->msaa_samples);
DBG(" Direct Option : %d", sfc->direct_fb_opt);
DBG(" Client-side Rot. : %d", sfc->client_side_rotation);
sfc->cfg_index = cfg_index;
return 1;
}
@ -1130,7 +1145,7 @@ _evgl_direct_renderable(EVGL_Resource *rsc, EVGL_Surface *sfc)
// Functions used by Evas GL module
//---------------------------------------------------------------//
EVGL_Resource *
_evgl_tls_resource_get()
_evgl_tls_resource_get(void)
{
EVGL_Resource *rsc = NULL;
@ -1219,8 +1234,8 @@ _evgl_tls_resource_destroy(void *eng_data)
evgl_engine->resource_key = 0;
}
EVGL_Context *
_evgl_current_context_get()
EAPI void * /* EVGL_Context */
evas_gl_common_current_context_get(void)
{
EVGL_Resource *rsc;
@ -1230,11 +1245,11 @@ _evgl_current_context_get()
return NULL;
}
else
return rsc->current_ctx;
return rsc->current_ctx;
}
int
_evgl_not_in_pixel_get()
_evgl_not_in_pixel_get(void)
{
EVGL_Resource *rsc;
@ -1254,7 +1269,7 @@ _evgl_not_in_pixel_get()
}
int
_evgl_direct_enabled()
_evgl_direct_enabled(void)
{
EVGL_Resource *rsc;
EVGL_Surface *sfc;
@ -1266,6 +1281,50 @@ _evgl_direct_enabled()
return _evgl_direct_renderable(rsc, sfc);
}
EAPI void
evas_gl_common_error_set(void *data EINA_UNUSED, int error_enum)
{
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
WRN("evgl: Unable to set error!");
return;
}
rsc->error_state = error_enum;
}
EAPI int
evas_gl_common_error_get(void *data EINA_UNUSED)
{
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get()))
{
WRN("evgl: Unable to get error!");
return EVAS_GL_NOT_INITIALIZED;
}
return rsc->error_state;
}
EVGLNative_Context
_evgl_native_context_get(Evas_GL_Context *ctx)
{
EVGL_Context *evglctx;
if (!glsym_evas_gl_native_context_get)
{
ERR("Engine can't get a pointer to the native context");
return NULL;
}
evglctx = glsym_evas_gl_native_context_get(ctx);
if (!evglctx) return NULL;
return evglctx->context;
}
//---------------------------------------------------------------//
// Exported functions for evas_engine to use
@ -1315,6 +1374,8 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
goto error;
}
LKI(evgl_engine->resource_lock);
// Assign functions
evgl_engine->funcs = efunc;
@ -1326,6 +1387,9 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
}
DBG("TLS KEY created: %d", evgl_engine->resource_key);
// Link to evas_gl.c (this doesn't look great)
glsym_evas_gl_native_context_get = dlsym(RTLD_DEFAULT, "_evas_gl_native_context_get");
// Initialize Extensions
if (efunc->proc_address_get && efunc->ext_string_get)
evgl_api_ext_init(efunc->proc_address_get, efunc->ext_string_get(eng_data));
@ -1381,6 +1445,7 @@ error:
{
if (evgl_engine->resource_key)
eina_tls_free(evgl_engine->resource_key);
LKD(evgl_engine->resource_lock);
free(evgl_engine);
}
evgl_engine = NULL;
@ -1394,7 +1459,11 @@ void
evgl_engine_shutdown(void *eng_data)
{
// Check if engine is valid
if (!evgl_engine) return;
if (!evgl_engine)
{
ERR("EVGL Engine not valid!");
return;
}
// Log
eina_log_domain_unregister(_evas_gl_log_dom);
@ -1403,6 +1472,8 @@ evgl_engine_shutdown(void *eng_data)
// Destroy internal resources
_evgl_tls_resource_destroy(eng_data);
LKD(evgl_engine->resource_lock);
// Free engine
free(evgl_engine);
evgl_engine = NULL;
@ -1414,17 +1485,20 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
EVGL_Surface *sfc = NULL;
char *s = NULL;
int direct_override = 0, direct_mem_opt = 0;
Eina_Bool need_reconfigure = EINA_FALSE;
// Check if engine is valid
if (!evgl_engine)
{
ERR("Invalid EVGL Engine!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ACCESS);
return NULL;
}
if (!cfg)
{
ERR("Invalid Config!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
return NULL;
}
@ -1433,6 +1507,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
{
ERR("Requested surface size [%d, %d] is greater than max supported size [%d, %d]",
w, h, evgl_engine->caps.max_w, evgl_engine->caps.max_h);
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_PARAMETER);
return NULL;
}
@ -1460,6 +1535,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!sfc)
{
ERR("Surface allocation failed.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
goto error;
}
@ -1471,6 +1547,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
if (!_internal_config_set(sfc, cfg))
{
ERR("Unsupported Format!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
goto error;
}
@ -1478,13 +1555,28 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
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 a special surface for 1.1
if (cfg->gles_version == EVAS_GL_GLES_1_X)
{
if (!evgl_engine->funcs->gles1_surface_create)
{
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
goto error;
}
INF("Creating special surface for GLES 1.x rendering");
evgl_engine->funcs->gles1_surface_create(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;
};
@ -1494,6 +1586,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
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;
}
}
@ -1501,11 +1594,28 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
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);
LKU(evgl_engine->resource_lock);
if (sfc->direct_fb_opt &&
(sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt))
{
need_reconfigure = !evgl_engine->direct_depth_stencil_surfaces;
evgl_engine->direct_depth_stencil_surfaces =
eina_list_prepend(evgl_engine->direct_depth_stencil_surfaces, sfc);
}
if (need_reconfigure)
{
// See FIXME notice above in _internal_config_set
ERR("Surface reconfigure is not implemented yet");
}
return sfc;
@ -1514,11 +1624,123 @@ error:
return NULL;
}
void *
evgl_pbuffer_surface_create(void *eng_data, Evas_GL_Config *cfg,
int w, int h, const int *attrib_list)
{
EVGL_Surface *sfc = NULL;
void *pbuffer;
// Check if engine is valid
if (!evgl_engine)
{
ERR("Invalid EVGL Engine!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ACCESS);
return NULL;
}
if (!cfg)
{
ERR("Invalid Config!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
return NULL;
}
if (!evgl_engine->funcs->pbuffer_surface_create)
{
ERR("Engine can not create PBuffers");
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
return NULL;
}
// Allocate surface structure
sfc = calloc(1, sizeof(EVGL_Surface));
if (!sfc)
{
ERR("Surface allocation failed.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
goto error;
}
sfc->w = w;
sfc->h = h;
sfc->pbuffer.color_fmt = cfg->color_format;
sfc->pbuffer.is_pbuffer = EINA_TRUE;
// Set the context current with resource context/surface
if (!_internal_resource_make_current(eng_data, NULL))
{
ERR("Error doing an internal resource make current");
goto error;
}
// If the surface is defined as RGB or RGBA, then create an FBO
if (sfc->pbuffer.color_fmt != EVAS_GL_NO_FBO)
{
// Set the internal config value
if (!_internal_config_set(sfc, cfg))
{
ERR("Unsupported Format!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
goto error;
}
// 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 (!evgl_engine->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;
}
}
}
// Not calling make_current
pbuffer = evgl_engine->funcs->pbuffer_surface_create
(eng_data, sfc, attrib_list);
if (!pbuffer)
{
ERR("Engine failed to create a PBuffer");
goto error;
}
sfc->pbuffer.native_surface = pbuffer;
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
{
ERR("Error doing make_current(NULL, NULL).");
goto error;
}
// Keep track of all the created surfaces
LKL(evgl_engine->resource_lock);
evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
LKU(evgl_engine->resource_lock);
return sfc;
error:
free(sfc);
return NULL;
}
int
evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
{
EVGL_Resource *rsc;
Eina_Bool need_reconfigure = EINA_FALSE;
// Check input parameter
if ((!evgl_engine) || (!sfc))
@ -1549,13 +1771,35 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
evgl_make_current(eng_data, NULL, NULL);
}
// Set the context current with resource context/surface
if (!_internal_resource_make_current(eng_data, NULL))
if (!sfc->pbuffer.native_surface)
{
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, NULL))
{
ERR("Error doing an internal resource make current");
return 0;
}
}
// Destroy surface used for 1.1
if (sfc->gles1_indirect)
{
int ret;
if (!evgl_engine->funcs->gles1_surface_destroy)
{
ERR("Error destroying GLES 1.x surface");
return 0;
}
INF("Destroying special surface used for GLES 1.x rendering");
ret = evgl_engine->funcs->gles1_surface_destroy(eng_data, sfc);
if (!ret) ERR("Engine failed to destroy a GLES1.x Surface.");
return ret;
}
// Destroy created buffers
if (!_surface_buffers_destroy(sfc))
{
@ -1563,6 +1807,24 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
return 0;
}
// Destroy PBuffer surfaces
if (sfc->pbuffer.native_surface)
{
int ret;
if (sfc->pbuffer.fbo)
glDeleteFramebuffers(1, &sfc->pbuffer.fbo);
ret = evgl_engine->funcs->pbuffer_surface_destroy(eng_data, sfc->pbuffer.native_surface);
LKL(evgl_engine->resource_lock);
evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
LKU(evgl_engine->resource_lock);
free(sfc);
if (!ret) ERR("Engine failed to destroy a PBuffer.");
return ret;
}
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
{
ERR("Error doing make_current(NULL, NULL).");
@ -1570,7 +1832,25 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
}
// Remove it from the list
LKL(evgl_engine->resource_lock);
evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
LKU(evgl_engine->resource_lock);
if (sfc->direct_fb_opt &&
(sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt))
{
Eina_List *found;
found = eina_list_data_find_list(evgl_engine->direct_depth_stencil_surfaces, sfc);
need_reconfigure = !!found;
evgl_engine->direct_depth_stencil_surfaces =
eina_list_remove_list(evgl_engine->direct_depth_stencil_surfaces, found);
}
if (need_reconfigure)
{
// See FIXME notice above in _internal_config_set
WRN("Surface reconfigure is not implemented yet");
}
free(sfc);
sfc = NULL;
@ -1580,7 +1860,8 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
}
void *
evgl_context_create(void *eng_data, EVGL_Context *share_ctx)
evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
Evas_GL_Context_Version version)
{
EVGL_Context *ctx = NULL;
@ -1588,6 +1869,14 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx)
if (!evgl_engine)
{
ERR("Invalid EVGL Engine!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ACCESS);
return NULL;
}
if ((version < EVAS_GL_GLES_1_X) || (version > EVAS_GL_GLES_3_X))
{
ERR("Invalid context version number %d", version);
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_PARAMETER);
return NULL;
}
@ -1596,13 +1885,17 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx)
if (!ctx)
{
ERR("Error allocating context object.");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
return NULL;
}
ctx->version = version;
// Call engine create context
if (share_ctx)
ctx->context = evgl_engine->funcs->context_create(eng_data, share_ctx->context);
ctx->context = evgl_engine->funcs->context_create(eng_data, share_ctx->context, version);
else
ctx->context = evgl_engine->funcs->context_create(eng_data, NULL);
ctx->context = evgl_engine->funcs->context_create(eng_data, NULL, version);
// Call engine create context
if (!ctx->context)
@ -1613,7 +1906,9 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx)
}
// Keep track of all the created context
LKL(evgl_engine->resource_lock);
evgl_engine->contexts = eina_list_prepend(evgl_engine->contexts, ctx);
LKU(evgl_engine->resource_lock);
return ctx;
}
@ -1655,7 +1950,9 @@ evgl_context_destroy(void *eng_data, EVGL_Context *ctx)
}
// Remove it from the list
LKL(evgl_engine->resource_lock);
evgl_engine->contexts = eina_list_remove(evgl_engine->contexts, ctx);
LKU(evgl_engine->resource_lock);
// Free context
free(ctx);
@ -1677,6 +1974,8 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
(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);
return 0;
}
@ -1726,6 +2025,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, 1))
{
ERR("Unable to destroy surface buffers!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
return 0;
}
sfc->buffers_allocated = 0;
@ -1745,6 +2045,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1))
{
ERR("Unable Create Specificed Surfaces. Unsupported format!");
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
return 0;
};
sfc->buffers_allocated = 1;
@ -1757,9 +2058,28 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
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;
}
if (ctx->version == EVAS_GL_GLES_1_X)
{
if (_evgl_direct_renderable(rsc, sfc))
{
rsc->direct.rendered = 1;
}
else
{
evgl_engine->funcs->make_current(eng_data, sfc->gles1_sfc,
ctx->context, EINA_TRUE);
}
ctx->current_sfc = sfc;
rsc->current_ctx = ctx;
rsc->current_eng = eng_data;
return 1;
}
// Normal FBO Rendering
// Create FBO if it hasn't been created
if (!ctx->surface_fbo)
@ -1775,6 +2095,12 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
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);
ctx->current_fbo = 0;
}
if (ctx->current_fbo == 0)
{
@ -1791,6 +2117,35 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
rsc->direct.rendered = 1;
}
else if (sfc->pbuffer.native_surface)
{
// Call end tiling
if (rsc->direct.partial.enabled)
evgl_direct_partial_render_end();
if (sfc->color_buf)
{
if (!sfc->pbuffer.fbo)
{
glGenFramebuffers(1, &sfc->pbuffer.fbo);
GLERRLOG();
}
if (!_surface_buffers_fbo_set(sfc, sfc->pbuffer.fbo))
ERR("Could not detach current FBO");
}
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)
{
glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
GLERRLOG();
}
rsc->direct.rendered = 0;
}
else
{
// Attach fbo and the buffers
@ -1811,6 +2166,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo))
{
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);
return 0;
}
}
@ -1837,7 +2193,7 @@ evgl_string_query(int name)
switch(name)
{
case EVAS_GL_EXTENSIONS:
return (void*)evgl_api_ext_string_get();
return evgl_api_ext_string_get();
default:
return "";
};
@ -1885,35 +2241,38 @@ evgl_direct_rendered()
return rsc->direct.rendered;
}
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)
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)
{
EVGL_Resource *rsc;
if (!(rsc=_evgl_tls_resource_get())) return;
// Normally direct rendering isn't allowed if alpha is on and
// rotation is not 0. BUT, if override is on, allow it.
if ( (rot==0) ||
((rot!=0) && (evgl_engine->direct_override)) )
/* Normally direct rendering isn't allowed if rotation is not 0.
* BUT, if client_side_rotation or override is on, allow it.
*/
if ((rot == 0) || evgl_engine->direct_override ||
(rsc->current_ctx &&
rsc->current_ctx->current_sfc &&
rsc->current_ctx->current_sfc->client_side_rotation))
{
rsc->direct.enabled = EINA_TRUE;
rsc->direct.win_w = win_w;
rsc->direct.win_h = win_h;
rsc->direct.rot = rot;
rsc->direct.win_w = win_w;
rsc->direct.win_h = win_h;
rsc->direct.rot = rot;
rsc->direct.img.x = img_x;
rsc->direct.img.y = img_y;
rsc->direct.img.w = img_w;
rsc->direct.img.h = img_h;
rsc->direct.img.x = img_x;
rsc->direct.img.y = img_y;
rsc->direct.img.w = img_w;
rsc->direct.img.h = img_h;
rsc->direct.clip.x = clip_x;
rsc->direct.clip.y = clip_y;
rsc->direct.clip.w = clip_w;
rsc->direct.clip.h = clip_h;
rsc->direct.clip.x = clip_x;
rsc->direct.clip.y = clip_y;
rsc->direct.clip.w = clip_w;
rsc->direct.clip.h = clip_h;
}
else
{
@ -1932,11 +2291,19 @@ evgl_direct_info_clear()
}
Evas_GL_API *
evgl_api_get()
evgl_api_get(Evas_GL_Context_Version version)
{
_evgl_api_get(&gl_funcs, evgl_engine->api_debug_mode);
return &gl_funcs;
if (version == EVAS_GL_GLES_2_X)
{
_evgl_api_get(&gl_funcs, evgl_engine->api_debug_mode);
return &gl_funcs;
}
else if (version == EVAS_GL_GLES_1_X)
{
_evgl_api_gles1_get(&gles1_funcs, evgl_engine->api_debug_mode);
return &gles1_funcs;
}
else return NULL;
}
@ -1993,7 +2360,7 @@ void
evgl_direct_partial_render_end()
{
EVGL_Context *ctx;
ctx = _evgl_current_context_get();
ctx = evas_gl_common_current_context_get();
if (!ctx) return;

View File

@ -24,15 +24,16 @@ typedef void (*EVGL_Engine_Call)(void *eng_data);
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);
void *evgl_context_create(void *eng_data, EVGL_Context *share_ctx, Evas_GL_Context_Version version);
int evgl_context_destroy(void *eng_data, EVGL_Context *ctx);
int evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx);
const char *evgl_string_query(int name);
void *evgl_proc_address_get(const char *name);
int evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns);
Evas_GL_API *evgl_api_get();
Evas_GL_API *evgl_api_get(Evas_GL_Context_Version version);
int evgl_direct_rendered();
void evgl_direct_override_get(int *override, int *force_off);

View File

@ -50,7 +50,7 @@ struct _EVGL_Interface
int (*surface_destroy)(void *data, void *surface);
// Creates/Destroys the native surface from evas engine.
void *(*context_create)(void *data, void *share_ctx);
void *(*context_create)(void *data, void *share_ctx, Evas_GL_Context_Version version);
int (*context_destroy)(void *data, void *context);
// Calls the make_current from evas_engine.
@ -64,6 +64,16 @@ struct _EVGL_Interface
// Returns the current rotation angle of evas
int (*rotation_angle_get)(void *data);
// Create a pbuffer surface
void *(*pbuffer_surface_create)(void *data, EVGL_Surface *evgl_sfc, const int *attrib_list);
int (*pbuffer_surface_destroy)(void *data, void *surface);
// Create a surface for 1.x rendering (could be pbuffer or xpixmap for instance)
void *(*gles1_surface_create)(void *data, EVGL_Surface *evgl_sfc, Evas_GL_Config *cfg, int w, int h);
// Destroy 1.x surface (could be pbuffer or xpixmap for instance)
int (*gles1_surface_destroy)(void *data, EVGL_Surface *evgl_sfc);
};
struct _EVGL_Surface
@ -93,8 +103,14 @@ struct _EVGL_Surface
GLuint depth_stencil_buf;
GLenum depth_stencil_fmt;
// Direct Rendering Option
int direct_fb_opt;
// Direct Rendering Options
unsigned direct_fb_opt : 1;
unsigned client_side_rotation : 1;
unsigned alpha : 1;
// Flag indicating this surface is used for GLES 1 indirect rendering
unsigned gles1_indirect : 1;
unsigned xpixmap : 1;
int cfg_index;
@ -108,6 +124,22 @@ struct _EVGL_Surface
// 0. color 1. depth 2. stencil 3. depth_stencil
int buffer_mem[4];
//-------------------------//
// Used if gles1_indirect == 1
EVGLNative_Surface gles1_sfc;
void *gles1_sfc_native;
void *gles1_sfc_visual;
//-------------------------//
// Related to PBuffer Surface
struct {
EVGLNative_Surface native_surface;
Evas_GL_Color_Format color_fmt;
GLuint fbo;
Eina_Bool is_pbuffer : 1;
} pbuffer;
//-------------------------//
EVGL_Context *current_ctx;
@ -119,6 +151,8 @@ struct _EVGL_Context
{
EVGLNative_Context context;
Evas_GL_Context_Version version;
// Context FBO
GLuint surface_fbo;
@ -212,6 +246,8 @@ struct _EVGL_Resource
EVGL_Context *current_ctx;
void *current_eng;
int error_state;
struct {
EVGLNative_Surface surface;
int rendered;
@ -235,6 +271,9 @@ struct _EVGL_Resource
Eina_Bool enabled : 1;
} direct;
struct {
GLclampf r, g, b, a;
} clear_color;
};
@ -269,6 +308,7 @@ struct _EVGL_Engine
// Keep track of all the current surfaces/contexts
Eina_List *surfaces;
Eina_List *contexts;
Eina_List *direct_depth_stencil_surfaces;
//void *engine_data;
@ -280,11 +320,13 @@ extern EVGL_Engine *evgl_engine;
// Internally used functions
extern void _evgl_api_get(Evas_GL_API *api, int debug);
extern EVGL_Resource *_evgl_tls_resource_get();
extern void _evgl_api_gles1_get(Evas_GL_API *api, Eina_Bool debug);
extern EVGL_Resource *_evgl_tls_resource_get(void);
extern EVGL_Resource *_evgl_tls_resource_create(void *data);
extern void _evgl_tls_resource_destroy(void *data);
extern EVGL_Context *_evgl_current_context_get();
extern int _evgl_not_in_pixel_get();
extern int _evgl_direct_enabled();
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);
#endif //_EVAS_GL_CORE_PRIVATE_H

View File

@ -84,7 +84,7 @@ static void *evgl_eng_native_window_create(void *data);
static int evgl_eng_native_window_destroy(void *data, void *native_window);
static void *evgl_eng_window_surface_create(void *data, void *native_window);
static int evgl_eng_window_surface_destroy(void *data, void *surface);
static void *evgl_eng_context_create(void *data, void *share_ctx);
static void *evgl_eng_context_create(void *data, void *share_ctx, int version);
static int evgl_eng_context_destroy(void *data, void *context);
static const char *evgl_eng_string_get(void *data);
static void *evgl_eng_proc_address_get(const char *name);
@ -118,7 +118,11 @@ static const EVGL_Interface evgl_funcs =
evgl_eng_make_current,
evgl_eng_proc_address_get,
evgl_eng_string_get,
evgl_eng_rotation_angle_get
evgl_eng_rotation_angle_get,
NULL, // PBuffer
NULL, // PBuffer
NULL, // OpenGL-ES 1
NULL, // OpenGL-ES 1
};
/* local functions */
@ -405,7 +409,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
}
static void *
evgl_eng_context_create(void *data, void *share_ctx)
evgl_eng_context_create(void *data, void *share_ctx, int version)
{
Render_Engine *re = (Render_Engine *)data;
EGLContext context = EGL_NO_CONTEXT;
@ -417,6 +421,12 @@ evgl_eng_context_create(void *data, void *share_ctx)
return NULL;
}
if (version != EVAS_GL_GLES_2_X)
{
ERR("This engine only supports OpenGL-ES 2.0 contexts for now!");
return NULL;
}
context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
context_attrs[1] = 2;
context_attrs[2] = EGL_NONE;

View File

@ -1113,6 +1113,15 @@ eng_gl_surface_create(void *data, void *config, int w, int h)
return evgl_surface_create(data, cfg, w, h);
}
static void *
eng_gl_pbuffer_surface_create(void *data, void *config, int w, int h, const int *attrib_list)
{
Evas_GL_Config *cfg = (Evas_GL_Config *)config;
EVGLINIT(data, NULL);
return evgl_pbuffer_surface_create(data, cfg, w, h, attrib_list);
}
static int
eng_gl_surface_destroy(void *data, void *surface)
{
@ -1123,12 +1132,12 @@ eng_gl_surface_destroy(void *data, void *surface)
}
static void *
eng_gl_context_create(void *data, void *share_context)
eng_gl_context_create(void *data, void *share_context, int version)
{
EVGL_Context *sctx = (EVGL_Context *)share_context;
EVGLINIT(data, NULL);
return evgl_context_create(data, sctx);
return evgl_context_create(data, sctx, version);
}
static int
@ -1147,6 +1156,8 @@ eng_gl_make_current(void *data, void *surface, void *context)
EVGL_Surface *sfc = (EVGL_Surface *)surface;
EVGL_Context *ctx = (EVGL_Context *)context;
// TODO: Add check for main thread before flush
EVGLINIT(data, 0);
if ((sfc) && (ctx))
{
@ -1166,6 +1177,28 @@ eng_gl_make_current(void *data, void *surface, void *context)
return evgl_make_current(data, sfc, ctx);
}
static void *
eng_gl_current_surface_get(void *data EINA_UNUSED)
{
EVGL_Context *ctx;
ctx = evas_gl_common_current_context_get();
if (!ctx)
return NULL;
// Note: We could verify with a call to eglGetCurrentSurface
return ctx->current_sfc;
}
static int
eng_gl_rotation_angle_get(void *data)
{
if (!evgl_engine->funcs->rotation_angle_get) return 0;
if (!_evgl_direct_enabled()) return 0;
return evgl_engine->funcs->rotation_angle_get(data);
}
static void *
eng_gl_string_query(void *data, int name)
{
@ -1190,10 +1223,10 @@ eng_gl_native_surface_get(void *data EINA_UNUSED, void *surface, void *native_su
}
static void *
eng_gl_api_get(void *data)
eng_gl_api_get(void *data, int version)
{
EVGLINIT(data, NULL);
return evgl_api_get();
return evgl_api_get(version);
}
@ -1303,6 +1336,112 @@ eng_gl_surface_read_pixels(void *data, void *surface,
return EINA_TRUE;
}
static Eina_Bool
eng_gl_surface_query(void *data, void *surface, int attr, void *value)
{
Render_Engine_GL_Generic *re = data;
EVGL_Surface *sfc = surface;
#ifdef GL_GLES
if (sfc->pbuffer.is_pbuffer)
{
// This is a real EGL surface, let's just call EGL directly
int val;
Eina_Bool ok;
void *disp;
disp = re->window_egl_display_get(re->software.ob);
ok = eglQuerySurface(disp, sfc->pbuffer.native_surface, attr, &val);
if (!ok) return EINA_FALSE;
switch (attr)
{
case EVAS_GL_TEXTURE_FORMAT:
if (val == EGL_TEXTURE_RGB)
*((int *) value) = EVAS_GL_RGB_888;
else if (val == EGL_TEXTURE_RGBA)
*((int *) value) = EVAS_GL_RGBA_8888;
else // if (val == EGL_NO_TEXTURE)
*((int *) value) = EVAS_GL_NO_FBO;
break;
case EVAS_GL_TEXTURE_TARGET:
if (val == EGL_TEXTURE_2D)
*((int *) value) = val;
else
*((int *) value) = 0;
break;
default:
*((int *) value) = val;
break;
}
return EINA_TRUE;
}
else
{
// Since this is a fake surface (shared with evas), we must filter the
// queries...
switch (attr)
{
// TODO: Add support for whole config get
/*
case EVAS_GL_CONFIG_ID:
*((int *) value) = sfc->cfg_index;
return EINA_TRUE;
*/
case EVAS_GL_WIDTH:
*((int *) value) = sfc->w;
return EINA_TRUE;
case EVAS_GL_HEIGHT:
*((int *) value) = sfc->h;
return EINA_TRUE;
case EVAS_GL_TEXTURE_FORMAT:
// FIXME: Check the possible color formats
if (sfc->color_buf)
{
if ((sfc->color_fmt == GL_RGBA) || (sfc->color_fmt == GL_BGRA))
{
*((Evas_GL_Color_Format *) value) = EVAS_GL_RGBA_8888;
return EINA_TRUE;
}
else if (sfc->color_fmt == GL_RGB)
{
*((Evas_GL_Color_Format *) value) = EVAS_GL_RGB_888;
return EINA_TRUE;
}
}
*((Evas_GL_Color_Format *) value) = EVAS_GL_NO_FBO;
return EINA_TRUE;
case EVAS_GL_TEXTURE_TARGET:
if (sfc->color_buf)
*((int *) value) = EVAS_GL_TEXTURE_2D;
else
*((int *) value) = 0;
return EINA_TRUE;
// TODO: Add support for this:
/*
case EVAS_GL_MULTISAMPLE_RESOLVE:
*((int *) value) = sfc->msaa_samples;
return EINA_TRUE;
*/
// TODO: Add support for mipmaps
/*
case EVAS_GL_MIPMAP_TEXTURE:
case EVAS_GL_MIPMAP_LEVEL:
return eglQuerySurface(re->win->egl_disp, re->win->egl_surface[0],
attr, (int *) value);
*/
default: break;
}
evas_gl_common_error_set(data, EVAS_GL_BAD_ATTRIBUTE);
return EINA_FALSE;
}
#else
(void) re; (void) sfc; (void) attr; (void) value;
ERR("GLX support for surface_query is not implemented!");
return EINA_FALSE;
#endif
}
//--------------------------------//
static int
@ -1769,6 +1908,7 @@ module_open(Evas_Module *em)
ORD(image_cache_get);
ORD(gl_surface_create);
ORD(gl_pbuffer_surface_create);
ORD(gl_surface_destroy);
ORD(gl_context_create);
ORD(gl_context_destroy);
@ -1782,6 +1922,11 @@ module_open(Evas_Module *em)
ORD(gl_surface_lock);
ORD(gl_surface_read_pixels);
ORD(gl_surface_unlock);
//ORD(gl_error_get);
ORD(gl_surface_query);
// gl_current_context_get is in engine
ORD(gl_current_surface_get);
ORD(gl_rotation_angle_get);
ORD(image_load_error_get);

View File

@ -198,10 +198,16 @@ evgl_eng_window_surface_destroy(void *data EINA_UNUSED,
}
static void *
evgl_eng_context_create(void *data, void *share_ctx EINA_UNUSED)
evgl_eng_context_create(void *data, void *share_ctx EINA_UNUSED, int version)
{
Render_Engine *re = data;
if (version != EVAS_GL_GLES_2_X)
{
ERR("This engine only supports OpenGL-ES 2.0 contexts for now!");
return NULL;
}
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
return SDL_GL_CreateContext(re->generic.software.ob->window);
}
@ -248,7 +254,11 @@ static const EVGL_Interface evgl_funcs =
evgl_eng_make_current,
evgl_eng_proc_address_get,
evgl_eng_string_get,
evgl_eng_rotation_angle_get
evgl_eng_rotation_angle_get,
NULL, // PBuffer
NULL, // PBuffer
NULL, // OpenGL-ES 1
NULL, // OpenGL-ES 1
};

View File

@ -22,8 +22,6 @@
#define EVAS_GL_UPDATE_TILE_SIZE 16
static int safe_native = -1;
typedef struct _Render_Engine Render_Engine;
struct _Render_Engine
@ -75,6 +73,10 @@ Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL;
Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;
glsym_func_void glsym_evas_gl_common_error_set = NULL;
glsym_func_int glsym_evas_gl_common_error_get = NULL;
glsym_func_void_ptr glsym_evas_gl_common_current_context_get = NULL;
#ifdef GL_GLES
#ifndef EGL_NATIVE_PIXMAP_KHR
@ -217,6 +219,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
@ -231,12 +234,15 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
ret = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ret)
{
ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
int err = eglGetError();
glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
ERR("eglMakeCurrent() failed! Error Code=%#x", err);
return 0;
}
return 1;
}
// FIXME: Check (eglGetCurrentDisplay() != dpy) ?
if ((eglGetCurrentContext() != ctx) ||
(eglGetCurrentSurface(EGL_READ) != sfc) ||
(eglGetCurrentSurface(EGL_DRAW) != sfc) )
@ -251,7 +257,9 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
if (!ret)
{
ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
int err = eglGetError();
glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
ERR("eglMakeCurrent() failed! Error Code=%#x", err);
return 0;
}
}
@ -267,6 +275,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
if (!ret)
{
ERR("glXMakeCurrent() failed!");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_DISPLAY);
return 0;
}
return 1;
@ -285,6 +294,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush)
if (!ret)
{
ERR("glXMakeCurrent() failed. Ret: %d! Context: %p Surface: %p", ret, (void*)ctx, (void*)sfc);
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_DISPLAY);
return 0;
}
}
@ -303,6 +313,7 @@ evgl_eng_native_window_create(void *data)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return NULL;
}
@ -331,6 +342,7 @@ evgl_eng_native_window_create(void *data)
if (!win)
{
ERR("Creating native X window failed.");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_DISPLAY);
return NULL;
}
@ -346,12 +358,14 @@ evgl_eng_native_window_destroy(void *data, void *native_window)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
if (!native_window)
{
ERR("Inavlid native surface.");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_NATIVE_WINDOW);
return 0;
}
@ -374,6 +388,7 @@ evgl_eng_window_surface_create(void *data, void *native_window EINA_UNUSED)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return NULL;
}
@ -414,6 +429,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
@ -421,6 +437,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
if (!surface)
{
ERR("Invalid surface.");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_SURFACE);
return 0;
}
@ -432,7 +449,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
}
static void *
evgl_eng_context_create(void *data, void *share_ctx)
evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version version)
{
Render_Engine *re = (Render_Engine *)data;
@ -440,6 +457,14 @@ evgl_eng_context_create(void *data, void *share_ctx)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return NULL;
}
if ((version < EVAS_GL_GLES_1_X) || (version > EVAS_GL_GLES_3_X))
{
ERR("Invalid context version number %d", version);
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_PARAMETER);
return NULL;
}
@ -448,7 +473,7 @@ evgl_eng_context_create(void *data, void *share_ctx)
int context_attrs[3];
context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
context_attrs[1] = 2;
context_attrs[1] = version;
context_attrs[2] = EGL_NONE;
// Share context already assumes that it's sharing with evas' context
@ -459,6 +484,13 @@ evgl_eng_context_create(void *data, void *share_ctx)
(EGLContext)share_ctx,
context_attrs);
}
else if (version == EVAS_GL_GLES_1_X)
{
context = eglCreateContext(eng_get_ob(re)->egl_disp,
eng_get_ob(re)->egl_config,
NULL,
context_attrs);
}
else
{
context = eglCreateContext(eng_get_ob(re)->egl_disp,
@ -469,7 +501,9 @@ evgl_eng_context_create(void *data, void *share_ctx)
if (!context)
{
ERR("Engine Context Creations Failed. Error: %#x.", eglGetError());
int err = eglGetError();
ERR("Engine Context Creations Failed. Error: %#x.", err);
glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
return NULL;
}
@ -485,6 +519,15 @@ evgl_eng_context_create(void *data, void *share_ctx)
(GLXContext)share_ctx,
1);
}
/* TODO: Check this case.
else if (version == EVAS_GL_GLES_1_X)
{
context = glXCreateContext(eng_get_ob(re)->info->info.display,
eng_get_ob(re)->visualinfo,
NULL,
1);
}
*/
else
{
context = glXCreateContext(eng_get_ob(re)->info->info.display,
@ -496,6 +539,8 @@ evgl_eng_context_create(void *data, void *share_ctx)
if (!context)
{
ERR("Internal Resource Context Creations Failed.");
if(!(eng_get_ob(re)->info->info.display)) glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_DISPLAY);
if(!(eng_get_ob(re)->win)) glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_NATIVE_WINDOW);
return NULL;
}
@ -513,6 +558,8 @@ evgl_eng_context_destroy(void *data, void *context)
if ((!re) || (!context))
{
ERR("Invalid Render Input Data. Engine: %p, Context: %p", data, context);
if (!re) glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
if (!context) glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_CONTEXT);
return 0;
}
@ -534,6 +581,7 @@ evgl_eng_string_get(void *data)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return NULL;
}
@ -566,18 +614,346 @@ evgl_eng_rotation_angle_get(void *data)
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
if ((eng_get_ob(re)) && (eng_get_ob(re)->gl_context))
return eng_get_ob(re)->gl_context->rot;
return eng_get_ob(re)->gl_context->rot;
else
{
ERR("Unable to retrieve rotation angle.");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_CONTEXT);
return 0;
}
}
static void *
evgl_eng_pbuffer_surface_create(void *data, EVGL_Surface *sfc,
const int *attrib_list)
{
Render_Engine_GL_Generic *re = data;
// TODO: Add support for surfaceless pbuffers (EGL_NO_TEXTURE)
// TODO: Add support for EGL_MIPMAP_TEXTURE??? (GLX doesn't support them)
if (attrib_list)
WRN("This PBuffer implementation does not support extra attributes yet");
#ifdef GL_GLES
int config_attrs[20];
int surface_attrs[20];
EGLSurface egl_sfc;
EGLConfig egl_cfg;
int num_config, i = 0;
EGLDisplay disp;
EGLContext ctx;
disp = re->window_egl_display_get(re->software.ob);
ctx = re->window_gl_context_get(re->software.ob);
#if 0
// Choose framebuffer configuration
// DISABLED FOR NOW
if (sfc->pbuffer.color_fmt != EVAS_GL_NO_FBO)
{
config_attrs[i++] = EGL_RED_SIZE;
config_attrs[i++] = 1;
config_attrs[i++] = EGL_GREEN_SIZE;
config_attrs[i++] = 1;
config_attrs[i++] = EGL_BLUE_SIZE;
config_attrs[i++] = 1;
if (sfc->pbuffer.color_fmt == EVAS_GL_RGBA_8888)
{
config_attrs[i++] = EGL_ALPHA_SIZE;
config_attrs[i++] = 1;
//config_attrs[i++] = EGL_BIND_TO_TEXTURE_RGBA;
//config_attrs[i++] = EGL_TRUE;
}
else
{
//config_attrs[i++] = EGL_BIND_TO_TEXTURE_RGB;
//config_attrs[i++] = EGL_TRUE;
}
}
if (sfc->depth_fmt || sfc->depth_stencil_fmt)
{
config_attrs[i++] = EGL_DEPTH_SIZE;
config_attrs[i++] = 1;
}
if (sfc->stencil_fmt || sfc->depth_stencil_fmt)
{
config_attrs[i++] = EGL_STENCIL_SIZE;
config_attrs[i++] = 1;
}
config_attrs[i++] = EGL_RENDERABLE_TYPE;
config_attrs[i++] = EGL_OPENGL_ES2_BIT;
config_attrs[i++] = EGL_SURFACE_TYPE;
config_attrs[i++] = EGL_PBUFFER_BIT;
config_attrs[i++] = EGL_NONE;
#else
// It looks like eglMakeCurrent might fail if we use a different config from
// the actual display surface. This is weird.
i = 0;
config_attrs[i++] = EGL_CONFIG_ID;
config_attrs[i++] = 0;
config_attrs[i++] = EGL_NONE;
eglQueryContext(disp, ctx, EGL_CONFIG_ID, &config_attrs[1]);
#endif
if (!eglChooseConfig(disp, config_attrs, &egl_cfg, 1, &num_config)
|| (num_config < 1))
{
int err = eglGetError();
glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
ERR("eglChooseConfig failed with error %x", err);
return NULL;
}
// Now, choose the config for the PBuffer
i = 0;
surface_attrs[i++] = EGL_WIDTH;
surface_attrs[i++] = sfc->w;
surface_attrs[i++] = EGL_HEIGHT;
surface_attrs[i++] = sfc->h;
#if 0
// Adding these parameters will trigger EGL_BAD_ATTRIBUTE because
// the config also requires EGL_BIND_TO_TEXTURE_RGB[A]. But some drivers
// don't support those configs (eg. nvidia)
surface_attrs[i++] = EGL_TEXTURE_FORMAT;
if (sfc->pbuffer.color_fmt == EVAS_GL_RGB_888)
surface_attrs[i++] = EGL_TEXTURE_RGB;
else
surface_attrs[i++] = EGL_TEXTURE_RGBA;
surface_attrs[i++] = EGL_TEXTURE_TARGET;
surface_attrs[i++] = EGL_TEXTURE_2D;
surface_attrs[i++] = EGL_MIPMAP_TEXTURE;
surface_attrs[i++] = EINA_TRUE;
#endif
surface_attrs[i++] = EGL_NONE;
egl_sfc = eglCreatePbufferSurface(disp, egl_cfg, surface_attrs);
if (!egl_sfc)
{
int err = eglGetError();
glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
ERR("eglCreatePbufferSurface failed with error %x", err);
return NULL;
}
return egl_sfc;
#else
GLXPbuffer pbuf;
GLXFBConfig *cfgs;
int config_attrs[20];
int surface_attrs[20];
int ncfg = 0, i;
// TODO: Check all required config attributes
#ifndef GLX_VISUAL_ID
# define GLX_VISUAL_ID 0x800b
#endif
i = 0;
if (sfc->pbuffer.color_fmt != EVAS_GL_NO_FBO)
{
config_attrs[i++] = GLX_BUFFER_SIZE;
if (sfc->pbuffer.color_fmt == EVAS_GL_RGBA_8888)
{
config_attrs[i++] = 32;
//config_attrs[i++] = GLX_BIND_TO_TEXTURE_RGBA_EXT;
//config_attrs[i++] = 1;
}
else
{
config_attrs[i++] = 24;
//config_attrs[i++] = GLX_BIND_TO_TEXTURE_RGB_EXT;
//config_attrs[i++] = 1;
}
}
if (sfc->depth_fmt)
{
config_attrs[i++] = GLX_DEPTH_SIZE;
config_attrs[i++] = 24; // FIXME: This should depend on the requested bits
}
if (sfc->stencil_fmt)
{
config_attrs[i++] = GLX_STENCIL_SIZE;
config_attrs[i++] = 8; // FIXME: This should depend on the requested bits
}
//config_attrs[i++] = GLX_VISUAL_ID;
//config_attrs[i++] = XVisualIDFromVisual(vis);
config_attrs[i++] = 0;
cfgs = glXChooseFBConfig(re->software.ob->disp, re->software.ob->screen,
config_attrs, &ncfg);
if (!cfgs || !ncfg)
{
ERR("GLX failed to find a valid config for the pbuffer");
if (cfgs) XFree(cfgs);
return NULL;
}
i = 0;
surface_attrs[i++] = GLX_LARGEST_PBUFFER;
surface_attrs[i++] = 0;
surface_attrs[i++] = GLX_PBUFFER_WIDTH;
surface_attrs[i++] = sfc->w;
surface_attrs[i++] = GLX_PBUFFER_HEIGHT;
surface_attrs[i++] = sfc->h;
surface_attrs[i++] = 0;
pbuf = glXCreatePbuffer(re->software.ob->disp, cfgs[0], surface_attrs);
if (cfgs) XFree(cfgs);
if (!pbuf)
{
ERR("GLX failed to create a pbuffer");
return NULL;
}
return (void*)(intptr_t)pbuf;
#endif
}
static int
evgl_eng_pbuffer_surface_destroy(void *data, void *surface)
{
/* EVGLINIT(re, 0); */
if (!data)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(NULL, EVAS_GL_NOT_INITIALIZED);
return 0;
}
if (!surface)
{
ERR("Invalid surface.");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_SURFACE);
return 0;
}
#ifdef GL_GLES
Render_Engine *re = data;
eglDestroySurface(eng_get_ob(re)->egl_disp, (EGLSurface)surface);
#else
Render_Engine_GL_Generic *re = data;
GLXPbuffer pbuf = (GLXPbuffer)(intptr_t) surface;
glXDestroyPbuffer(re->software.ob->disp, pbuf);
#endif
return 1;
}
// This function should create a surface that can be used for offscreen rendering
// with GLES 1.x, and still be bindable to a texture in Evas main GL context.
// For now, this will create an X pixmap... Ideally it should be able to create
// a bindable pbuffer surface or just an FBO if that is supported and it can
// be shared with Evas.
static void *
evgl_eng_gles1_surface_create(void *data, EVGL_Surface *evgl_sfc,
Evas_GL_Config *cfg, int w, int h)
{
Render_Engine *re = (Render_Engine *)data;
Pixmap px;
if (!re || !evgl_sfc || !cfg)
{
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_PARAMETER);
return NULL;
}
if (cfg->gles_version != EVAS_GL_GLES_1_X)
{
ERR("Inconsistent parameters, not creating any surface!");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_PARAMETER);
return NULL;
}
// FIXME: Check the depth of the buffer!
px = XCreatePixmap(eng_get_ob(re)->disp, eng_get_ob(re)->win, w, h,
XDefaultDepth(eng_get_ob(re)->disp, eng_get_ob(re)->screen));
if (!px)
{
ERR("Failed to create XPixmap!");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_ALLOC);
return NULL;
}
#ifdef GL_GLES
EGLSurface egl_sfc;
egl_sfc = eglCreatePixmapSurface(eng_get_ob(re)->egl_disp, eng_get_ob(re)->egl_config, px, NULL);
if (!egl_sfc)
{
int err = eglGetError();
ERR("eglCreatePixmapSurface failed with error: %x", err);
glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
XFreePixmap(eng_get_ob(re)->disp, px);
return NULL;
}
evgl_sfc->gles1_indirect = EINA_TRUE;
evgl_sfc->xpixmap = EINA_TRUE;
evgl_sfc->gles1_sfc = egl_sfc;
evgl_sfc->gles1_sfc_native = (void *)(intptr_t) px;
evgl_sfc->gles1_sfc_visual = eng_get_ob(re)->info->info.visual; // FIXME: Check this!
return evgl_sfc;
#else
evgl_sfc->gles1_indirect = EINA_TRUE;
evgl_sfc->xpixmap = EINA_TRUE;
evgl_sfc->gles1_sfc_native = (void *)(intptr_t) px;
evgl_sfc->gles1_sfc = (void *)(intptr_t) px;
evgl_sfc->gles1_sfc_visual = eng_get_ob(re)->info->info.visual; // FIXME: Check this!
return evgl_sfc;
#endif
}
// This function should destroy the surface used for offscreen rendering
// with GLES 1.x.This will also destroy the X pixmap...
static int
evgl_eng_gles1_surface_destroy(void *data, EVGL_Surface *evgl_sfc)
{
Render_Engine *re = (Render_Engine *)data;
if (!re)
{
ERR("Invalid Render Engine Data!");
glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
return 0;
}
#ifdef GL_GLES
if ((!evgl_sfc) || (!evgl_sfc->gles1_sfc))
{
ERR("Invalid surface.");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_SURFACE);
return 0;
}
eglDestroySurface(eng_get_ob(re)->egl_disp, (EGLSurface)evgl_sfc->gles1_sfc);
#endif
if (!evgl_sfc->gles1_sfc_native)
{
ERR("Inconsistent parameters, not freeing XPixmap for gles1 surface!");
glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_PARAMETER);
return 0;
}
XFreePixmap(eng_get_ob(re)->disp, (Pixmap)evgl_sfc->gles1_sfc_native);
return 1;
}
static const EVGL_Interface evgl_funcs =
{
evgl_eng_display_get,
@ -591,7 +967,11 @@ static const EVGL_Interface evgl_funcs =
evgl_eng_make_current,
evgl_eng_proc_address_get,
evgl_eng_string_get,
evgl_eng_rotation_angle_get
evgl_eng_rotation_angle_get,
evgl_eng_pbuffer_surface_create,
evgl_eng_pbuffer_surface_destroy,
evgl_eng_gles1_surface_create,
evgl_eng_gles1_surface_destroy,
};
//----------------------------------------------------------//
@ -630,6 +1010,9 @@ gl_symbols(void)
LINK2GENERIC(evas_gl_preload_shutdown);
LINK2GENERIC(evgl_engine_shutdown);
LINK2GENERIC(evas_gl_symbols);
LINK2GENERIC(evas_gl_common_error_get);
LINK2GENERIC(evas_gl_common_error_set);
LINK2GENERIC(evas_gl_common_current_context_get);
#ifdef GL_GLES
#define FINDSYM(dst, sym, typ) \
@ -916,23 +1299,6 @@ eng_setup(Evas *eo_e, void *in)
}
}
if (safe_native == -1)
{
s = getenv("EVAS_GL_SAFE_NATIVE");
safe_native = 0;
if (s) safe_native = atoi(s);
else
{
s = (const char *)glGetString(GL_RENDERER);
if (s)
{
if (strstr(s, "PowerVR SGX 540") ||
strstr(s, "Mali-400 MP"))
safe_native = 1;
}
}
}
// Set this env var to dump files every frame
// Or set the global var in gdb to 1|0 to turn it on and off
if (getenv("EVAS_GL_SWAP_BUFFER_DEBUG_ALWAYS"))
@ -1240,6 +1606,52 @@ eng_output_dump(void *data)
_re_winfree(re);
}
static void *
eng_gl_current_context_get(void *data EINA_UNUSED)
{
EVGL_Context *ctx;
ctx = glsym_evas_gl_common_current_context_get();
if (!ctx)
return NULL;
#ifdef GL_GLES
if (eglGetCurrentContext() == (ctx->context))
return ctx;
else
return NULL;
#else
if (glXGetCurrentContext() == (ctx->context))
return ctx;
else
return NULL;
#endif
}
static int
eng_gl_error_get(void *data)
{
int err;
if ((err = glsym_evas_gl_common_error_get(data)) != EVAS_GL_SUCCESS)
goto end;
#ifdef GL_GLES
err = eglGetError() - EGL_SUCCESS;
#else
Render_Engine *re = data;
if (!eng_get_ob(re)->win)
err = EVAS_GL_BAD_DISPLAY;
else if (!eng_get_ob(re)->info)
err = EVAS_GL_BAD_SURFACE;
#endif
end:
glsym_evas_gl_common_error_set(data, EVAS_GL_SUCCESS);
return err;
}
/////////////////////////////////////////////////////////////////////////
//
//
@ -1357,15 +1769,19 @@ _native_free_cb(void *data, void *image)
#ifdef GL_GLES
if (n->egl_surface)
{
if (glsym_eglDestroyImage)
{
glsym_eglDestroyImage(eng_get_ob(re)->egl_disp,
n->egl_surface);
if (eglGetError() != EGL_SUCCESS)
ERR("eglDestroyImage() failed.");
}
else
ERR("Try eglDestroyImage on EGL with no support");
int err;
if (glsym_eglDestroyImage)
{
glsym_eglDestroyImage(eng_get_ob(re)->egl_disp,
n->egl_surface);
if ((err = eglGetError()) != EGL_SUCCESS)
{
ERR("eglDestroyImage() failed.");
glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
}
}
else
ERR("Try eglDestroyImage on EGL with no support");
}
#else
# ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
@ -1549,7 +1965,12 @@ eng_image_native_set(void *data, void *image, void *native)
if (!eglChooseConfig(eng_get_ob(re)->egl_disp, config_attrs,
&egl_config, 1, &num_config))
ERR("eglChooseConfig() failed for pixmap 0x%x, num_config = %i", (unsigned int)pm, num_config);
{
int err = eglGetError();
ERR("eglChooseConfig() failed for pixmap 0x%x, num_config = %i with error %d",
(unsigned int)pm, num_config, err);
glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
}
else
{
int val;
@ -1875,6 +2296,10 @@ module_open(Evas_Module *em)
ORD(image_native_set);
ORD(gl_error_get);
// gl_current_surface_get is in gl generic
ORD(gl_current_context_get);
gl_symbols();
/* now advertise out own api */

View File

@ -1,13 +1,14 @@
#include "evas_engine.h"
static Outbuf *_evas_gl_x11_window = NULL;
static Eina_TLS _outbuf_key = 0;
static Eina_TLS _context_key = 0;
#ifdef GL_GLES
static EGLContext context = EGL_NO_CONTEXT;
typedef EGLContext GLContext;
#else
// FIXME: this will only work for 1 display connection (glx land can have > 1)
static GLXContext context = 0;
static GLXContext rgba_context = 0;
typedef GLXContext GLContext;
static Eina_TLS _rgba_context_key = 0;
static GLXFBConfig fbconf = 0;
static GLXFBConfig rgba_fbconf = 0;
#endif
@ -21,6 +22,80 @@ static Colormap _evas_gl_x11_cmap = 0;
static Colormap _evas_gl_x11_rgba_cmap = 0;
static int win_count = 0;
static Eina_Bool initted = EINA_FALSE;
Eina_Bool
eng_init(void)
{
if (initted)
return EINA_TRUE;
// FIXME: These resources are never released
if (!eina_tls_new(&_outbuf_key))
goto error;
if (!eina_tls_new(&_context_key))
goto error;
eina_tls_set(_outbuf_key, NULL);
eina_tls_set(_context_key, NULL);
#ifndef GL_GLES
if (!eina_tls_new(&_rgba_context_key))
goto error;
eina_tls_set(_rgba_context_key, NULL);
#endif
initted = EINA_TRUE;
return EINA_TRUE;
error:
ERR("Could not create TLS key!");
return EINA_FALSE;
}
static inline Outbuf *
_tls_outbuf_get(void)
{
if (!initted) eng_init();
return eina_tls_get(_outbuf_key);
}
static inline Eina_Bool
_tls_outbuf_set(Outbuf *xwin)
{
if (!initted) eng_init();
return eina_tls_set(_outbuf_key, xwin);
}
static inline GLContext
_tls_context_get(void)
{
if (!initted) eng_init();
return eina_tls_get(_context_key);
}
static inline Eina_Bool
_tls_context_set(GLContext ctx)
{
if (!initted) eng_init();
return eina_tls_set(_context_key, ctx);
}
#ifndef GL_GLES
static inline GLXContext
_tls_rgba_context_get(void)
{
if (!initted) eng_init();
return eina_tls_get(_rgba_context_key);
}
static inline Eina_Bool
_tls_rgba_context_set(GLXContext ctx)
{
if (!initted) eng_init();
return eina_tls_set(_rgba_context_key, ctx);
}
#endif
Outbuf *
eng_window_new(Evas_Engine_Info_GL_X11 *info,
@ -38,11 +113,16 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
Render_Engine_Swap_Mode swap_mode)
{
Outbuf *gw;
GLContext context;
#ifdef GL_GLES
int context_attrs[3];
int config_attrs[40];
int major_version, minor_version;
int num_config, n = 0;
#else
# ifdef NEWGL
GLXContext rgbactx;
# endif
#endif
const GLubyte *vendor, *renderer, *version;
int blacklist = 0;
@ -140,6 +220,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
return NULL;
}
context = _tls_context_get();
gw->egl_context[0] = eglCreateContext
(gw->egl_disp, gw->egl_config, context, context_attrs);
if (gw->egl_context[0] == EGL_NO_CONTEXT)
@ -148,7 +229,8 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
eng_window_free(gw);
return NULL;
}
if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
if (context == EGL_NO_CONTEXT)
_tls_context_set(gw->egl_context[0]);
if (eglMakeCurrent(gw->egl_disp,
gw->egl_surface[0],
@ -193,6 +275,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
}
// GLX
#else
context = _tls_context_get();
if (!context)
{
#ifdef NEWGL
@ -210,18 +293,21 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
else
context = glXCreateContext(gw->disp, gw->visualinfo, NULL, GL_TRUE);
#endif
_tls_context_set(context);
}
#ifdef NEWGL
if ((gw->alpha) && (!rgba_context))
rgbactx = _tls_rgba_context_get();
if ((gw->alpha) && (!rgbactx))
{
if (indirect)
rgba_context = glXCreateNewContext(gw->disp, rgba_fbconf,
GLX_RGBA_TYPE, context,
GL_FALSE);
rgbactx = glXCreateNewContext(gw->disp, rgba_fbconf,
GLX_RGBA_TYPE, context,
GL_FALSE);
else
rgba_context = glXCreateNewContext(gw->disp, rgba_fbconf,
GLX_RGBA_TYPE, context,
GL_TRUE);
rgbactx = glXCreateNewContext(gw->disp, rgba_fbconf,
GLX_RGBA_TYPE, context,
GL_TRUE);
_tls_rgba_context_set(rgbactx);
}
if (gw->alpha)
gw->glxwin = glXCreateWindow(gw->disp, rgba_fbconf, gw->win, NULL);
@ -234,7 +320,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
return NULL;
}
if (gw->alpha) gw->context = rgba_context;
if (gw->alpha) gw->context = rgbactx;
else gw->context = context;
#else
gw->context = context;
@ -404,10 +490,16 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
void
eng_window_free(Outbuf *gw)
{
Outbuf *xwin;
GLContext context;
int ref = 0;
win_count--;
eng_window_use(gw);
if (gw == _evas_gl_x11_window) _evas_gl_x11_window = NULL;
context = _tls_context_get();
xwin = _tls_outbuf_get();
if (gw == xwin) _tls_outbuf_set(NULL);
if (gw->gl_context)
{
ref = gw->gl_context->references - 1;
@ -417,6 +509,8 @@ eng_window_free(Outbuf *gw)
eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (gw->egl_surface[0] != EGL_NO_SURFACE)
eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
if (gw->egl_surface[1] != EGL_NO_SURFACE)
eglDestroySurface(gw->egl_disp, gw->egl_surface[1]);
if (gw->egl_context[0] != context)
eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
if (ref == 0)
@ -424,7 +518,7 @@ eng_window_free(Outbuf *gw)
if (context) eglDestroyContext(gw->egl_disp, context);
eglTerminate(gw->egl_disp);
eglReleaseThread();
context = EGL_NO_CONTEXT;
_tls_context_set(EGL_NO_CONTEXT);
}
#else
if (gw->glxwin)
@ -434,15 +528,16 @@ eng_window_free(Outbuf *gw)
}
if (ref == 0)
{
GLXContext rgbactx = _tls_rgba_context_get();
if (!gw->glxwin)
{
if (glXGetCurrentContext() == gw->context)
glXMakeCurrent(gw->disp, 0, NULL);
}
if (context) glXDestroyContext(gw->disp, context);
if (rgba_context) glXDestroyContext(gw->disp, rgba_context);
context = 0;
rgba_context = 0;
if (rgbactx) glXDestroyContext(gw->disp, rgbactx);
_tls_context_set(0);
_tls_rgba_context_set(0);
fbconf = 0;
rgba_fbconf = 0;
}
@ -504,29 +599,43 @@ void
eng_window_use(Outbuf *gw)
{
Eina_Bool force_use = EINA_FALSE;
Outbuf *xwin;
xwin = _tls_outbuf_get();
glsym_evas_gl_preload_render_lock(eng_window_make_current, gw);
#ifdef GL_GLES
if (_evas_gl_x11_window)
if (xwin)
{
if (eglGetCurrentContext() != _evas_gl_x11_window->egl_context[0])
force_use = EINA_TRUE;
if ((eglGetCurrentDisplay() !=
xwin->egl_disp) ||
(eglGetCurrentContext() !=
xwin->egl_context[0])
#if 0
// FIXME: Figure out what that offscreen thing was about...
|| (eglGetCurrentSurface(EGL_READ) !=
xwin->egl_surface[xwin->offscreen])
|| (eglGetCurrentSurface(EGL_DRAW) !=
xwin->egl_surface[xwin->offscreen])
#endif
)
force_use = EINA_TRUE;
}
#else
if (_evas_gl_x11_window)
if (xwin)
{
if (glXGetCurrentContext() != _evas_gl_x11_window->context)
if (glXGetCurrentContext() != xwin->context)
force_use = EINA_TRUE;
}
#endif
if ((_evas_gl_x11_window != gw) || (force_use))
if ((xwin != gw) || (force_use))
{
if (_evas_gl_x11_window)
if (xwin)
{
glsym_evas_gl_common_context_use(_evas_gl_x11_window->gl_context);
glsym_evas_gl_common_context_flush(_evas_gl_x11_window->gl_context);
glsym_evas_gl_common_context_use(xwin->gl_context);
glsym_evas_gl_common_context_flush(xwin->gl_context);
}
_evas_gl_x11_window = gw;
_tls_outbuf_set(gw);
if (gw)
{
// EGL / GLES
@ -571,16 +680,23 @@ eng_window_unsurf(Outbuf *gw)
if (!getenv("EVAS_GL_WIN_RESURF")) return;
if (getenv("EVAS_GL_INFO"))
printf("unsurf %p\n", gw);
#ifdef GL_GLES
if (_evas_gl_x11_window)
glsym_evas_gl_common_context_flush(_evas_gl_x11_window->gl_context);
if (_evas_gl_x11_window == gw)
Outbuf *xwin;
xwin = _tls_outbuf_get();
if (xwin)
glsym_evas_gl_common_context_flush(xwin->gl_context);
if (xwin == gw)
{
eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (gw->egl_surface[0] != EGL_NO_SURFACE)
eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
gw->egl_surface[0] = EGL_NO_SURFACE;
_evas_gl_x11_window = NULL;
if (gw->egl_surface[1] != EGL_NO_SURFACE)
eglDestroySurface(gw->egl_disp, gw->egl_surface[1]);
gw->egl_surface[1] = EGL_NO_SURFACE;
_tls_outbuf_set(NULL);
}
#else
if (gw->glxwin)
@ -1059,19 +1175,6 @@ eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update EINA_UNUSED,
if (!_re_wincheck(ob)) return;
ob->draw.drew = 1;
glsym_evas_gl_common_context_flush(ob->gl_context);
#ifdef GL_GLES
// this is needed to make sure all previous rendering is flushed to
// buffers/surfaces
// previous rendering should be done and swapped
//xx if (!safe_native) eglWaitNative(EGL_CORE_NATIVE_ENGINE);
// if (eglGetError() != EGL_SUCCESS)
// {
// printf("Error: eglWaitNative(EGL_CORE_NATIVE_ENGINE) fail.\n");
// }
#else
// previous rendering should be done and swapped
//xx if (!safe_native) glXWaitX();
#endif
}
void

View File

@ -116,6 +116,10 @@ static void *gl_lib_handle;
static int gl_lib_is_gles = 0;
static Evas_GL_API gl_funcs;
static Eina_Bool _tls_init = EINA_FALSE;
static Eina_TLS gl_current_ctx_key = 0;
static Eina_TLS gl_current_sfc_key = 0;
//------------------------------------------------------//
// OSMesa APIS...
static OSMesaContext (*_sym_OSMesaCreateContextExt) (GLenum format, GLint depthBits, GLint stencilBits, GLint accumBits, OSMesaContext sharelist) = NULL;
@ -2263,7 +2267,25 @@ eng_image_load_error_get(void *data EINA_UNUSED, void *image)
return im->cache_entry.load_error;
}
//------------ Evas GL engine code ---------------//
#ifdef EVAS_GL
static inline int
_tls_check(void)
{
// note: this is not thread safe...
if (!_tls_init)
{
if (!eina_tls_new(&gl_current_ctx_key)) return 0;
if (!eina_tls_new(&gl_current_sfc_key)) return 0;
eina_tls_set(gl_current_ctx_key, NULL);
eina_tls_set(gl_current_sfc_key, NULL);
}
_tls_init = EINA_TRUE;
return 1;
}
#endif
static void *
eng_gl_surface_create(void *data EINA_UNUSED, void *config, int w, int h)
{
@ -2370,6 +2392,10 @@ eng_gl_surface_destroy(void *data EINA_UNUSED, void *surface)
if (!sfc) return 0;
_tls_check();
if (sfc == eina_tls_get(gl_current_sfc_key))
eina_tls_set(gl_current_sfc_key, NULL);
if (sfc->buffer) free(sfc->buffer);
free(sfc);
@ -2384,12 +2410,19 @@ eng_gl_surface_destroy(void *data EINA_UNUSED, void *surface)
}
static void *
eng_gl_context_create(void *data EINA_UNUSED, void *share_context)
eng_gl_context_create(void *data EINA_UNUSED, void *share_context,
int version)
{
#ifdef EVAS_GL
Render_Engine_GL_Context *ctx;
Render_Engine_GL_Context *share_ctx;
if (version != EVAS_GL_GLES_2_X)
{
ERR("This engine only supports OpenGL-ES 2.0 contexts for now!");
return NULL;
}
ctx = calloc(1, sizeof(Render_Engine_GL_Context));
if (!ctx) return NULL;
@ -2432,6 +2465,10 @@ eng_gl_context_destroy(void *data EINA_UNUSED, void *context)
if (!ctx) return 0;
_tls_check();
if (ctx == eina_tls_get(gl_current_ctx_key))
eina_tls_set(gl_current_ctx_key, NULL);
_sym_OSMesaDestroyContext(ctx->context);
free(ctx);
@ -2456,11 +2493,15 @@ eng_gl_make_current(void *data EINA_UNUSED, void *surface, void *context)
sfc = (Render_Engine_GL_Surface*)surface;
ctx = (Render_Engine_GL_Context*)context;
_tls_check();
// Unset surface/context
if ((!sfc) || (!ctx))
{
if (ctx) ctx->current_sfc = NULL;
if (sfc) sfc->current_ctx = NULL;
eina_tls_set(gl_current_ctx_key, NULL);
eina_tls_set(gl_current_sfc_key, NULL);
return 1;
}
@ -2480,6 +2521,8 @@ eng_gl_make_current(void *data EINA_UNUSED, void *surface, void *context)
if (!ctx->context)
{
ERR("Error initializing context.");
eina_tls_set(gl_current_ctx_key, NULL);
eina_tls_set(gl_current_sfc_key, NULL);
return 0;
}
@ -2494,6 +2537,8 @@ eng_gl_make_current(void *data EINA_UNUSED, void *surface, void *context)
if (ret == GL_FALSE)
{
ERR("Error doing MakeCurrent.");
eina_tls_set(gl_current_ctx_key, NULL);
eina_tls_set(gl_current_sfc_key, NULL);
return 0;
}
@ -2502,6 +2547,8 @@ eng_gl_make_current(void *data EINA_UNUSED, void *surface, void *context)
// Set the current surface/context
ctx->current_sfc = sfc;
sfc->current_ctx = ctx;
eina_tls_set(gl_current_ctx_key, ctx);
eina_tls_set(gl_current_sfc_key, sfc);
return 1;
#else
@ -2556,8 +2603,11 @@ eng_gl_native_surface_get(void *data EINA_UNUSED, void *surface, void *native_su
static void *
eng_gl_api_get(void *data EINA_UNUSED)
eng_gl_api_get(void *data EINA_UNUSED, int version)
{
if (version != EVAS_GL_GLES_2_X)
return NULL;
#ifdef EVAS_GL
return &gl_funcs;
#else
@ -2565,6 +2615,39 @@ eng_gl_api_get(void *data EINA_UNUSED)
#endif
}
static int
eng_gl_error_get(void *data)
{
Render_Engine_Software_Generic *re = data;
// TODO: Track EGL-like errors in the software engines
if (!re->ob)
return EVAS_GL_BAD_DISPLAY;
return EVAS_GL_SUCCESS;
}
static void *
eng_gl_current_context_get(void *data EINA_UNUSED)
{
_tls_check();
return eina_tls_get(gl_current_ctx_key);
}
static void *
eng_gl_current_surface_get(void *data EINA_UNUSED)
{
_tls_check();
return eina_tls_get(gl_current_sfc_key);
}
static int
eng_gl_rotation_angle_get(void *data EINA_UNUSED)
{
return 0;
}
//------------------------------------------------//
/* The following function require that any engine
@ -2989,6 +3072,7 @@ static Evas_Func func =
eng_font_text_props_info_create,
eng_font_right_inset_get,
NULL, // need software mesa for gl rendering <- gl_surface_create
NULL, // need software mesa for gl rendering <- gl_pbuffer_surface_create
NULL, // need software mesa for gl rendering <- gl_surface_destroy
NULL, // need software mesa for gl rendering <- gl_context_create
NULL, // need software mesa for gl rendering <- gl_context_destroy
@ -3002,6 +3086,11 @@ static Evas_Func func =
NULL, // need software mesa for gl rendering <- gl_surface_lock
NULL, // need software mesa for gl rendering <- gl_surface_read_pixels
NULL, // need software mesa for gl rendering <- gl_surface_unlock
NULL, // need software mesa for gl rendering <- gl_error_get
NULL, // need software mesa for gl rendering <- gl_current_context_get
NULL, // need software mesa for gl rendering <- gl_current_surface_get
NULL, // need software mesa for gl rendering <- gl_rotation_angle_get
NULL, // need software mesa for gl rendering <- gl_surface_query
eng_image_load_error_get,
eng_font_run_font_end_get,
eng_image_animated_get,
@ -3971,6 +4060,9 @@ static int
gl_lib_init(void)
{
#ifdef EVAS_GL
// Current ctx & sfc stuff
if (!_tls_check()) return 0;
// dlopen OSMesa
gl_lib_handle = dlopen("libOSMesa.so.9", RTLD_NOW);
if (!gl_lib_handle) gl_lib_handle = dlopen("libOSMesa.so.8", RTLD_NOW);
@ -4020,6 +4112,10 @@ init_gl(void)
ORD(gl_proc_address_get); // FIXME: Need to implement
ORD(gl_native_surface_get);
ORD(gl_api_get);
ORD(gl_error_get);
ORD(gl_current_context_get);
ORD(gl_current_surface_get);
ORD(gl_rotation_angle_get);
#undef ORD
}
}

View File

@ -76,7 +76,6 @@ void (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL;
unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL;
/* local variables */
static int safe_native = -1;
static Eina_Bool initted = EINA_FALSE;
static int gl_wins = 0;
static Evas_Func func, pfunc;
@ -324,7 +323,7 @@ evgl_eng_window_surface_destroy(void *data, void *surface)
}
static void *
evgl_eng_context_create(void *data, void *ctxt)
evgl_eng_context_create(void *data, void *ctxt, int version)
{
Render_Engine *re;
Outbuf *ob;
@ -334,6 +333,12 @@ evgl_eng_context_create(void *data, void *ctxt)
if (!(re = (Render_Engine *)data)) return NULL;
if (!(ob = eng_get_ob(re))) return NULL;
if (version != EVAS_GL_GLES_2_X)
{
ERR("This engine only supports OpenGL-ES 2.0 contexts for now!");
return NULL;
}
attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
attrs[1] = 2;
attrs[2] = EGL_NONE;
@ -466,7 +471,11 @@ static const EVGL_Interface evgl_funcs =
evgl_eng_make_current,
evgl_eng_proc_address_get,
evgl_eng_string_get,
evgl_eng_rotation_angle_get
evgl_eng_rotation_angle_get,
NULL, // PBuffer
NULL, // PBuffer
NULL, // OpenGL-ES 1
NULL, // OpenGL-ES 1
};
/* engine functions */
@ -565,23 +574,6 @@ eng_setup(Evas *evas, void *info)
}
}
if (safe_native == -1)
{
s = getenv("EVAS_GL_SAFE_NATIVE");
safe_native = 0;
if (s) safe_native = atoi(s);
else
{
s = (const char *)glGetString(GL_RENDERER);
if (s)
{
if (strstr(s, "PowerVR SGX 540") ||
strstr(s, "Mali-400 MP"))
safe_native = 1;
}
}
}
if (!(re = epd->engine.data.output))
{
Render_Engine_Merge_Mode merge = MERGE_BOUNDING;