From d74e82f6d83af88e1f2d609bb80d843dbd5f147d Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 2 May 2012 08:31:15 +0000 Subject: [PATCH] Cleaned up some evas_gl code and added surface cap feature. Previously, evas_gl_surface_create() didn't actually do the render buffer attach to the the FBO. It was performed when the make_current was called for the first time. The issue was that even though the surface was successfully created with the given configuration, there was a possibility of make_current failing with the error message "FBO not complete" because of the surface configuration. So, I've added a piece of code that checks the FBO capabilities beforehand to set up a available surface configurations so that it doesn't have to fail during make_current for unsupported surface format. Also, I've changed the surface config in a way that once the user calls evas_gl_surface_create(), evas gl sets the config parameter with configuration that evas_gl is actually using. SVN revision: 70617 --- legacy/evas/src/lib/Evas_GL.h | 6 +- legacy/evas/src/lib/canvas/evas_gl.c | 20 +- .../src/modules/engines/gl_x11/evas_engine.c | 625 +++++++++++++----- 3 files changed, 469 insertions(+), 182 deletions(-) diff --git a/legacy/evas/src/lib/Evas_GL.h b/legacy/evas/src/lib/Evas_GL.h index 9a7113cdb4..17b3aab1d5 100644 --- a/legacy/evas/src/lib/Evas_GL.h +++ b/legacy/evas/src/lib/Evas_GL.h @@ -2,7 +2,6 @@ #define _EVAS_GL_H #include -//#include #ifdef __cplusplus extern "C" { @@ -422,6 +421,11 @@ EAPI void evas_gl_config_free (Evas_GL_Config *cfg) E * @param w The width of the surface. * @param h The height of the surface. * @return The created GL surface object, or NULL on failure. + * + * The surface_create function internally finds the closest surface + * configureation that matches the input config. The function then internally + * sets the input config parameters to the configuratoin that was actually + * used to create the surface. */ EAPI Evas_GL_Surface *evas_gl_surface_create (Evas_GL *evas_gl, Evas_GL_Config *cfg, int w, int h) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1,2); diff --git a/legacy/evas/src/lib/canvas/evas_gl.c b/legacy/evas/src/lib/canvas/evas_gl.c index 85ed851bb4..bccab2dd8d 100644 --- a/legacy/evas/src/lib/canvas/evas_gl.c +++ b/legacy/evas/src/lib/canvas/evas_gl.c @@ -39,7 +39,7 @@ evas_gl_new(Evas *e) if (!evas_gl->evas->engine.func->gl_context_create) { - ERR("GL engine not available\n"); + ERR("Evas GL engine not available."); free(evas_gl); return NULL; } @@ -96,7 +96,7 @@ evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int if (!config) { - ERR("Invalid Config\n"); + ERR("Invalid Config Pointer!"); return NULL; } @@ -108,7 +108,7 @@ evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int if (!surf->data) { - ERR("Failed creating a surface from the engine\n"); + ERR("Failed creating a surface from the engine."); free(surf); return NULL; } @@ -129,7 +129,7 @@ evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf) if (!surf) { - ERR("Trying to destroy a NULL surface pointer!\n"); + ERR("Trying to destroy a NULL surface pointer!"); return; } @@ -158,7 +158,7 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx) ctx = calloc(1, sizeof(Evas_GL_Context)); if (!ctx) { - ERR("Unable to create a Evas_GL_Context object\n"); + ERR("Unable to create a Evas_GL_Context object"); return NULL; } @@ -175,7 +175,7 @@ evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx) // Set a few variables if (!ctx->data) { - ERR("Failed creating a context from the engine\n"); + ERR("Failed creating a context from the engine."); free(ctx); return NULL; } @@ -197,7 +197,7 @@ evas_gl_context_destroy(Evas_GL *evas_gl, Evas_GL_Context *ctx) if (!ctx) { - ERR("Trying to destroy a NULL context pointer!\n"); + ERR("Trying to destroy a NULL context pointer!"); return; } @@ -256,6 +256,12 @@ evas_gl_native_surface_get(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_Native_ return EINA_FALSE; MAGIC_CHECK_END(); + if ((!surf) || (!ns)) + { + ERR("Invalid input parameters!"); + return EINA_FALSE; + } + return (Eina_Bool)evas_gl->evas->engine.func->gl_native_surface_get(evas_gl->evas->engine.data.output, surf->data, ns); } 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 957f266f28..ef7b7f7eab 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -41,17 +41,26 @@ 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; + // GL Surface Capability + struct { + int rgb_fmt; + int rgba_fmt; - GLfloat df_clear_color[4]; - GLfloat df_depth_value; + int depth_8; + int depth_16; + int depth_24; + int depth_32; - int df_initialized; + int stencil_1; + int stencil_2; + int stencil_4; + int stencil_8; + int stencil_16; + + int depth_24_stencil_8; + } gl_cap; + + int gl_cap_initted; }; struct _Render_Engine_GL_Surface @@ -64,7 +73,7 @@ struct _Render_Engine_GL_Surface int direct_fb_opt; - // Render target texture/buffers + // Render target Texture/Buffers GLuint rt_tex; GLint rt_internal_fmt; GLenum rt_fmt; @@ -72,6 +81,8 @@ struct _Render_Engine_GL_Surface GLenum rb_depth_fmt; GLuint rb_stencil; GLenum rb_stencil_fmt; + GLuint rb_depth_stencil; + GLenum rb_depth_stencil_fmt; #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) EGLSurface direct_sfc; @@ -93,9 +104,9 @@ struct _Render_Engine_GL_Context GLuint context_fbo; GLuint current_fbo; - int scissor_enabled; int scissor_upated; + GLfloat df_clear_color[4]; Render_Engine_GL_Surface *current_sfc; }; @@ -343,7 +354,7 @@ static Extension_Entry _evasgl_ext_entries[] = { }; static void -_sym_init(void) +_gl_ext_sym_init(void) { static int done = 0; @@ -582,7 +593,7 @@ _sym_init(void) } static void -_extensions_init(Render_Engine *re) +_gl_ext_init(Render_Engine *re) { int i; const char *glexts, *evasglexts; @@ -620,7 +631,7 @@ _extensions_init(Render_Engine *re) re->info->info.screen); #endif - DBG("--------EvasGL Extensions----------"); + DBG("--------EvasGL Supported Extensions----------"); for (i = 0; _evasgl_ext_entries[i].name != NULL; i++) { if ( (strstr(evasglexts, _evasgl_ext_entries[i].name) != NULL) || @@ -632,8 +643,8 @@ _extensions_init(Render_Engine *re) DBG("\t%s", _evasgl_ext_entries[i].name); } } - DBG(" "); } + DBG(" "); } int _evas_engine_GL_X11_log_dom = -1; @@ -750,16 +761,26 @@ _create_internal_glue_resources(void *data) context_attrs[1] = 2; context_attrs[2] = EGL_NONE; - // Create resource surface for EGL - rsc->surface = eglCreateWindowSurface(re->win->egl_disp, - re->win->egl_config, - (EGLNativeWindowType)DefaultRootWindow(re->info->info.display), - NULL); - if (!rsc->surface) + + + + if (eina_main_loop_is()) { - ERR("Creating internal resource surface failed."); - free(rsc); - return NULL; + rsc->surface = re->win->egl_surface[0]; + } + else + { + // Create resource surface for EGL + rsc->surface = eglCreateWindowSurface(re->win->egl_disp, + re->win->egl_config, + (EGLNativeWindowType)DefaultRootWindow(re->info->info.display), + NULL); + if (!rsc->surface) + { + ERR("Creating internal resource surface failed."); + free(rsc); + return NULL; + } } // Create a resource context for EGL @@ -832,8 +853,10 @@ _destroy_internal_glue_resources(void *data) LKL(resource_lock); EINA_LIST_FOREACH(resource_list, l, rsc) { - if (rsc->surface) eglDestroySurface(re->win->egl_disp, rsc->surface); - if (rsc->context) eglDestroyContext(re->win->egl_disp, rsc->context); + if ((rsc->surface) && (rsc->surface != re->win->egl_surface[0])) + eglDestroySurface(re->win->egl_disp, rsc->surface); + if (rsc->context) + eglDestroyContext(re->win->egl_disp, rsc->context); free(rsc); } eina_list_free(resource_list); @@ -1072,11 +1095,8 @@ eng_setup(Evas *e, void *in) eng_window_use(re->win); re->vsync = 0; - _sym_init(); - _extensions_init(re); - - // This is used in extensions. Not pretty but can't get display otherwise. - current_engine = re; + _gl_ext_sym_init(); + _gl_ext_init(re); return 1; } @@ -2812,7 +2832,8 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int evas_gl_font_texture_new, evas_gl_font_texture_free, evas_gl_font_texture_draw); - evas_common_font_draw(im, context, x, y, intl_props); + evas_common_font_draw(im, context, (RGBA_Font *) font, x, y, + intl_props); evas_common_draw_context_font_ext_set(context, NULL, NULL, @@ -2828,22 +2849,164 @@ eng_canvas_alpha_get(void *data, void *info __UNUSED__) return re->win->alpha; } + +// Unfortunately, there is no query function to figure out which surface formats work. +// So, this is one way to test for surface config capability. static int -_set_internal_config(Render_Engine_GL_Surface *sfc, Evas_GL_Config *cfg) +_check_gl_surface_format(GLint int_fmt, GLenum fmt, GLenum attachment, GLenum attach_fmt) { - // Also initialize pixel format here as well... + GLuint fbo, tex, rb; + int w, h, fb_status; + + // Width/Heith for test purposes + w = h = 2; + + // Gen FBO + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + // Render Target Texture + if (int_fmt) + { + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); + } + + // Render Target Attachment (Stencil or Depth) + if (attachment) + { + glGenRenderbuffers(1, &rb); + glBindRenderbuffer(GL_RENDERBUFFER, rb); + glRenderbufferStorage(GL_RENDERBUFFER, attach_fmt, w, h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, rb); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + // Check FBO for completeness + fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + + // Delete Created Resources + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo); + if (tex) glDeleteTextures(1, &tex); + if (rb) glDeleteBuffers(1, &rb); + + if (fb_status != GL_FRAMEBUFFER_COMPLETE) + return 0; + else + { + if (attachment) + return attach_fmt; + else + return 1; + } +} + +static void +_print_gl_surface_cap(Render_Engine *re, int error) +{ +#define PRINT_LOG(...) \ + if (error) \ + ERR(__VA_ARGS__); \ + else \ + DBG(__VA_ARGS__); + + PRINT_LOG("---------------------------------------------------"); + PRINT_LOG(" EvasGL Supported Surface Format "); + PRINT_LOG(" [RGB Fromat] : %x", re->gl_cap.rgb_fmt); + PRINT_LOG(" [RGBA Fromat] : %x", re->gl_cap.rgba_fmt); + PRINT_LOG(" [Depth 8 Bits] : %x", re->gl_cap.depth_8); + PRINT_LOG(" [Depth 16 Bits] : %x", re->gl_cap.depth_16); + PRINT_LOG(" [Depth 24 Bits] : %x", re->gl_cap.depth_24); + PRINT_LOG(" [Depth 32 Bits] : %x", re->gl_cap.depth_32); + PRINT_LOG(" [Stencil 1 Bits] : %x", re->gl_cap.stencil_1); + PRINT_LOG(" [Stencil 2 Bits] : %x", re->gl_cap.stencil_2); + PRINT_LOG(" [Stencil 4 Bits] : %x", re->gl_cap.stencil_4); + PRINT_LOG(" [Stencil 8 Bits] : %x", re->gl_cap.stencil_8); + PRINT_LOG(" [Stencil 16 Bits] : %x", re->gl_cap.stencil_16); + PRINT_LOG(" [Depth 24 Stencil 8 Bits]: %x", re->gl_cap.depth_24_stencil_8); + PRINT_LOG("---------------------------------------------------"); +#undef PRINT_LOG +} + +static void +_set_gl_surface_cap(Render_Engine *re) +{ + GLuint fbo, tex, depth, stencil; + int w, h; + int ret; + + if (!re) return; + if (re->gl_cap_initted) return; + + // Width/Heith for test purposes + w = h = 2; + + re->gl_cap.rgb_fmt = _check_gl_surface_format(GL_RGB, GL_RGB, 0, 0); + re->gl_cap.rgba_fmt = _check_gl_surface_format(GL_RGBA, GL_RGBA, 0, 0); + +#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) + re->gl_cap.depth_8 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT); + re->gl_cap.depth_16 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16); + re->gl_cap.depth_24 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24_OES); + re->gl_cap.depth_32 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32_OES); + + re->gl_cap.stencil_1 = _check_gl_surface_format(0, 0, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX1_OES); + re->gl_cap.stencil_4 = _check_gl_surface_format(0, 0, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX4_OES); + re->gl_cap.stencil_8 = _check_gl_surface_format(0, 0, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8); +#else + re->gl_cap.depth_8 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT); + re->gl_cap.depth_16 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16); + re->gl_cap.depth_24 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24); + re->gl_cap.depth_32 = _check_gl_surface_format(0, 0, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32); + + re->gl_cap.stencil_1 = _check_gl_surface_format(0, 0, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX1); + re->gl_cap.stencil_4 = _check_gl_surface_format(0, 0, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX4); + re->gl_cap.stencil_8 = _check_gl_surface_format(0, 0, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8); + + re->gl_cap.depth_24_stencil_8 = _check_gl_surface_format(0, 0, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8); +#endif + + _print_gl_surface_cap(re, 0); + + re->gl_cap_initted = 1; +} + +static int +_set_internal_config(Render_Engine *re, Render_Engine_GL_Surface *sfc, Evas_GL_Config *cfg) +{ + int ret = 0; + + // Check if color formats are supported switch((int)cfg->color_format) { case EVAS_GL_RGB_888: - sfc->rt_fmt = GL_RGB; - sfc->rt_internal_fmt = GL_RGB; - break; + if (re->gl_cap.rgb_fmt) + { + sfc->rt_fmt = GL_RGB; + sfc->rt_internal_fmt = GL_RGB; + break; + } case EVAS_GL_RGBA_8888: - sfc->rt_fmt = GL_RGBA; - sfc->rt_internal_fmt = GL_RGBA; - break; + if (re->gl_cap.rgba_fmt) + { + sfc->rt_fmt = GL_RGBA; + sfc->rt_internal_fmt = GL_RGBA; + cfg->color_format = EVAS_GL_RGBA_8888; + break; + } default: - ERR("Invalid Color Format!"); + ERR("Color Format Not Supported!"); + _print_gl_surface_cap(re, 1); return 0; } @@ -2852,18 +3015,36 @@ _set_internal_config(Render_Engine_GL_Surface *sfc, Evas_GL_Config *cfg) case EVAS_GL_DEPTH_NONE: break; case EVAS_GL_DEPTH_BIT_8: + if (re->gl_cap.depth_8) + { + sfc->rb_depth_fmt = re->gl_cap.depth_8; + cfg->depth_bits = EVAS_GL_DEPTH_BIT_8; + break; + } case EVAS_GL_DEPTH_BIT_16: + if (re->gl_cap.depth_16) + { + sfc->rb_depth_fmt = re->gl_cap.depth_16; + cfg->depth_bits = EVAS_GL_DEPTH_BIT_16; + break; + } case EVAS_GL_DEPTH_BIT_24: -#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) - // 24 bit doesn't work... just cover it with 16 for now.. - sfc->rb_depth_fmt = GL_DEPTH_COMPONENT16; -#else - sfc->rb_depth_fmt = GL_DEPTH_COMPONENT; -#endif - break; + if (re->gl_cap.depth_24) + { + sfc->rb_depth_fmt = re->gl_cap.depth_24; + cfg->depth_bits = EVAS_GL_DEPTH_BIT_24; + break; + } case EVAS_GL_DEPTH_BIT_32: + if (re->gl_cap.depth_32) + { + sfc->rb_depth_fmt = re->gl_cap.depth_32; + cfg->depth_bits = EVAS_GL_DEPTH_BIT_32; + break; + } default: ERR("Unsupported Depth Bits Format!"); + _print_gl_surface_cap(re, 1); return 0; } @@ -2872,47 +3053,92 @@ _set_internal_config(Render_Engine_GL_Surface *sfc, Evas_GL_Config *cfg) case EVAS_GL_STENCIL_NONE: break; case EVAS_GL_STENCIL_BIT_1: + if (re->gl_cap.stencil_1) + { + sfc->rb_stencil_fmt = re->gl_cap.stencil_1; + cfg->stencil_bits = EVAS_GL_STENCIL_BIT_1; + break; + } case EVAS_GL_STENCIL_BIT_2: + if (re->gl_cap.stencil_2) + { + sfc->rb_stencil_fmt = re->gl_cap.stencil_2; + cfg->stencil_bits = EVAS_GL_STENCIL_BIT_2; + break; + } case EVAS_GL_STENCIL_BIT_4: + if (re->gl_cap.stencil_4) + { + sfc->rb_stencil_fmt = re->gl_cap.stencil_4; + cfg->stencil_bits = EVAS_GL_STENCIL_BIT_4; + break; + } case EVAS_GL_STENCIL_BIT_8: -#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) - sfc->rb_stencil_fmt = GL_STENCIL_INDEX8; -#else - sfc->rb_stencil_fmt = GL_STENCIL_INDEX; -#endif - break; + if (re->gl_cap.stencil_8) + { + sfc->rb_stencil_fmt = re->gl_cap.stencil_8; + cfg->stencil_bits = EVAS_GL_STENCIL_BIT_8; + break; + } + else if (re->gl_cap.depth_24_stencil_8) + { + sfc->rb_depth_stencil_fmt = re->gl_cap.depth_24_stencil_8; + cfg->depth_bits = EVAS_GL_DEPTH_BIT_24; + cfg->stencil_bits = EVAS_GL_STENCIL_BIT_8; + break; + } case EVAS_GL_STENCIL_BIT_16: + if (re->gl_cap.stencil_16) + { + sfc->rb_stencil_fmt = re->gl_cap.stencil_16; + cfg->stencil_bits = EVAS_GL_STENCIL_BIT_16; + break; + } default: ERR("Unsupported Stencil Bits Format!"); + _print_gl_surface_cap(re, 1); return 0; } if (cfg->options_bits) { if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT) - sfc->direct_fb_opt = 1; + { + sfc->direct_fb_opt = 1; + DBG("########################################################"); + DBG("######### [Evas] Direct option bit is enabled ##########"); + DBG("########################################################"); + } // Add other options here... } return 1; } -static int +static void _create_rt_buffers(Render_Engine *data __UNUSED__, Render_Engine_GL_Surface *sfc) { // Render Target texture - glGenTextures(1, &sfc->rt_tex ); + if (sfc->rt_fmt) + { + glGenTextures(1, &sfc->rt_tex); + } + + // First check if packed buffer is to be used. + if (sfc->rb_depth_stencil_fmt) + { + glGenRenderbuffers(1, &sfc->rb_depth_stencil); + return; + } // Depth RenderBuffer - Create storage here... - if (sfc->depth_bits != EVAS_GL_DEPTH_NONE) + if (sfc->rb_depth_fmt) glGenRenderbuffers(1, &sfc->rb_depth); // Stencil RenderBuffer - Create Storage here... - if (sfc->stencil_bits != EVAS_GL_STENCIL_NONE) + if (sfc->rb_stencil_fmt) glGenRenderbuffers(1, &sfc->rb_stencil); - - return 1; } static int @@ -2922,24 +3148,41 @@ _attach_fbo_surface(Render_Engine *data __UNUSED__, { int fb_status; - // Initialize Texture - glBindTexture(GL_TEXTURE_2D, sfc->rt_tex ); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sfc->w, sfc->h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_2D, 0); - - - // Attach texture to FBO glBindFramebuffer(GL_FRAMEBUFFER, ctx->context_fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, sfc->rt_tex, 0); + + // Render Target Texture + if (sfc->rt_tex) + { + glBindTexture(GL_TEXTURE_2D, sfc->rt_tex ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sfc->w, sfc->h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + // Attach texture to FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, sfc->rt_tex, 0); + } + +#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) +#else + // Depth Stencil RenderBuffer - Attach it to FBO + if (sfc->rb_depth_stencil) + { + glBindRenderbuffer(GL_RENDERBUFFER, sfc->rb_depth_stencil); + glRenderbufferStorage(GL_RENDERBUFFER, sfc->rb_depth_stencil_fmt, + sfc->w, sfc->h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, sfc->rb_depth_stencil); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } +#endif // Depth RenderBuffer - Attach it to FBO - if (sfc->depth_bits != EVAS_GL_DEPTH_NONE) + if (sfc->rb_depth) { glBindRenderbuffer(GL_RENDERBUFFER, sfc->rb_depth); glRenderbufferStorage(GL_RENDERBUFFER, sfc->rb_depth_fmt, @@ -2950,7 +3193,7 @@ _attach_fbo_surface(Render_Engine *data __UNUSED__, } // Stencil RenderBuffer - Attach it to FBO - if (sfc->stencil_bits != EVAS_GL_STENCIL_NONE) + if (sfc->rb_stencil) { glBindRenderbuffer(GL_RENDERBUFFER, sfc->rb_stencil); glRenderbufferStorage(GL_RENDERBUFFER, sfc->rb_stencil_fmt, @@ -2979,38 +3222,32 @@ eng_gl_surface_create(void *data, void *config, int w, int h) Render_Engine_GL_Surface *sfc; Render_Engine_GL_Resource *rsc; Evas_GL_Config *cfg; - int ret; - - sfc = calloc(1, sizeof(Render_Engine_GL_Surface)); - if (!sfc) return NULL; + void *ret = NULL; + int res; re = (Render_Engine *)data; cfg = (Evas_GL_Config *)config; - sfc->initialized = 0; - sfc->fbo_attached = 0; + // Allocate surface and fill in values + sfc = calloc(1, sizeof(Render_Engine_GL_Surface)); + if (!sfc) + { + ERR("Surface allocation failed."); + goto finish; + } + sfc->w = w; sfc->h = h; sfc->depth_bits = cfg->depth_bits; sfc->stencil_bits = cfg->stencil_bits; - sfc->rt_tex = 0; - sfc->rb_depth = 0; - sfc->rb_stencil = 0; - /* Allow alpha for evas gl direct rendering */ - // FIXME!!!: A little out of place for for now... + // Allow alpha for evas gl direct rendering override + // FIXME!!!: A little out of place but 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)) - { - ERR("Unsupported Format!"); - free(sfc); - return NULL; - } - - if (sfc->direct_fb_opt) + if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT) { DBG("Enabling Direct rendering to the Evas' window."); #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) @@ -3026,49 +3263,55 @@ eng_gl_surface_create(void *data, void *config, int w, int h) if ((rsc = _create_internal_glue_resources(re)) == NULL) { ERR("Error creating internal resources."); - free(sfc); - return NULL; + goto finish; } } - // I'm using evas's original context to create the render target texture - // This is to prevent awkwardness in using native_surface_get() function - // If the rt texture creation is deferred till the context is created and - // make_current called, the user can't call native_surface_get() right - // after the surface is created. hence this is done here using evas' context. + // Use resource surface/context to create surface resrouces #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) - ret = eglMakeCurrent(re->win->egl_disp, rsc->surface, rsc->surface, rsc->context); + res = eglMakeCurrent(re->win->egl_disp, rsc->surface, rsc->surface, rsc->context); #else - ret = glXMakeCurrent(re->info->info.display, re->win->win, rsc->context); + res = glXMakeCurrent(re->info->info.display, re->win->win, rsc->context); #endif - if (!ret) + if (!res) { - ERR("xxxMakeCurrent() failed!"); - free(sfc); - return NULL; + ERR("xxxMakeCurrent() finish!"); + goto finish; + } + + // Set the engine surface capability first if it hasn't been set + if (!re->gl_cap_initted) _set_gl_surface_cap(re); + + // Set the internal config value + if (!_set_internal_config(re, sfc, cfg)) + { + ERR("Unsupported Format!"); + goto finish; } // Create Render texture - if (!_create_rt_buffers(re, sfc)) - { - ERR("_create_rt_buffers() failed."); - free(sfc); - return NULL; - } + _create_rt_buffers(re, sfc); #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) - ret = eglMakeCurrent(re->win->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + res = eglMakeCurrent(re->win->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); #else - ret = glXMakeCurrent(re->info->info.display, None, NULL); + res = glXMakeCurrent(re->info->info.display, None, NULL); #endif - if (!ret) + if (!res) { - ERR("xxxMakeCurrent() failed!"); - free(sfc); - return NULL; + ERR("xxxMakeCurrent() finish!"); + goto finish; } - return sfc; + ret = sfc; + +finish: + + if (!ret) + { + if (!sfc) free(sfc); + } + return ret; } static int @@ -3104,7 +3347,7 @@ eng_gl_surface_destroy(void *data, void *surface) current_evgl_ctx->current_fbo = 0; current_evgl_ctx->current_sfc = NULL; } - + // Clear direct rendering flag gl_direct_enabled = 0; @@ -3118,6 +3361,8 @@ eng_gl_surface_destroy(void *data, void *surface) if (sfc->rb_stencil) glDeleteRenderbuffers(1, &sfc->rb_stencil); + if (sfc->rb_depth_stencil) + glDeleteRenderbuffers(1, &sfc->rb_depth_stencil); #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) @@ -3245,7 +3490,7 @@ eng_gl_context_destroy(void *data, void *context) // Delete the FBO if (ctx->context_fbo) - glDeleteFramebuffers(1, &ctx->context_fbo); + glDeleteFramebuffers(1, &ctx->context_fbo); // Destroy the Context #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) @@ -3289,6 +3534,8 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context) sfc = (Render_Engine_GL_Surface*)surface; ctx = (Render_Engine_GL_Context*)context; + current_engine = re; + // Unset surface/context if ((!sfc) || (!ctx)) { @@ -3311,9 +3558,9 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *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 + // 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; @@ -3322,17 +3569,18 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context) if (gl_direct_enabled) { + int curr_fbo = 0; + // Do a make current only if it's not already current #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) - if ((eglGetCurrentContext() != ctx->context) || + if ((eglGetCurrentContext() != ctx->context) || (eglGetCurrentSurface(EGL_READ) != sfc->direct_sfc) || - (eglGetCurrentSurface(EGL_DRAW) != sfc->direct_sfc) ) + (eglGetCurrentSurface(EGL_DRAW) != sfc->direct_sfc) ) { - 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); + eng_window_use(NULL); // Do a make current ret = eglMakeCurrent(re->win->egl_disp, sfc->direct_sfc, @@ -3343,50 +3591,73 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context) //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)) { // Flush remainder of what's in Evas' pipeline - if (re->win) eng_window_use(NULL); + eng_window_use(NULL); // Do a make current ret = glXMakeCurrent(re->info->info.display, sfc->direct_sfc, ctx->context); - if (!ret) + if (!ret) { ERR("xxxMakeCurrent() failed!"); return 0; } } #endif + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo); + if (ctx->context_fbo == curr_fbo) + { + ctx->current_fbo = 0; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + } 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) ) + if (eina_main_loop_is()) { - // 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) != re->win->egl_surface[0]) || + (eglGetCurrentSurface(EGL_DRAW) != re->win->egl_surface[0]) ) { - ERR("xxxMakeCurrent() failed!"); - return 0; + + // Flush remainder of what's in Evas' pipeline + eng_window_use(NULL); + + // Do a make current + ret = eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], + re->win->egl_surface[0], ctx->context); + if (!ret) + { + ERR("xxxMakeCurrent() failed! code=%#x", eglGetError()); + return 0; + } + } + } + else + { + 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 + 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 @@ -3394,7 +3665,7 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context) (glXGetCurrentDrawable() != re->win->win) ) { // Flush remainder of what's in Evas' pipeline - if (re->win) eng_window_use(NULL); + eng_window_use(NULL); // Do a make current ret = glXMakeCurrent(re->info->info.display, re->win->win, ctx->context); @@ -3437,6 +3708,7 @@ eng_gl_make_current(void *data __UNUSED__, void *surface, void *context) ctx->current_sfc = sfc; sfc->current_ctx = ctx; current_evgl_ctx = ctx; + current_engine = re; return 1; } @@ -3466,13 +3738,11 @@ 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; @@ -3507,7 +3777,7 @@ static const GLubyte * evgl_glGetString(GLenum name) { if (name == GL_EXTENSIONS) - return (GLubyte *)_gl_ext_string; //glGetString(GL_EXTENSIONS); + return (GLubyte *)_gl_ext_string; //glGetString(GL_EXTENSIONS); else return glGetString(name); } @@ -3553,14 +3823,14 @@ evgl_glBindRenderbuffer(GLenum target, GLuint renderbuffer) // 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, +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[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; @@ -3668,16 +3938,18 @@ evgl_glClear(GLbitfield 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; + Render_Engine_GL_Context *ctx = current_evgl_ctx; + + current_evgl_ctx->df_clear_color[0] = red; + current_evgl_ctx->df_clear_color[1] = green; + current_evgl_ctx->df_clear_color[2] = blue; + current_evgl_ctx->df_clear_color[3] = alpha; glClearColor(red, green, blue, alpha); } -static void +static void evgl_glEnable(GLenum cap) { Render_Engine_GL_Context *ctx = current_evgl_ctx; @@ -3804,7 +4076,6 @@ evgl_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* precision[0] = 24; // floor(-log2((1.0/16777218.0))); } return; - shadertype = precisiontype = 0; #endif } @@ -4125,14 +4396,14 @@ eng_gl_img_obj_set(void *data, void *image, int has_alpha) 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)) + // 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; + else + gl_direct_img_obj = image; } static int @@ -4274,7 +4545,13 @@ module_open(Evas_Module *em) return 0; } /* Allow alpha for evas gl direct rendering */ - if (getenv("EVAS_GL_DIRECT_OVERRIDE")) gl_direct_override = 1; + if (getenv("EVAS_GL_DIRECT_OVERRIDE")) + { + gl_direct_override = 1; + DBG("########################################################"); + DBG("######### [Evas] Direct overriding is enabled ##########"); + DBG("########################################################"); + } /* store it for later use */ func = pfunc; @@ -4383,7 +4660,7 @@ static void module_close(Evas_Module *em __UNUSED__) { eina_log_domain_unregister(_evas_engine_GL_X11_log_dom); -/* +/* if (xrdb_user.db) { XrmDestroyDatabase(xrdb_user.db);