Evas GL: Add support for OpenGL-ES 1.1 (part 3)

This introduces XPixmap usage for indirect rendering.
Of course this works only for the gl_x11 engine... and for
now only when using EGL... and only on some drivers...
damn limitations.
Direct rendering should work on more platforms (eg. some desktop
nvidia cards with the EGL drivers).
This commit is contained in:
Jean-Philippe Andre 2014-09-23 15:33:16 +09:00
parent 4315537820
commit 47ddb889ad
5 changed files with 186 additions and 3 deletions

View File

@ -1559,6 +1559,19 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
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))
{
@ -1768,6 +1781,25 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
}
}
// 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))
{
@ -1857,6 +1889,9 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
return NULL;
}
ctx->version = version;
// Call engine create context
if (share_ctx)
ctx->context = evgl_engine->funcs->context_create(eng_data, share_ctx->context, version);
else
@ -2027,6 +2062,24 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
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)

View File

@ -67,6 +67,12 @@ struct _EVGL_Interface
// Create a pbuffer surface
void *(*pbuffer_surface_create)(void *data, EVGL_Surface *evgl_sfc, const int *attrib_list);
// 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
@ -101,6 +107,10 @@ struct _EVGL_Surface
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;
// Attached Context
@ -113,6 +123,12 @@ 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 {

View File

@ -118,7 +118,10 @@ 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, // OpenGL-ES 1
NULL, // OpenGL-ES 1
};
/* local functions */

View File

@ -254,7 +254,10 @@ 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, // OpenGL-ES 1
NULL, // OpenGL-ES 1
};

View File

@ -519,6 +519,7 @@ evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version ver
(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,
@ -526,6 +527,7 @@ evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version ver
NULL,
1);
}
*/
else
{
context = glXCreateContext(eng_get_ob(re)->info->info.display,
@ -750,6 +752,110 @@ evgl_eng_pbuffer_surface_create(void *data, EVGL_Surface *sfc,
#endif
}
// 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
#warning GLX support is not implemented for GLES 1.x
CRIT("Not implemented yet! (GLX for GLES 1)");
return NULL;
#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);
#else
#warning GLX support is not implemented for GLES 1.x
CRIT("Not implemented yet! (GLX for GLES 1)");
return 0;
#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,
@ -764,7 +870,9 @@ static const EVGL_Interface evgl_funcs =
evgl_eng_proc_address_get,
evgl_eng_string_get,
evgl_eng_rotation_angle_get,
evgl_eng_pbuffer_surface_create
evgl_eng_pbuffer_surface_create,
evgl_eng_gles1_surface_create,
evgl_eng_gles1_surface_destroy,
};
//----------------------------------------------------------//