Evas GL: Skip glClear() with direct rendering & transparent color

When using direct rendering, glClear() should not do anything
if the ClearColor was (0,0,0,0). The application would indeed
expect a transparent output (so, see the widgets below the view),
but glClear would erase the pixels instead. So add a quick check
to skip glClear entirely in that specific case.
This commit is contained in:
Jean-Philippe Andre 2014-09-01 20:22:12 +09:00
parent cb5e88d20f
commit 49f79f0a73
3 changed files with 63 additions and 4 deletions

View File

@ -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
{
@ -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

@ -1092,10 +1092,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;
// Extra flags for direct rendering
sfc->alpha = (cfg->color_format == EVAS_GL_RGBA_8888);
cfg_index = i;
break;
}

View File

@ -93,8 +93,9 @@ 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 alpha : 1;
int cfg_index;
@ -237,6 +238,9 @@ struct _EVGL_Resource
Eina_Bool enabled : 1;
} direct;
struct {
GLclampf r, g, b, a;
} clear_color;
};