diff --git a/ChangeLog b/ChangeLog index c50c3b6544..55704c3d93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2013-01-07 Sung W. Park (sung_) + + * Applied on-demand memory allocation policy for Evas GL Surface + for direct rendering optimization. For direct rendering in EvasGL, + it falls back to FBO rendering if the conditions are not met. Before, + the fallback resources were created in the beginning but now they are + created and destroyed on need base. + 2013-01-21 Carsten Haitzler (The Rasterman) * Fix xsync problem in ecore_x_image_get() where prior errors diff --git a/src/modules/evas/engines/gl_common/evas_gl_api.c b/src/modules/evas/engines/gl_common/evas_gl_api.c index 786be7342e..b6af4ca9e4 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api.c +++ b/src/modules/evas/engines/gl_common/evas_gl_api.c @@ -285,7 +285,7 @@ _evgl_glClear(GLbitfield mask) compute_gl_coordinates(img, rot, 0, 0, 0, 0, 0, oc, nc); - if ((ctx->scissor_upated) && (ctx->scissor_enabled)) + if ((ctx->scissor_updated) && (ctx->scissor_enabled)) { glScissor(ctx->dr_scissor_coord[0], ctx->dr_scissor_coord[1], ctx->dr_scissor_coord[2], ctx->dr_scissor_coord[3]); @@ -369,7 +369,7 @@ _evgl_glGetIntegerv(GLenum pname, GLint* params) if (pname == GL_SCISSOR_BOX) { - if (ctx->scissor_upated) + if (ctx->scissor_updated) { memcpy(params, ctx->scissor_coord, sizeof(int)*4); return; @@ -498,7 +498,7 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) ctx->direct_scissor = 0; // Check....!!!! - ctx->scissor_upated = 1; + ctx->scissor_updated = 1; } else { @@ -510,7 +510,7 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) glScissor(x, y, width, height); - ctx->scissor_upated = 0; + ctx->scissor_updated = 0; } } else @@ -563,7 +563,7 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) compute_gl_coordinates(img, rot, 0, x, y, width, height, oc, nc); - if ((ctx->scissor_upated) && (ctx->scissor_enabled)) + if ((ctx->scissor_updated) && (ctx->scissor_enabled)) { glScissor(ctx->dr_scissor_coord[0], ctx->dr_scissor_coord[1], ctx->dr_scissor_coord[2], ctx->dr_scissor_coord[3]); diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c index 885acbbdca..6b40a961c9 100755 --- a/src/modules/evas/engines/gl_common/evas_gl_core.c +++ b/src/modules/evas/engines/gl_common/evas_gl_core.c @@ -11,9 +11,12 @@ typedef struct _GL_Format // Globals static Evas_GL_API gl_funcs; EVGL_Engine *evgl_engine = NULL; -int _evas_gl_log_dom = -1; +int _evas_gl_log_dom = -1; +int _evas_gl_log_level = -1; static void _surface_cap_print(EVGL_Engine *ee, int error); +static void _surface_context_list_print(EVGL_Engine *ee); + //---------------------------------------------------------------// // Internal Resources: @@ -267,12 +270,20 @@ _internal_resource_make_current(EVGL_Engine *ee, EVGL_Context *ctx) // - Surface capability check // - Internal config choose function //---------------------------------------------------------------// -// Create and allocate 2D texture +// Gen Texture void -_texture_2d_create(GLuint *tex, GLint ifmt, GLenum fmt, GLenum type, int w, int h) +_texture_create(GLuint *tex) { glGenTextures(1, tex); - glBindTexture(GL_TEXTURE_2D, *tex ); +} + +// Create and allocate 2D texture +void +_texture_allocate_2d(GLuint tex, GLint ifmt, GLenum fmt, GLenum type, int w, int h) +{ + //if (!(*tex)) + // 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); @@ -295,7 +306,7 @@ _texture_destroy(GLuint *tex) // Attach 2D texture with the given format to already bound FBO // *NOTE: attach2 here is used for depth_stencil attachment in GLES env. void -_texture_2d_attach(GLuint tex, GLenum attach, GLenum attach2, int samples) +_texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples) { if (samples) { @@ -325,12 +336,19 @@ _texture_2d_attach(GLuint tex, GLenum attach, GLenum attach2, int samples) } } -// Attach a renderbuffer with the given format to already bound FBO +// Gen Renderbuffer void -_renderbuffer_create(GLuint *buf, GLenum fmt, int w, int h, int samples) +_renderbuffer_create(GLuint *buf) { glGenRenderbuffers(1, buf); - glBindRenderbuffer(GL_RENDERBUFFER, *buf); +} + + +// Attach a renderbuffer with the given format to already bound FBO +void +_renderbuffer_allocate(GLuint buf, GLenum fmt, int w, int h, int samples) +{ + glBindRenderbuffer(GL_RENDERBUFFER, buf); if (samples) #ifdef GL_GLES EXT_FUNC(glRenderbufferStorageMultisample)(GL_RENDERBUFFER, samples, fmt, w, h); @@ -383,24 +401,27 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, // Color Buffer Texture if ((color_ifmt) && (color_fmt)) { - _texture_2d_create(&color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h); - _texture_2d_attach(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples); + _texture_create(&color_buf); + _texture_allocate_2d(color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h); + _texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples); } // Check Depth_Stencil Format First #ifdef GL_GLES if (depth_fmt == GL_DEPTH_STENCIL_OES) { - _texture_2d_create(&depth_stencil_buf, depth_fmt, + _texture_create(&depth_stencil_buf); + _texture_allocate_2d(depth_stencil_buf, depth_fmt, depth_fmt, GL_UNSIGNED_INT_24_8_OES, w, h); - _texture_2d_attach(depth_stencil_buf, GL_DEPTH_ATTACHMENT, + _texture_attach_2d(depth_stencil_buf, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, mult_samples); depth_stencil = 1; } #else if (depth_fmt == GL_DEPTH24_STENCIL8) { - _renderbuffer_create(&depth_stencil_buf, depth_fmt, w, h, mult_samples); + _renderbuffer_create(&depth_stencil_buf); + _renderbuffer_allocate(depth_stencil_buf, depth_fmt, w, h, mult_samples); _renderbuffer_attach(depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT); depth_stencil = 1; } @@ -409,14 +430,16 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, // Depth Attachment if ((!depth_stencil) && (depth_fmt)) { - _renderbuffer_create(&depth_buf, depth_fmt, w, h, mult_samples); + _renderbuffer_create(&depth_buf); + _renderbuffer_allocate(depth_buf, depth_fmt, w, h, mult_samples); _renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT); } // Stencil Attachment if ((!depth_stencil) && (stencil_fmt)) { - _renderbuffer_create(&stencil_buf, stencil_fmt, w, h, mult_samples); + _renderbuffer_create(&stencil_buf); + _renderbuffer_allocate(stencil_buf, stencil_fmt, w, h, mult_samples); _renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT); } @@ -899,6 +922,74 @@ _surface_cap_print(EVGL_Engine *ee, int error) #undef PRINT_LOG } +static void +_surface_context_list_print(EVGL_Engine *ee) +{ + Eina_List *l; + EVGL_Surface *s; + EVGL_Context *c; + int count = 0; + + // Only print them when the log level is 6 + if (_evas_gl_log_level < 6) return; + +#define RESET "\e[m" +#define GREEN "\e[1;32m" +#define YELLOW "\e[1;33m" +#define RED "\e[1;31m" + + DBG( YELLOW "-----------------------------------------------" RESET); + DBG("Total Number of active Evas GL Surfaces: %d", eina_list_count(ee->surfaces)); + + EINA_LIST_FOREACH(ee->surfaces, l, s) + { + DBG( YELLOW "\t-----------------------------------------------" RESET); + DBG( RED "\t[Surface %d]" YELLOW " Ptr: %p" RED " Appx Mem: %d Byte", count++, s, (s->buffer_mem[0]+s->buffer_mem[1]+s->buffer_mem[2]+s->buffer_mem[3])); + DBG( GREEN "\t\t Size:" RESET " (%d, %d)", s->w, s->h); + + if (s->buffer_mem[0]) + { + DBG( GREEN "\t\t Color Format:" RESET " %s", _glenum_string_get(s->color_fmt)); + DBG( GREEN "\t\t Color Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[0]); + } + if (s->buffer_mem[1]) + { + DBG( GREEN "\t\t Depth Format:" RESET " %s", _glenum_string_get(s->depth_fmt)); + DBG( GREEN "\t\t Depth Buffer Appx. Mem Usage: " RESET "%d Byte", s->buffer_mem[1]); + } + if (s->buffer_mem[2]) + { + DBG( GREEN "\t\t Stencil Format:" RESET " %s", _glenum_string_get(s->stencil_fmt)); + DBG( GREEN "\t\t Stencil Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[2]); + } + if (s->buffer_mem[3]) + { + DBG( GREEN "\t\t D-Stencil Format:" RESET " %s", _glenum_string_get(s->depth_stencil_fmt)); + DBG( GREEN "\t\t D-Stencil Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[3]); + } + if (s->msaa_samples) + DBG( GREEN "\t\t MSAA Samples:" RESET " %d", s->msaa_samples); + if (s->direct_fb_opt) + DBG( GREEN "\t\t Direct Option Enabled" RESET ); + DBG( YELLOW "\t-----------------------------------------------" RESET); + } + + count = 0; + + DBG( YELLOW "-----------------------------------------------" RESET); + DBG("Total Number of active Evas GL Contexts: %d", eina_list_count(ee->contexts)); + EINA_LIST_FOREACH(ee->contexts, l, c) + { + DBG( YELLOW "\t-----------------------------------------------" RESET); + DBG( RED "\t[Context %d]" YELLOW " Ptr: %p", count++, c); + } + DBG( YELLOW "-----------------------------------------------" RESET); + +#undef RESET +#undef GREEN +#undef YELLOW +#undef RED +} //--------------------------------------------------------// // Start from here..... @@ -924,14 +1015,14 @@ _surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo) // Render Target Texture if (sfc->color_buf) - _texture_2d_attach(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples); + _texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples); // Depth Stencil RenderBuffer - Attach it to FBO if (sfc->depth_stencil_buf) { #ifdef GL_GLES - _texture_2d_attach(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT, + _texture_attach_2d(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, sfc->msaa_samples); #else _renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT); @@ -960,9 +1051,6 @@ _surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo) static int _surface_buffers_create(EVGL_Engine *ee, EVGL_Surface *sfc) { - GLuint fbo = 0; - int ret = 0; - // Set the context current with resource context/surface if (!_internal_resource_make_current(ee, NULL)) { @@ -973,8 +1061,7 @@ _surface_buffers_create(EVGL_Engine *ee, EVGL_Surface *sfc) // Create buffers if (sfc->color_fmt) { - _texture_2d_create(&sfc->color_buf, sfc->color_ifmt, sfc->color_fmt, - GL_UNSIGNED_BYTE, sfc->w, sfc->h); + _texture_create(&sfc->color_buf); } @@ -982,44 +1069,105 @@ _surface_buffers_create(EVGL_Engine *ee, EVGL_Surface *sfc) if (sfc->depth_stencil_fmt) { #ifdef GL_GLES - _texture_2d_create(&sfc->depth_stencil_buf, sfc->depth_stencil_fmt, - sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES, - sfc->w, sfc->h); + _texture_create(&sfc->depth_stencil_buf); #else - _renderbuffer_create(&sfc->depth_stencil_buf, sfc->depth_stencil_fmt, - sfc->w, sfc->h, sfc->msaa_samples); + _renderbuffer_create(&sfc->depth_stencil_buf); #endif } else { if (sfc->depth_fmt) { - _renderbuffer_create(&sfc->depth_buf, sfc->depth_fmt, sfc->w, sfc->h, - sfc->msaa_samples); + _renderbuffer_create(&sfc->depth_buf); } if (sfc->stencil_fmt) { - _renderbuffer_create(&sfc->stencil_buf, sfc->stencil_fmt, sfc->w, - sfc->h, sfc->msaa_samples); + _renderbuffer_create(&sfc->stencil_buf); } } - // Set surface buffers with an fbo - if (!(ret = _surface_buffers_fbo_set(sfc, fbo))) + if (!ee->funcs->make_current(ee->engine_data, NULL, NULL, 0)) + { + ERR("Error doing make_current(NULL, NULL)."); + return 0; + } + + return 1; //ret; +} + + +static int +_surface_buffers_allocate(EVGL_Engine *ee, EVGL_Surface *sfc, int w, int h) +{ + // Set the context current with resource context/surface + if (!_internal_resource_make_current(ee, NULL)) + { + ERR("Error doing an internal resource make current"); + return 0; + } + + // Create buffers + if (sfc->color_fmt) + { + _texture_allocate_2d(sfc->color_buf, sfc->color_ifmt, sfc->color_fmt, + GL_UNSIGNED_BYTE, w, h); + sfc->buffer_mem[0] = w * h * 4; + } + + // Depth_stencil buffers or separate buffers + if (sfc->depth_stencil_fmt) { - ERR("Attaching the surface buffers to an FBO failed."); - if (sfc->color_buf) - glDeleteTextures(1, &sfc->color_buf); - if (sfc->depth_buf) - glDeleteRenderbuffers(1, &sfc->depth_buf); - if (sfc->stencil_buf) - glDeleteRenderbuffers(1, &sfc->stencil_buf); #ifdef GL_GLES - if (sfc->depth_stencil_buf) - glDeleteTextures(1, &sfc->depth_stencil_buf); + _texture_allocate_2d(sfc->depth_stencil_buf, sfc->depth_stencil_fmt, + sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES, + w, h); #else - if (sfc->depth_stencil_buf) - glDeleteRenderbuffers(1, &sfc->depth_stencil_buf); + _renderbuffer_allocate(sfc->depth_stencil_buf, sfc->depth_stencil_fmt, + w, h, sfc->msaa_samples); +#endif + sfc->buffer_mem[3] = w * h * 4; + } + else + { + if (sfc->depth_fmt) + { + _renderbuffer_allocate(sfc->depth_buf, sfc->depth_fmt, w, h, + sfc->msaa_samples); + sfc->buffer_mem[1] = w * h * 3; // Assume it's 24 bits + } + if (sfc->stencil_fmt) + { + _renderbuffer_allocate(sfc->stencil_buf, sfc->stencil_fmt, w, + h, sfc->msaa_samples); + sfc->buffer_mem[2] = w * h; // Assume it's 8 bits + } + } + + return 1; //ret; +} + +static int +_surface_buffers_destroy(EVGL_Engine *ee, EVGL_Surface *sfc) +{ + // Set the context current with resource context/surface + if (!_internal_resource_make_current(ee, NULL)) + { + ERR("Error doing an internal resource make current"); + return 0; + } + + if (sfc->color_buf) + _texture_destroy(&sfc->color_buf); + if (sfc->depth_buf) + _renderbuffer_destroy(&sfc->depth_buf); + if (sfc->stencil_buf) + _renderbuffer_destroy(&sfc->stencil_buf); + if (sfc->depth_stencil_buf) + { +#ifdef GL_GLES + _texture_destroy(&sfc->depth_stencil_buf); +#else + _renderbuffer_destroy(&sfc->depth_stencil_buf); #endif } @@ -1028,9 +1176,9 @@ _surface_buffers_create(EVGL_Engine *ee, EVGL_Surface *sfc) ERR("Error doing make_current(NULL, NULL)."); return 0; } - return ret; -} + return 1; +} static int _internal_config_set(EVGL_Engine *ee, EVGL_Surface *sfc, Evas_GL_Config *cfg) @@ -1208,6 +1356,7 @@ evgl_engine_create(EVGL_Interface *efunc, void *engine_data) int direct_off = 0, debug_mode = 0; char *s = NULL; + if (evgl_engine) return evgl_engine; // Initialize Log Domain @@ -1219,6 +1368,9 @@ evgl_engine_create(EVGL_Interface *efunc, void *engine_data) return NULL; } + // Store the Log Level + _evas_gl_log_level = eina_log_domain_level_get("EvasGL"); + // Check the validity of the efunc if ((!efunc) || (!efunc->surface_create) || @@ -1394,10 +1546,13 @@ evgl_surface_create(EVGL_Engine *ee, Evas_GL_Config *cfg, int w, int h) // Create internal buffers if (!_surface_buffers_create(ee, sfc)) { - ERR("Unable Create Specificed Surfaces. Unsupported format!"); + ERR("Unable Create Specificed Surfaces."); goto error; }; + // Keep track of all the created surfaces + ee->surfaces = eina_list_prepend(ee->surfaces, sfc); + return sfc; error: @@ -1440,34 +1595,15 @@ evgl_surface_destroy(EVGL_Engine *ee, EVGL_Surface *sfc) evgl_make_current(ee, NULL, NULL); } - // Set the context current with resource context/surface - if (!_internal_resource_make_current(ee, NULL)) + // Destroy created buffers + if (!_surface_buffers_destroy(ee, sfc)) { - ERR("Error doing an internal resource make current"); + ERR("Error deleting surface resources."); return 0; } - // Delete buffers - if (sfc->color_buf) - glDeleteTextures(1, &sfc->color_buf); - - if (sfc->depth_buf) - glDeleteRenderbuffers(1, &sfc->depth_buf); - - if (sfc->stencil_buf) - glDeleteRenderbuffers(1, &sfc->stencil_buf); - - if (sfc->depth_stencil_buf) - { -#ifdef GL_GLES - glDeleteTextures(1, &sfc->depth_stencil_buf); -#else - glDeleteRenderbuffers(1, &sfc->depth_stencil_buf); -#endif - } - - if (!ee->funcs->make_current(ee->engine_data, NULL, NULL, 0)) - ERR("Error doing make_current(NULL, NULL). Passing over the error..."); + // Remove it from the list + ee->surfaces = eina_list_remove(ee->surfaces, sfc); free(sfc); sfc = NULL; @@ -1509,6 +1645,9 @@ evgl_context_create(EVGL_Engine *ee, EVGL_Context *share_ctx) return NULL; } + // Keep track of all the created context + ee->contexts = eina_list_prepend(ee->contexts, ctx); + return ctx; } @@ -1548,6 +1687,9 @@ evgl_context_destroy(EVGL_Engine *ee, EVGL_Context *ctx) return 0; } + // Remove it from the list + ee->contexts = eina_list_remove(ee->contexts, ctx); + // Free context free(ctx); ctx = NULL; @@ -1592,6 +1734,34 @@ evgl_make_current(EVGL_Engine *ee, EVGL_Surface *sfc, EVGL_Context *ctx) } + // Allocate or free resources depending on what mode it's running. + if (_evgl_direct_renderable(ee, rsc, sfc)) + { + // Destroy created resources + if (sfc->buffers_allocated) + { + if (!_surface_buffers_allocate(ee, sfc, 0, 0)) + { + ERR("Unable to destroy surface buffers!"); + return 0; + }; + sfc->buffers_allocated = 0; + } + } + else + { + // Create internal buffers if not yet created + if (!sfc->buffers_allocated) + { + if (!_surface_buffers_allocate(ee, sfc, sfc->w, sfc->h)) + { + ERR("Unable Create Specificed Surfaces. Unsupported format!"); + return 0; + }; + sfc->buffers_allocated = 1; + } + } + // Do a make current if (!_internal_resource_make_current(ee, ctx)) { @@ -1637,6 +1807,8 @@ evgl_make_current(EVGL_Engine *ee, EVGL_Surface *sfc, EVGL_Context *ctx) ctx->current_sfc = sfc; rsc->current_ctx = ctx; + _surface_context_list_print(ee); + return 1; } diff --git a/src/modules/evas/engines/gl_common/evas_gl_core_private.h b/src/modules/evas/engines/gl_common/evas_gl_core_private.h index 491bd75349..77d4d07178 100755 --- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h +++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h @@ -100,6 +100,14 @@ struct _EVGL_Surface // Attached Context int fbo_attached; + + // Init Flag + int buffers_allocated; + + // Rough estimate of buffer in memory per renderbuffer + // 0. color 1. depth 2. stencil 3. depth_stencil + int buffer_mem[4]; + //-------------------------// EVGL_Context *current_ctx; @@ -119,7 +127,7 @@ struct _EVGL_Context // Direct Rendering Related int scissor_enabled; - int scissor_upated; + int scissor_updated; int scissor_coord[4]; int dr_scissor_coord[4]; int direct_scissor; @@ -237,7 +245,12 @@ struct _EVGL_Engine // Force Off fo Debug purposes int force_direct_off; + // Keep track of all the current surfaces/contexts + Eina_List *surfaces; + Eina_List *contexts; + void *engine_data; + };