forked from enlightenment/efl
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:
parent
4315537820
commit
47ddb889ad
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------//
|
||||
|
|
Loading…
Reference in New Issue