forked from enlightenment/efl
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:
parent
0f2dba299d
commit
9afd5b3f3f
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue