Added Direct Rendering to Evas' window instead of an FBO in Evas_GL.

This optimization is significant for rendering to a large surface 
because it'l save an extra copy overhead as well as an extra rendering pass.

To enable it, you can give EVAS_GL_OPTIONS_DIRECT hint in the surface
config options_bits. The following conditions have to be met in order
for evas to render directly into the Evas' window. If they are not met, the 
engine will fallback to rendering to an FBO as it normally does. 

conditions: 
1.) All the GL calls have to be called using the pixel_get_callback function.
This is necessary for the evas object order to be maintained.
2.) Alpha must be disabled on the image ojbect that renders evas_gl.
3.) No rotation allowed.

One way to override above condition is to set EVAS_GL_DIRECT_OVERRIDE=1 but 
there is no guarantee in its behavior.

Currently, this optimization is added for gl_x11 engine only. 




SVN revision: 67388
This commit is contained in:
Sung Park 2012-01-20 12:29:14 +00:00
parent 0f2dba299d
commit 9afd5b3f3f
6 changed files with 523 additions and 78 deletions

View File

@ -638,7 +638,7 @@
* Add evas_object_smart_callback_del_full() to allow users to
unregister a specific smart event callback instead of all
callbacks matching a given type and function pointer.
2012-01-17 Carsten Haitzler (The Rasterman)
* Add EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN pointer mode
@ -647,3 +647,16 @@
2012-01-19 Cedric Bail
* Add double buffer support to buffer engine.
2012-01-20 Sung W. Park (sung_)
* Add Direct Rendering to Evas' window optimization for Evas_GL. This
optimization can be significant since it avoids and extra copy from
an offscreen buffer. Normally, Evas_GL will render to a render
target using an FBO. This can be enabled by giving
EVAS_GL_OPTIONS_DIRECT hint in the config options_bits. Direct
rendering is actually done if the following conditions are met -
1) All GL rendering is done in the pixel_getter callback 2) No
rotation on the image object 3) Corresponding image
object has alpha disabled.

View File

@ -66,6 +66,9 @@ Additions:
* underline dashing suport to textblock
* API to get largest image size
* GL Cocoa engine
* Evas GL support in software backend through OSMesa
* API to new/free Evas_GL_Config rather than user declaring it
* Evas GL Direct rendering option hint to allow rendering to evas' window when possible
Fixes:

View File

@ -2908,11 +2908,31 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
{
Evas_Coord idw, idh, idx, idy;
int ix, iy, iw, ih;
int img_set = 0;
if (o->dirty_pixels)
{
if (o->func.get_pixels)
{
// Set img object for direct rendering optimization
// Check for image w/h against image geometry w/h
// Check for image color r,g,b,a = {255,255,255,255}
// Check and make sure that there are no maps.
if ( (obj->cur.geometry.w == o->cur.image.w) &&
(obj->cur.geometry.h == o->cur.image.h) &&
(obj->cur.color.r == 255) &&
(obj->cur.color.g == 255) &&
(obj->cur.color.b == 255) &&
(obj->cur.color.a == 255) &&
(!obj->cur.map) )
{
if (obj->layer->evas->engine.func->gl_img_obj_set)
{
obj->layer->evas->engine.func->gl_img_obj_set(output, obj, o->cur.has_alpha);
img_set = 1;
}
}
o->func.get_pixels(o->func.get_pixels_data, obj);
if (o->engine_data != pixels)
pixels = o->engine_data;
@ -3152,7 +3172,17 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
idy = ydy;
if (dobreak_w) break;
}
}
}
// Unset img object
if (img_set)
{
if (obj->layer->evas->engine.func->gl_img_obj_set)
{
obj->layer->evas->engine.func->gl_img_obj_set(output, NULL, 0);
img_set = 0;
}
}
}
}

View File

@ -850,6 +850,7 @@ struct _Evas_Func
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_img_obj_set) (void *data, void *image, int has_alpha);
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

@ -41,6 +41,17 @@ struct _Render_Engine
int w, h;
int vsync;
// Shader used for Evas_GL_Direct Optimization
GLuint df_program;
GLuint df_vtx_shader;
GLuint df_fgmt_shader;
GLuint df_col_attrib;
GLuint df_pos_attrib;
GLfloat df_clear_color[4];
GLfloat df_depth_value;
int df_initialized;
};
struct _Render_Engine_GL_Surface
@ -51,6 +62,8 @@ struct _Render_Engine_GL_Surface
int depth_bits;
int stencil_bits;
int direct_fb_opt;
// Render target texture/buffers
GLuint rt_tex;
GLint rt_internal_fmt;
@ -60,6 +73,12 @@ struct _Render_Engine_GL_Surface
GLuint rb_stencil;
GLenum rb_stencil_fmt;
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
EGLSurface direct_sfc;
#else
Window direct_sfc;
#endif
Render_Engine_GL_Context *current_ctx;
};
@ -74,6 +93,10 @@ struct _Render_Engine_GL_Context
GLuint context_fbo;
GLuint current_fbo;
int scissor_enabled;
int scissor_upated;
Render_Engine_GL_Surface *current_sfc;
};
@ -99,8 +122,11 @@ struct _Extension_Entry
static int initted = 0;
static int gl_wins = 0;
static Render_Engine_GL_Context *current_evgl_ctx;
static Render_Engine *current_engine;
static int gl_direct_override = 0;
static int gl_direct_enabled = 0;
static Render_Engine_GL_Context *current_evgl_ctx = NULL;
static Render_Engine *current_engine = NULL;
static Evas_Object *gl_direct_img_obj = NULL;
static char _gl_ext_string[1024];
static char _evasgl_ext_string[1024];
@ -2605,13 +2631,22 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
re = (Render_Engine *)data;
if (!image) return;
eng_window_use(re->win);
evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
re->win->gl_context->dc = context;
evas_gl_common_image_draw(re->win->gl_context, image,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h,
smooth);
if ((gl_direct_img_obj) && (gl_direct_enabled))
{
DBG("Rendering Directly to the window");
evas_object_image_pixels_dirty_set(gl_direct_img_obj, EINA_TRUE);
}
else
{
eng_window_use(re->win);
evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
re->win->gl_context->dc = context;
evas_gl_common_image_draw(re->win->gl_context, image,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h,
smooth);
}
}
static void
@ -2794,7 +2829,7 @@ static int
_set_internal_config(Render_Engine_GL_Surface *sfc, Evas_GL_Config *cfg)
{
// Also initialize pixel format here as well...
switch(cfg->color_format)
switch((int)cfg->color_format)
{
case EVAS_GL_RGB_888:
sfc->rt_fmt = GL_RGB;
@ -2849,7 +2884,12 @@ _set_internal_config(Render_Engine_GL_Surface *sfc, Evas_GL_Config *cfg)
return 0;
}
// Do Packed Depth24_Stencil8 Later...
if (cfg->options_bits)
{
if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT)
sfc->direct_fb_opt = 1;
// Add other options here...
}
return 1;
}
@ -2954,6 +2994,11 @@ eng_gl_surface_create(void *data, void *config, int w, int h)
sfc->rb_depth = 0;
sfc->rb_stencil = 0;
/* Allow alpha for evas gl direct rendering */
// FIXME!!!: A little out of place for for now...
if (!gl_direct_override)
if (getenv("EVAS_GL_DIRECT_OVERRIDE")) gl_direct_override = 1;
// Set the internal format based on the config
if (!_set_internal_config(sfc, cfg))
{
@ -2962,6 +3007,16 @@ eng_gl_surface_create(void *data, void *config, int w, int h)
return NULL;
}
if (sfc->direct_fb_opt)
{
DBG("Enabling Direct rendering to the Evas' window.");
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
sfc->direct_sfc = re->win->egl_surface[0];
#else
sfc->direct_sfc = re->win->win;
#endif
}
// Create internal resource context if it hasn't been created already
if ((rsc = eina_tls_get(resource_key)) == NULL)
{
@ -3039,6 +3094,17 @@ eng_gl_surface_destroy(void *data, void *surface)
return 0;
}
// Reset the Framebuffer binding point
if ((current_evgl_ctx) && (current_evgl_ctx->current_fbo == current_evgl_ctx->context_fbo))
{
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
current_evgl_ctx->current_fbo = 0;
current_evgl_ctx->current_sfc = NULL;
}
// Clear direct rendering flag
gl_direct_enabled = 0;
// Delete FBO/RBO and Texture here
if (sfc->rt_tex)
glDeleteTextures(1, &sfc->rt_tex);
@ -3049,6 +3115,8 @@ eng_gl_surface_destroy(void *data, void *surface)
if (sfc->rb_stencil)
glDeleteRenderbuffers(1, &sfc->rb_stencil);
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
ret = eglMakeCurrent(re->win->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
#else
@ -3158,7 +3226,7 @@ eng_gl_context_destroy(void *data, void *context)
if ((rsc = eina_tls_get(resource_key)) == EINA_FALSE) return 0;
// 1. Do a make current with the given context
// Do a make current with the given context
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
ret = eglMakeCurrent(re->win->egl_disp, rsc->surface,
rsc->surface, ctx->context);
@ -3172,11 +3240,11 @@ eng_gl_context_destroy(void *data, void *context)
return 0;
}
// 2. Delete the FBO
// Delete the FBO
if (ctx->context_fbo)
glDeleteFramebuffers(1, &ctx->context_fbo);
// 3. Destroy the Context
// Destroy the Context
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
eglDestroyContext(re->win->egl_disp, ctx->context);
@ -3218,6 +3286,16 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context)
sfc = (Render_Engine_GL_Surface*)surface;
ctx = (Render_Engine_GL_Context*)context;
// Check if direct rendering is possible:
// It's possible when direct_fb_opt is on and either current image
// object is valid or gl_direct_override is on. Override allows
// rendering outside of pixel getter but it doesn't guarantee
// correct rendering.
if ((sfc->direct_fb_opt) && (gl_direct_img_obj || gl_direct_override))
gl_direct_enabled = 1;
else
gl_direct_enabled = 0;
// Unset surface/context
if ((!sfc) || (!ctx))
{
@ -3239,67 +3317,117 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context)
return 1;
}
// Do a make current only if it's not already current
if (gl_direct_enabled)
{
// Do a make current only if it's not already current
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
if ((rsc = eina_tls_get(resource_key)) == EINA_FALSE) return 0;
if ((eglGetCurrentContext() != ctx->context) ||
(eglGetCurrentSurface(EGL_READ) != rsc->surface) ||
(eglGetCurrentSurface(EGL_DRAW) != rsc->surface) )
{
// Flush remainder of what's in Evas' pipeline
if (re->win) eng_window_use(NULL);
// Do a make current
ret = eglMakeCurrent(re->win->egl_disp, rsc->surface,
rsc->surface, ctx->context);
if (!ret)
if ((eglGetCurrentContext() != ctx->context) ||
(eglGetCurrentSurface(EGL_READ) != sfc->direct_sfc) ||
(eglGetCurrentSurface(EGL_DRAW) != sfc->direct_sfc) )
{
ERR("xxxMakeCurrent() failed!");
return 0;
int curr_fbo = 0;
DBG("Rendering Directly to the window\n");
// Flush remainder of what's in Evas' pipeline
if (re->win) eng_window_use(NULL);
// Do a make current
ret = eglMakeCurrent(re->win->egl_disp, sfc->direct_sfc,
sfc->direct_sfc, ctx->context);
if (!ret)
{
ERR("xxxMakeCurrent() failed! code=%#x", eglGetError());
//ERR("xxxMakeCurrent() failed!");
return 0;
}
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo);
if (ctx->context_fbo == curr_fbo)
{
ctx->current_fbo = 0;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
}
#else
if ((glXGetCurrentContext() != ctx->context) ||
(glXGetCurrentDrawable() != re->win->win) )
{
// Flush remainder of what's in Evas' pipeline
if (re->win) eng_window_use(NULL);
// Do a make current
ret = glXMakeCurrent(re->info->info.display, re->win->win, ctx->context);
if (!ret)
if ((glXGetCurrentContext() != ctx->context))
{
ERR("xxxMakeCurrent() failed!");
return 0;
// Flush remainder of what's in Evas' pipeline
if (re->win) eng_window_use(NULL);
// Do a make current
ret = glXMakeCurrent(re->info->info.display, sfc->direct_sfc, ctx->context);
if (!ret)
{
ERR("xxxMakeCurrent() failed!");
return 0;
}
}
#endif
}
else
{
// Do a make current only if it's not already current
#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
if ((rsc = eina_tls_get(resource_key)) == EINA_FALSE) return 0;
if ((eglGetCurrentContext() != ctx->context) ||
(eglGetCurrentSurface(EGL_READ) != rsc->surface) ||
(eglGetCurrentSurface(EGL_DRAW) != rsc->surface) )
{
// Flush remainder of what's in Evas' pipeline
if (re->win) eng_window_use(NULL);
// Do a make current
ret = eglMakeCurrent(re->win->egl_disp, rsc->surface,
rsc->surface, ctx->context);
if (!ret)
{
ERR("xxxMakeCurrent() failed!");
return 0;
}
}
#else
if ((glXGetCurrentContext() != ctx->context) ||
(glXGetCurrentDrawable() != re->win->win) )
{
// Flush remainder of what's in Evas' pipeline
if (re->win) eng_window_use(NULL);
// Do a make current
ret = glXMakeCurrent(re->info->info.display, re->win->win, ctx->context);
if (!ret)
{
ERR("xxxMakeCurrent() failed!");
return 0;
}
}
#endif
// Create FBO if not already created
if (!ctx->initialized)
{
glGenFramebuffers(1, &ctx->context_fbo);
ctx->initialized = 1;
}
// Attach FBO if it hasn't been attached or if surface changed
if ((!sfc->fbo_attached) || (ctx->current_sfc != sfc))
{
if (!_attach_fbo_surface(re, sfc, ctx))
// Create FBO if not already created
if (!ctx->initialized)
{
ERR("_attach_fbo_surface() failed.");
return 0;
glGenFramebuffers(1, &ctx->context_fbo);
ctx->initialized = 1;
}
if (ctx->current_fbo)
// Bind to the previously bound buffer
glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
else
// Bind FBO
glBindFramebuffer(GL_FRAMEBUFFER, ctx->context_fbo);
// Attach FBO if it hasn't been attached or if surface changed
if ((!sfc->fbo_attached) || (ctx->current_sfc != sfc))
{
if (!_attach_fbo_surface(re, sfc, ctx))
{
ERR("_attach_fbo_surface() failed.");
return 0;
}
sfc->fbo_attached = 1;
if (ctx->current_fbo)
// Bind to the previously bound buffer
glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo);
else
// Bind FBO
glBindFramebuffer(GL_FRAMEBUFFER, ctx->context_fbo);
sfc->fbo_attached = 1;
}
}
// Set the current surface/context
@ -3345,13 +3473,28 @@ eng_gl_native_surface_get(void *data, void *surface, void *native_surface)
sfc = (Render_Engine_GL_Surface*)surface;
ns = (Evas_Native_Surface*)native_surface;
ns->type = EVAS_NATIVE_SURFACE_OPENGL;
ns->version = EVAS_NATIVE_SURFACE_VERSION;
ns->data.opengl.texture_id = sfc->rt_tex;
ns->data.opengl.x = 0;
ns->data.opengl.y = 0;
ns->data.opengl.w = sfc->w;
ns->data.opengl.h = sfc->h;
if (sfc->direct_fb_opt)
{
ns->type = EVAS_NATIVE_SURFACE_OPENGL;
ns->version = EVAS_NATIVE_SURFACE_VERSION;
ns->data.opengl.texture_id = sfc->rt_tex;
ns->data.opengl.framebuffer_id = 0;
ns->data.opengl.x = 0;
ns->data.opengl.y = 0;
ns->data.opengl.w = sfc->w;
ns->data.opengl.h = sfc->h;
}
else
{
ns->type = EVAS_NATIVE_SURFACE_OPENGL;
ns->version = EVAS_NATIVE_SURFACE_VERSION;
ns->data.opengl.texture_id = sfc->rt_tex;
ns->data.opengl.framebuffer_id = sfc->rt_tex;
ns->data.opengl.x = 0;
ns->data.opengl.y = 0;
ns->data.opengl.w = sfc->w;
ns->data.opengl.h = sfc->h;
}
return 1;
}
@ -3374,7 +3517,9 @@ evgl_glBindFramebuffer(GLenum target, GLuint framebuffer)
// Take care of BindFramebuffer 0 issue
if (framebuffer==0)
{
if (ctx)
if (gl_direct_enabled)
glBindFramebuffer(target, 0);
else if (ctx)
{
glBindFramebuffer(target, ctx->context_fbo);
ctx->current_fbo = 0;
@ -3398,6 +3543,228 @@ evgl_glBindRenderbuffer(GLenum target, GLuint renderbuffer)
glBindRenderbuffer(target, renderbuffer);
}
// Transform from Evas Coordinat to GL Coordinate
// returns: oc[4] original image object dimension in gl coord
// returns: nc[4] tranformed (x, y, width, heigth) in gl coord
static void
compute_gl_coordinates(Evas_Object *obj, int rot, int clip,
int x, int y, int width, int height,
int imgc[4], int objc[4])
{
int nx1, ny1, nx2, ny2;
int ox1, oy1, ox2, oy2;
if (rot == 0)
{
// oringinal image object coordinate in gl coordinate
imgc[0] = obj->cur.geometry.x;
imgc[1] = obj->layer->evas->output.h - obj->cur.geometry.y - obj->cur.geometry.h;
imgc[2] = imgc[0] + obj->cur.geometry.w;
imgc[3] = imgc[1] + obj->cur.geometry.h;
// transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + x;
objc[1] = imgc[1] + y;
objc[2] = objc[0] + width;
objc[3] = objc[1] + height;
}
else if (rot == 180)
{
// oringinal image object coordinate in gl coordinate
imgc[0] = obj->layer->evas->output.w - obj->cur.geometry.x - obj->cur.geometry.w;
imgc[1] = obj->cur.geometry.y;
imgc[2] = imgc[0] + obj->cur.geometry.w;
imgc[3] = imgc[1] + obj->cur.geometry.h;
// transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + obj->cur.geometry.w - x - width;
objc[1] = imgc[1] + obj->cur.geometry.h - y - height;
objc[2] = objc[0] + width;
objc[3] = objc[1] + height;
}
else if (rot == 90)
{
// oringinal image object coordinate in gl coordinate
imgc[0] = obj->cur.geometry.y;
imgc[1] = obj->cur.geometry.x;
imgc[2] = imgc[0] + obj->cur.geometry.h;
imgc[3] = imgc[1] + obj->cur.geometry.w;
// transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + obj->cur.geometry.h - y - height;
objc[1] = imgc[1] + x;
objc[2] = objc[0] + height;
objc[3] = objc[1] + width;
}
else if (rot == 270)
{
// oringinal image object coordinate in gl coordinate
imgc[0] = obj->layer->evas->output.h - obj->cur.geometry.y - obj->cur.geometry.h;
imgc[1] = obj->layer->evas->output.w - obj->cur.geometry.x - obj->cur.geometry.w;
imgc[2] = imgc[0] + obj->cur.geometry.h;
imgc[3] = imgc[1] + obj->cur.geometry.w;
// transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + y;
objc[1] = imgc[1] + obj->cur.geometry.w - x - width;
objc[2] = objc[0] + height;
objc[3] = objc[1] + width;
}
else
{
ERR("Invalid rotation angle %d.", rot);
return;
}
if (clip)
{
// Clip against original image object
if (objc[0] < imgc[0]) objc[0] = imgc[0];
if (objc[0] > imgc[2]) objc[0] = 0;
if (objc[1] < imgc[1]) objc[1] = imgc[1];
if (objc[1] > imgc[3]) objc[1] = 0;
if (objc[2] < imgc[0]) objc[0] = 0;
if (objc[2] > imgc[2]) objc[2] = imgc[2];
if (objc[3] < imgc[1]) objc[1] = 0;
if (objc[3] > imgc[3]) objc[3] = imgc[3];
}
imgc[2] = imgc[2]-imgc[0]; // width
imgc[3] = imgc[3]-imgc[1]; // height
objc[2] = objc[2]-objc[0]; // width
objc[3] = objc[3]-objc[1]; // height
}
static void
evgl_glClear(GLbitfield mask)
{
Render_Engine_GL_Context *ctx = current_evgl_ctx;
int rot = 0;
int oc[4], nc[4];
if ((gl_direct_img_obj) && (gl_direct_enabled) && (ctx) && (!ctx->current_fbo))
{
if ((current_engine) && (current_engine->win) && (current_engine->win->gl_context))
rot = current_engine->win->gl_context->rot;
else
ERR("Unable to retrieve rotation angle: %d", rot);
compute_gl_coordinates(gl_direct_img_obj, rot, 0, 0, 0, 0, 0, oc, nc);
glScissor(oc[0], oc[1], oc[2], oc[3]);
glClear(mask);
}
else
glClear(mask);
}
static void
evgl_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
current_engine->df_clear_color[0] = red;
current_engine->df_clear_color[1] = green;
current_engine->df_clear_color[2] = blue;
current_engine->df_clear_color[3] = alpha;
glClearColor(red, green, blue, alpha);
}
static void
evgl_glEnable(GLenum cap)
{
Render_Engine_GL_Context *ctx = current_evgl_ctx;
if (cap == GL_SCISSOR_TEST)
if (ctx) ctx->scissor_enabled = 1;
glEnable(cap);
}
static void
evgl_glDisable(GLenum cap)
{
Render_Engine_GL_Context *ctx = current_evgl_ctx;
if (cap == GL_SCISSOR_TEST)
if (ctx) ctx->scissor_enabled = 0;
glDisable(cap);
}
static void
evgl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
{
Render_Engine_GL_Context *ctx = current_evgl_ctx;
int rot = 0;
int oc[4], nc[4];
if ((gl_direct_img_obj) && (gl_direct_enabled) && (ctx) && (!ctx->current_fbo))
{
if ((current_engine) && (current_engine->win) && (current_engine->win->gl_context))
rot = current_engine->win->gl_context->rot;
else
ERR("Unable to retrieve rotation angle: %d", rot);
compute_gl_coordinates(gl_direct_img_obj, rot, 1, x, y, width, height, oc, nc);
glReadPixels(nc[0], nc[1], nc[2], nc[3], format, type, pixels);
}
else
glReadPixels(x, y, width, height, format, type, pixels);
}
static void
evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
Render_Engine_GL_Context *ctx = current_evgl_ctx;
int rot = 0;
int oc[4], nc[4];
if ((gl_direct_img_obj) && (gl_direct_enabled) && (ctx) && (!ctx->current_fbo))
{
if ((current_engine) && (current_engine->win) && (current_engine->win->gl_context))
rot = current_engine->win->gl_context->rot;
else
ERR("Unable to retrieve rotation angle: %d", rot);
compute_gl_coordinates(gl_direct_img_obj, rot, 1, x, y, width, height, oc, nc);
glScissor(nc[0], nc[1], nc[2], nc[3]);
ctx->scissor_upated = 1;
}
else
glScissor(x, y, width, height);
}
static void
evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
Render_Engine_GL_Context *ctx = current_evgl_ctx;
int rot = 0;
int oc[4], nc[4];
if ((gl_direct_img_obj) && (gl_direct_enabled) && (ctx) && (!ctx->current_fbo))
{
if ((current_engine) && (current_engine->win) && (current_engine->win->gl_context))
rot = current_engine->win->gl_context->rot;
else
ERR("Unable to retrieve rotation angle: %d", rot);
compute_gl_coordinates(gl_direct_img_obj, rot, 0, x, y, width, height, oc, nc);
glEnable(GL_SCISSOR_TEST);
glScissor(oc[0], oc[1], oc[2], oc[3]);
glViewport(nc[0], nc[1], nc[2], nc[3]);
}
else
glViewport(x, y, width, height);
}
//----------------------------------------------//
static void
evgl_glClearDepthf(GLclampf depth)
{
@ -3531,8 +3898,8 @@ eng_gl_api_get(void *data)
ORD(glBufferData);
ORD(glBufferSubData);
ORD(glCheckFramebufferStatus);
ORD(glClear);
ORD(glClearColor);
// ORD(glClear);
// ORD(glClearColor);
// ORD(glClearDepthf);
ORD(glClearStencil);
ORD(glColorMask);
@ -3554,11 +3921,11 @@ eng_gl_api_get(void *data)
ORD(glDepthMask);
// ORD(glDepthRangef);
ORD(glDetachShader);
ORD(glDisable);
// ORD(glDisable);
ORD(glDisableVertexAttribArray);
ORD(glDrawArrays);
ORD(glDrawElements);
ORD(glEnable);
// ORD(glEnable);
ORD(glEnableVertexAttribArray);
ORD(glFinish);
ORD(glFlush);
@ -3612,7 +3979,7 @@ eng_gl_api_get(void *data)
// ORD(glReleaseShaderCompiler);
ORD(glRenderbufferStorage);
ORD(glSampleCoverage);
ORD(glScissor);
// ORD(glScissor);
// ORD(glShaderBinary);
ORD(glShaderSource);
ORD(glStencilFunc);
@ -3657,7 +4024,7 @@ eng_gl_api_get(void *data)
ORD(glVertexAttrib4f);
ORD(glVertexAttrib4fv);
ORD(glVertexAttribPointer);
ORD(glViewport);
// ORD(glViewport);
#undef ORD
#define ORD(f) EVAS_API_OVERRIDE(f, &gl_funcs, glsym_)
@ -3717,6 +4084,14 @@ eng_gl_api_get(void *data)
ORD(glBindFramebuffer);
ORD(glBindRenderbuffer);
ORD(glClear);
ORD(glClearColor);
ORD(glEnable);
ORD(glDisable);
ORD(glReadPixels);
ORD(glScissor);
ORD(glViewport);
// GLES2.0 API compat on top of desktop gl
ORD(glClearDepthf);
ORD(glDepthRangef);
@ -3739,6 +4114,24 @@ eng_gl_api_get(void *data)
return &gl_funcs;
}
static void
eng_gl_img_obj_set(void *data, void *image, int has_alpha)
{
Render_Engine *re = (Render_Engine *)data;
gl_direct_img_obj = NULL;
// Normally direct rendering isn't allowed if alpha is on and
// rotation is not 0. BUT, if override is on, allow it.
if ((has_alpha) && (re->win->gl_context->rot!=0))
{
if (gl_direct_override)
gl_direct_img_obj = image;
}
else
gl_direct_img_obj = image;
}
static int
eng_image_load_error_get(void *data __UNUSED__, void *image)
{
@ -3877,6 +4270,9 @@ module_open(Evas_Module *em)
EINA_LOG_ERR("Can not create a module log domain.");
return 0;
}
/* Allow alpha for evas gl direct rendering */
if (getenv("EVAS_GL_DIRECT_OVERRIDE")) gl_direct_override = 1;
/* store it for later use */
func = pfunc;
/* now to override methods */
@ -3961,6 +4357,7 @@ module_open(Evas_Module *em)
ORD(gl_proc_address_get);
ORD(gl_native_surface_get);
ORD(gl_api_get);
ORD(gl_img_obj_set);
ORD(image_load_error_get);

View File

@ -1778,6 +1778,7 @@ static Evas_Func func =
NULL, // need software mesa for gl rendering <- gl_proc_address_get
NULL, // need software mesa for gl rendering <- gl_native_surface_get
NULL, // need software mesa for gl rendering <- gl_api_get
NULL, // need software mesa for gl rendering <- gl_img_obj_set
eng_image_load_error_get,
eng_font_run_font_end_get,
eng_image_animated_get,