From: Park SangHee Date: Thu, 9 Feb 2012 07:25:13 +0000 (+0900) Subject: Applying direct rendering X-Git-Tag: accepted/2.0/20130306.225542~150^2~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=98c02ea473ca61c542307ba629fcf1922e24324b;p=profile%2Fivi%2Fevas.git Applying direct rendering --- diff --git a/src/lib/Evas_GL.h b/src/lib/Evas_GL.h index 39f6ada..b8e28ef 100644 --- a/src/lib/Evas_GL.h +++ b/src/lib/Evas_GL.h @@ -43,11 +43,18 @@ typedef enum _Evas_GL_Stencil_Bits EVAS_GL_STENCIL_BIT_16 = 5, } Evas_GL_Stencil_Bits; +typedef enum _Evas_GL_Options_Bits +{ + EVAS_GL_OPTIONS_NONE = 0, + EVAS_GL_OPTIONS_DIRECT = (1<<0) +} Evas_GL_Options_Bits; + struct _Evas_GL_Config { - Evas_GL_Color_Format color_format; - Evas_GL_Depth_Bits depth_bits; - Evas_GL_Stencil_Bits stencil_bits; + Evas_GL_Color_Format color_format; + Evas_GL_Depth_Bits depth_bits; + Evas_GL_Stencil_Bits stencil_bits; + Evas_GL_Options_Bits options_bits; }; #define EVAS_GL_EXTENSIONS 1 @@ -75,6 +82,7 @@ typedef struct _GLData { Evas_GL_Context *ctx; Evas_GL_Surface *sfc; + Evas_GL_Config *cfg; Evas_GL *evasgl; Evas_GL_API *glapi; GLuint program; @@ -95,13 +103,6 @@ static GLuint load_shader (GLData *gld, GLenum type, const char *shader_src) int main(int argc, char **argv) { - // config for the surface for evas_gl - Evas_GL_Config config = - { - EVAS_GL_RGBA_8888, - EVAS_GL_DEPTH_NONE, - EVAS_GL_STENCIL_NONE - }; // a size by default int w = 256, h = 256; // some variables we will use @@ -126,8 +127,16 @@ main(int argc, char **argv) // get the evas gl handle for doing gl things gld->evasgl = evas_gl_new(canvas); gld->glapi = evas_gl_api_get(gld->evasgl); + + // Set a surface config + gld->cfg = evas_gl_config_new(); + gld->cfg->color_format = EVAS_GL_RGBA_8888; + //gld->cfg->depth_bits = EVAS_GL_DEPTH_NONE; // Othe config options + //gld->cfg->stencil_bits = EVAS_GL_STENCIL_NONE; + //gld->cfg->options_bits = EVAS_GL_OPTIONS_NONE; + // create a surface and context - gld->sfc = evas_gl_surface_create(gld->evasgl, &config, w, h); + gld->sfc = evas_gl_surface_create(gld->evasgl, gld->cfg, w, h); gld->ctx = evas_gl_context_create(gld->evasgl, NULL); //-// //-//-//-// END GL INIT BLOB @@ -209,6 +218,7 @@ on_del(void *data, Evas *e, Evas_Object *obj, void *event_info) evas_gl_surface_destroy(gld->evasgl, gld->sfc); evas_gl_context_destroy(gld->evasgl, gld->ctx); + evas_gl_config_free(gld->cfg); evas_gl_free(gld->evasgl); free(gld); } @@ -391,6 +401,22 @@ EAPI Evas_GL *evas_gl_new (Evas *e) EINA_WARN_UNU EAPI void evas_gl_free (Evas_GL *evas_gl) EINA_ARG_NONNULL(1); /** + * Allocates a new config object for the user to fill out. + * + * As long as the Evas creates a config object for the user, it takes care + * of the backward compatibility issue. + */ +EAPI Evas_GL_Config *evas_gl_config_new (); + +/** + * Frees a config object created from evas_gl_config_new. + * + * As long as the Evas creates a config object for the user, it takes care + * of the backward compatibility issue. + */ +EAPI void evas_gl_config_free (Evas_GL_Config *cfg) EINA_ARG_NONNULL(1); + +/** * Creates and returns new Evas_GL_Surface object for GL Rendering. * * @param evas_gl The given Evas_GL object. diff --git a/src/lib/canvas/evas_gl.c b/src/lib/canvas/evas_gl.c index 08edbc4..85ed851 100644 --- a/src/lib/canvas/evas_gl.c +++ b/src/lib/canvas/evas_gl.c @@ -37,6 +37,13 @@ evas_gl_new(Evas *e) evas_gl->magic = MAGIC_EVAS_GL; evas_gl->evas = e; + if (!evas_gl->evas->engine.func->gl_context_create) + { + ERR("GL engine not available\n"); + free(evas_gl); + return NULL; + } + return evas_gl; } @@ -60,6 +67,24 @@ evas_gl_free(Evas_GL *evas_gl) free(evas_gl); } +EAPI Evas_GL_Config * +evas_gl_config_new() +{ + Evas_GL_Config *cfg; + + cfg = calloc(1, sizeof(Evas_GL_Config)); + + if (!cfg) return NULL; + + return cfg; +} + +EAPI void +evas_gl_config_free(Evas_GL_Config *cfg) +{ + if (cfg) free(cfg); +} + EAPI Evas_GL_Surface * evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int height) { @@ -77,6 +102,8 @@ evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int surf = calloc(1, sizeof(Evas_GL_Surface)); + if (!surf) return NULL; + surf->data = evas_gl->evas->engine.func->gl_surface_create(evas_gl->evas->engine.data.output, config, width, height); if (!surf->data) @@ -135,12 +162,6 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx) return NULL; } - if (!evas_gl->evas->engine.func->gl_context_create) - { - ERR("GL engine not available\n"); - return NULL; - } - // Call engine->gl_create_context if (share_ctx) { diff --git a/src/lib/canvas/evas_object_image.c b/src/lib/canvas/evas_object_image.c index 4f61ea6..818dc5d 100755 --- a/src/lib/canvas/evas_object_image.c +++ b/src/lib/canvas/evas_object_image.c @@ -2918,11 +2918,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; @@ -3162,7 +3182,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/src/lib/include/evas_private.h b/src/lib/include/evas_private.h index ed27ce2..e74c83b 100644 --- a/src/lib/include/evas_private.h +++ b/src/lib/include/evas_private.h @@ -849,6 +849,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/src/modules/engines/gl_x11/evas_engine.c b/src/modules/engines/gl_x11/evas_engine.c index c1bdfee..9c83c21 100644 --- a/src/modules/engines/gl_x11/evas_engine.c +++ b/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]; @@ -2500,13 +2526,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 @@ -2689,7 +2724,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; @@ -2744,7 +2779,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; } @@ -2849,6 +2889,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)) { @@ -2857,6 +2902,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) { @@ -2934,6 +2989,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)) + { + //glsym_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) glsym_glDeleteTextures(1, &sfc->rt_tex); @@ -3136,67 +3202,152 @@ 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 defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) - if ((rsc = eina_tls_get(resource_key)) == EINA_FALSE) return 0; + // 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; - if ((glsym_eglGetCurrentContext() != ctx->context) || - (glsym_eglGetCurrentSurface(EGL_READ) != rsc->surface) || - (glsym_eglGetCurrentSurface(EGL_DRAW) != rsc->surface) ) + if (gl_direct_enabled) { - // Flush remainder of what's in Evas' pipeline - if (re->win) eng_window_use(NULL); + int curr_fbo = 0; - // Do a make current - ret = glsym_eglMakeCurrent(re->win->egl_disp, rsc->surface, - rsc->surface, ctx->context); - if (!ret) + // Do a make current only if it's not already current +#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) + if ((glsym_eglGetCurrentContext() != ctx->context) || + (glsym_eglGetCurrentSurface(EGL_READ) != sfc->direct_sfc) || + (glsym_eglGetCurrentSurface(EGL_DRAW) != sfc->direct_sfc) ) { - ERR("xxxMakeCurrent() failed!"); - return 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 = glsym_eglMakeCurrent(re->win->egl_disp, sfc->direct_sfc, + sfc->direct_sfc, ctx->context); + if (!ret) + { + ERR("xxxMakeCurrent() failed! code=%#x", glsym_eglGetError()); + //ERR("xxxMakeCurrent() failed!"); + return 0; + } + } - } #else - if ((glsym_glXGetCurrentContext() != ctx->context) || - (glsym_glXGetCurrentDrawable() != re->win->win) ) - { - // Flush remainder of what's in Evas' pipeline - if (re->win) eng_window_use(NULL); - - // Do a make current - ret = glsym_glXMakeCurrent(re->info->info.display, re->win->win, ctx->context); - if (!ret) + if ((glsym_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 = glsym_glXMakeCurrent(re->info->info.display, sfc->direct_sfc, ctx->context); + if (!ret) + { + ERR("xxxMakeCurrent() failed!"); + return 0; + } } - } #endif + glsym_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo); + if (ctx->context_fbo == curr_fbo) + { + ctx->current_fbo = 0; + glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0); + } - // Create FBO if not already created - if (!ctx->initialized) - { - glsym_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)) + else { - if (!_attach_fbo_surface(re, sfc, ctx)) + // Do a make current only if it's not already current +#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) + if (eina_main_loop_is()) { - ERR("_attach_fbo_surface() failed."); - return 0; - } + if ((glsym_eglGetCurrentContext() != ctx->context) || + (glsym_eglGetCurrentSurface(EGL_READ) != re->win->egl_surface[0]) || + (glsym_eglGetCurrentSurface(EGL_DRAW) != re->win->egl_surface[0]) ) + { - if (ctx->current_fbo) - // Bind to the previously bound buffer - glsym_glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo); + // Flush remainder of what's in Evas' pipeline + if (re->win) eng_window_use(NULL); + + // Do a make current + ret = glsym_eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], + re->win->egl_surface[0], ctx->context); + if (!ret) + { + ERR("xxxMakeCurrent() failed! code=%#x", glsym_eglGetError()); + return 0; + } + } + } else - // Bind FBO - glsym_glBindFramebuffer(GL_FRAMEBUFFER, ctx->context_fbo); + { + if ((rsc = eina_tls_get(resource_key)) == EINA_FALSE) return 0; + + if ((glsym_eglGetCurrentContext() != ctx->context) || + (glsym_eglGetCurrentSurface(EGL_READ) != rsc->surface) || + (glsym_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 = glsym_eglMakeCurrent(re->win->egl_disp, rsc->surface, + rsc->surface, ctx->context); + if (!ret) + { + ERR("xxxMakeCurrent() failed!"); + return 0; + } + } + } +#else + if ((glsym_glXGetCurrentContext() != ctx->context) || + (glsym_glXGetCurrentDrawable() != re->win->win) ) + { + // Flush remainder of what's in Evas' pipeline + if (re->win) eng_window_use(NULL); + + // Do a make current + ret = glsym_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) + { + glsym_glGenFramebuffers(1, &ctx->context_fbo); + ctx->initialized = 1; + } - sfc->fbo_attached = 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)) + { + ERR("_attach_fbo_surface() failed."); + return 0; + } + + if (ctx->current_fbo) + // Bind to the previously bound buffer + glsym_glBindFramebuffer(GL_FRAMEBUFFER, ctx->current_fbo); + else + // Bind FBO + glsym_glBindFramebuffer(GL_FRAMEBUFFER, ctx->context_fbo); + + sfc->fbo_attached = 1; + } } // Set the current surface/context @@ -3232,23 +3383,36 @@ eng_gl_proc_address_get(void *data __UNUSED__, const char *name) } static int -eng_gl_native_surface_get(void *data, void *surface, void *native_surface) +eng_gl_native_surface_get(void *data __UNUSED__, void *surface, void *native_surface) { - Render_Engine *re; Render_Engine_GL_Surface *sfc; Evas_Native_Surface *ns; - re = (Render_Engine *)data; 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; } @@ -3268,22 +3432,27 @@ evgl_glBindFramebuffer(GLenum target, GLuint framebuffer) { Render_Engine_GL_Context *ctx = current_evgl_ctx; + if (!ctx) + { + ERR("Current context NULL.\n"); + return; + } + // Take care of BindFramebuffer 0 issue if (framebuffer==0) { - if (ctx) - { - glsym_glBindFramebuffer(target, ctx->context_fbo); - ctx->current_fbo = 0; - } + if (gl_direct_enabled) + glsym_glBindFramebuffer(target, 0); + else + glsym_glBindFramebuffer(target, ctx->context_fbo); + ctx->current_fbo = 0; } else { glsym_glBindFramebuffer(target, framebuffer); // Save this for restore when doing make current - if (ctx) - ctx->current_fbo = framebuffer; + ctx->current_fbo = framebuffer; } } @@ -3295,6 +3464,225 @@ evgl_glBindRenderbuffer(GLenum target, GLuint renderbuffer) glsym_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]) +{ + 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); + glsym_glScissor(oc[0], oc[1], oc[2], oc[3]); + glsym_glClear(mask); + } + else + glsym_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; + + glsym_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; + glsym_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; + glsym_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); + glsym_glReadPixels(nc[0], nc[1], nc[2], nc[3], format, type, pixels); + } + else + glsym_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); + glsym_glScissor(nc[0], nc[1], nc[2], nc[3]); + ctx->scissor_upated = 1; + } + else + glsym_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); + glsym_glEnable(GL_SCISSOR_TEST); + glsym_glScissor(oc[0], oc[1], oc[2], oc[3]); + glsym_glViewport(nc[0], nc[1], nc[2], nc[3]); + } + else + glsym_glViewport(x, y, width, height); + +} + + +//----------------------------------------------// + static void evgl_glClearDepthf(GLclampf depth) { @@ -3331,7 +3719,9 @@ evgl_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* precision[0] = 24; // floor(-log2((1.0/16777218.0))); } return; + /* shadertype = precisiontype = 0; + */ #endif } @@ -3372,7 +3762,10 @@ evgl_evasglCreateImage(int target, void* buffer, int *attrib_list) attrib_list); } else - ERR("Invalid Engine... (Can't acccess EGL Display)\n"); + { + ERR("Invalid Engine... (Can't acccess EGL Display)\n"); + return NULL; + } } static void @@ -3425,8 +3818,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); @@ -3448,11 +3841,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); @@ -3506,7 +3899,7 @@ eng_gl_api_get(void *data) // ORD(glReleaseShaderCompiler); ORD(glRenderbufferStorage); ORD(glSampleCoverage); - ORD(glScissor); +// ORD(glScissor); // ORD(glShaderBinary); ORD(glShaderSource); ORD(glStencilFunc); @@ -3551,7 +3944,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_) @@ -3611,6 +4004,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); @@ -3633,6 +4034,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) { @@ -3771,6 +4190,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 */ @@ -3855,6 +4277,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/src/modules/engines/software_generic/evas_engine.c b/src/modules/engines/software_generic/evas_engine.c index 2381a8d..e1f4c2a 100644 --- a/src/modules/engines/software_generic/evas_engine.c +++ b/src/modules/engines/software_generic/evas_engine.c @@ -1784,6 +1784,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,