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,