From 9afd5b3f3fdf678c26898b33d03258c3f0f4e023 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Fri, 20 Jan 2012 12:29:14 +0000 Subject: [PATCH] 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 --- legacy/evas/ChangeLog | 15 +- legacy/evas/NEWS | 3 + .../evas/src/lib/canvas/evas_object_image.c | 32 +- legacy/evas/src/lib/include/evas_private.h | 1 + .../src/modules/engines/gl_x11/evas_engine.c | 549 +++++++++++++++--- .../engines/software_generic/evas_engine.c | 1 + 6 files changed, 523 insertions(+), 78 deletions(-) diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index efae30869b..0242cc5d9e 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -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. + diff --git a/legacy/evas/NEWS b/legacy/evas/NEWS index 68df381eae..1dd6ad60ca 100644 --- a/legacy/evas/NEWS +++ b/legacy/evas/NEWS @@ -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: diff --git a/legacy/evas/src/lib/canvas/evas_object_image.c b/legacy/evas/src/lib/canvas/evas_object_image.c index d9f6378897..2553ec4624 100644 --- a/legacy/evas/src/lib/canvas/evas_object_image.c +++ b/legacy/evas/src/lib/canvas/evas_object_image.c @@ -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; + } + } } } diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 84c1d361f9..2e9eb79cb6 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -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); diff --git a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c index fbbd1a26e6..736858b822 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -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); diff --git a/legacy/evas/src/modules/engines/software_generic/evas_engine.c b/legacy/evas/src/modules/engines/software_generic/evas_engine.c index b7b98886fe..817b87dff6 100644 --- a/legacy/evas/src/modules/engines/software_generic/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_generic/evas_engine.c @@ -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,