Evas GL: Fix support for GLES 1.1 indirect rendering

This requires a special context that matches the configuration
required for GLES 1.1. Otherwise eglMakeCurrent() would fail
miserably with EGL_BAD_MATCH in case of indirect rendering
(at least on some drivers).
This commit is contained in:
Jean-Philippe Andre 2015-02-24 20:54:55 +09:00
parent 9a0f591314
commit ae2061dbe2
3 changed files with 103 additions and 9 deletions

View File

@ -2074,6 +2074,14 @@ evgl_context_destroy(void *eng_data, EVGL_Context *ctx)
return 0;
}
// Destroy GLES1 indirect rendering context
if (ctx->gles1_context &&
!evgl_engine->funcs->context_destroy(eng_data, ctx->context))
{
ERR("Error destroying the GLES1 context.");
return 0;
}
// Destroy engine context
if (!evgl_engine->funcs->context_destroy(eng_data, ctx->context))
{
@ -2226,22 +2234,59 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
if (dbg) DBG("ctx %p is GLES 1", ctx);
if (_evgl_direct_renderable(rsc, sfc))
{
// Transition from pixmap surface rendering to direct rendering
/*
* TODO:
if (!rsc->direct.rendered)
{
// Restore viewport and scissor test to direct rendering mode
glViewport(ctx->viewport_direct[0], ctx->viewport_direct[1], ctx->viewport_direct[2], ctx->viewport_direct[3]);
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
glEnable(GL_SCISSOR_TEST);
}
*/
if (dbg) DBG("sfc %p is direct renderable.", sfc);
rsc->direct.rendered = 1;
}
else
{
if (!ctx->gles1_context)
{
ctx->gles1_context =
evgl_engine->funcs->gles1_context_create(eng_data, ctx, sfc);
}
if (dbg) DBG("Calling make_current(%p, %p)", sfc->gles1_sfc, ctx->context);
evgl_engine->funcs->make_current(eng_data, sfc->gles1_sfc,
ctx->context, EINA_TRUE);
if (!evgl_engine->funcs->make_current(eng_data, sfc->gles1_sfc,
ctx->gles1_context, EINA_TRUE))
{
ERR("Failed to make current with GLES1 indirect surface.");
return 0;
}
// Transition from direct rendering to pixmap surface rendering
if (rsc->direct.rendered)
{
glViewport(ctx->viewport_coord[0], ctx->viewport_coord[1], ctx->viewport_coord[2], ctx->viewport_coord[3]);
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
glDisable(GL_SCISSOR_TEST);
}
ctx->current_fbo = 0;
rsc->direct.rendered = 0;
}
ctx->current_sfc = sfc;
rsc->current_ctx = ctx;
rsc->current_eng = eng_data;
// Update extensions after GLESv1 context is bound
evgl_api_gles1_ext_get(gles1_funcs);
return 1;
}
// GLES 2+ below
// Normal FBO Rendering
// Create FBO if it hasn't been created
if (!ctx->surface_fbo)
@ -2343,12 +2388,6 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
rsc->current_ctx = ctx;
rsc->current_eng = eng_data;
// Update GLESv1 extension functions after GLESv1 context is bound
if (ctx->version == EVAS_GL_GLES_1_X)
{
evgl_api_gles1_ext_get(gles1_funcs);
}
_surface_context_list_print();
return 1;

View File

@ -74,6 +74,9 @@ struct _EVGL_Interface
// Destroy 1.x surface (could be pbuffer or xpixmap for instance)
int (*gles1_surface_destroy)(void *data, EVGL_Surface *evgl_sfc);
// Create an indirect rendering context for GLES 1.x
void *(*gles1_context_create)(void *data, EVGL_Context *share_ctx, EVGL_Surface *evgl_sfc);
};
struct _EVGL_Surface
@ -131,6 +134,7 @@ struct _EVGL_Surface
EVGLNative_Surface gles1_sfc;
void *gles1_sfc_native;
void *gles1_sfc_visual;
void *gles1_sfc_config;
//-------------------------//
// Related to PBuffer Surface
@ -169,6 +173,9 @@ struct _EVGL_Context
int scissor_coord[4];
int viewport_coord[4];
// For GLES1 with indirect rendering
EVGLNative_Context gles1_context;
// Partial Rendering
int partial_render;

View File

@ -980,7 +980,7 @@ try_again:
config_attrs[i++] = EGL_NONE;
config_attrs[i++] = 0;
if (!eglChooseConfig(eng_get_ob(re)->egl_disp, config_attrs, configs, 200, &num))
if (!eglChooseConfig(eng_get_ob(re)->egl_disp, config_attrs, configs, 200, &num) || !num)
{
int err = eglGetError();
ERR("eglChooseConfig() can't find any configs, error: %x", err);
@ -1075,6 +1075,8 @@ try_again:
evgl_sfc->gles1_sfc = egl_sfc;
evgl_sfc->gles1_sfc_native = (void *)(intptr_t) px;
evgl_sfc->gles1_sfc_visual = visual;
evgl_sfc->gles1_sfc_config = egl_cfg;
DBG("Successfully created GLES1 surface: Pixmap %lu EGLSurface %p", px, egl_sfc);
return evgl_sfc;
#else
@ -1127,6 +1129,51 @@ evgl_eng_gles1_surface_destroy(void *data, EVGL_Surface *evgl_sfc)
return 1;
}
static void *
evgl_eng_gles1_context_create(void *data,
EVGL_Context *share_ctx, EVGL_Surface *sfc)
{
Render_Engine *re = data;
if (!re) return NULL;
#ifdef GL_GLES
EGLContext context = EGL_NO_CONTEXT;
int context_attrs[3];
EGLConfig config;
context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
context_attrs[1] = 1;
context_attrs[2] = EGL_NONE;
if (!sfc || !sfc->gles1_sfc_config)
{
ERR("Surface is not set! Creating context anyways but eglMakeCurrent "
"might very well fail with EGL_BAD_MATCH (0x3009)");
config = eng_get_ob(re)->egl_config;
}
else config = sfc->gles1_sfc_config;
context = eglCreateContext(eng_get_ob(re)->egl_disp, config,
share_ctx ? share_ctx->context : NULL,
context_attrs);
if (!context)
{
int err = eglGetError();
ERR("eglCreateContext failed with error 0x%x", err);
glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
return NULL;
}
DBG("Successfully created context for GLES1 indirect rendering.");
return context;
#else
CRI("Support for GLES1 indirect rendering contexts is not implemented for GLX");
(void) share_ctx; (void) sfc;
return NULL;
#endif
}
static const EVGL_Interface evgl_funcs =
{
evgl_eng_display_get,
@ -1145,6 +1192,7 @@ static const EVGL_Interface evgl_funcs =
evgl_eng_pbuffer_surface_destroy,
evgl_eng_gles1_surface_create,
evgl_eng_gles1_surface_destroy,
evgl_eng_gles1_context_create,
};
//----------------------------------------------------------//