sung pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=2b4a7b438def96d01a5c0bb85d2c9636773d333d
commit 2b4a7b438def96d01a5c0bb85d2c9636773d333d Author: Sung W. Park <sung...@gmail.com> Date: Sat Feb 15 02:33:47 2014 +0900 evas gl: added partial rendering support for qcom extension When running in direct rendering mode, properly support partial rendering if the extension is properly supported. Also, fixed the SwapBufferwWithDamage rectangle coordinate bug. It wasn't properly y-inverted before. --- src/modules/evas/engines/gl_common/evas_gl_api.c | 28 ++++- .../evas/engines/gl_common/evas_gl_common.h | 9 +- .../evas/engines/gl_common/evas_gl_context.c | 58 +++++++-- src/modules/evas/engines/gl_common/evas_gl_core.c | 132 +++++++++++++++++++-- src/modules/evas/engines/gl_common/evas_gl_core.h | 13 +- .../evas/engines/gl_common/evas_gl_core_private.h | 10 +- src/modules/evas/engines/gl_x11/evas_engine.c | 86 ++++++++++---- src/modules/evas/engines/wayland_egl/evas_engine.c | 14 ++- 8 files changed, 298 insertions(+), 52 deletions(-) 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 d831f9d..0555b4a 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api.c +++ b/src/modules/evas/engines/gl_common/evas_gl_api.c @@ -56,7 +56,9 @@ void _evgl_glBindFramebuffer(GLenum target, GLuint framebuffer) { EVGL_Context *ctx = NULL; + EVGL_Resource *rsc; + rsc = _evgl_tls_resource_get(); ctx = _evgl_current_context_get(); if (!ctx) @@ -69,13 +71,35 @@ _evgl_glBindFramebuffer(GLenum target, GLuint framebuffer) if (framebuffer==0) { if (_evgl_direct_enabled()) - glBindFramebuffer(target, 0); + { + glBindFramebuffer(target, 0); + + if (rsc->direct.partial.enabled) + { + if (!ctx->partial_render) + { + evgl_direct_partial_render_start(); + ctx->partial_render = 1; + } + } + } else - glBindFramebuffer(target, ctx->surface_fbo); + { + glBindFramebuffer(target, ctx->surface_fbo); + } ctx->current_fbo = 0; } else { + if (_evgl_direct_enabled()) + { + if (ctx->current_fbo == 0) + { + if (rsc->direct.partial.enabled) + evgl_direct_partial_render_end(); + } + } + glBindFramebuffer(target, framebuffer); // Save this for restore when doing make current diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 9e1579a..a6b624d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -531,6 +531,8 @@ struct _Evas_Engine_GL_Context void *egldisp; void *eglctxt; #endif + + GLuint preserve_bit; }; struct _Evas_GL_Texture_Pool @@ -692,7 +694,12 @@ void evas_gl_common_context_free(Evas_Engine_GL_Context *gc); void evas_gl_common_context_use(Evas_Engine_GL_Context *gc); void evas_gl_common_context_newframe(Evas_Engine_GL_Context *gc); void evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot); +void evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc, + int rot, int gw, int gh, + int cx, int cy, int cw, int ch, + int bitmask); void evas_gl_common_context_done(Evas_Engine_GL_Context *gc); +void evas_gl_common_tiling_done(Evas_Engine_GL_Context *gc); void evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc, Evas_GL_Image *surface); void evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc, @@ -818,7 +825,7 @@ void evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_P void evas_gl_common_line_draw(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int y2); -int evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* fname, int frame); +int evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* fname, int frame, const char* suffix); extern void (*glsym_glGenFramebuffers) (GLsizei a, GLuint *b); extern void (*glsym_glBindFramebuffer) (GLenum a, GLuint b); diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 5626ce4..2e447d9 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -158,7 +158,8 @@ gl_symbols(void) FINDSYM(glsym_glStartTiling, "glStartTilingQCOM", glsym_func_void); FINDSYM(glsym_glStartTiling, "glStartTiling", glsym_func_void); - + FINDSYM(glsym_glStartTiling, "glActivateTileQCOM", glsym_func_void); + FINDSYM(glsym_glEndTiling, "glEndTilingQCOM", glsym_func_void); FINDSYM(glsym_glEndTiling, "glEndTiling", glsym_func_void); @@ -1046,6 +1047,43 @@ evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot) } void +evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc EINA_UNUSED, + int rot, int gw, int gh, + int cx, int cy, int cw, int ch, + int bitmask) +{ + if (!glsym_glStartTiling) return; + switch (rot) + { + case 0: // UP this way: ^ + glsym_glStartTiling(cx, cy, cw, ch, bitmask); + break; + case 90: // UP this way: < + glsym_glStartTiling(gh - (cy + ch), cx, ch, cw, bitmask); + break; + case 180: // UP this way: v + glsym_glStartTiling(gw - (cx + cw), gh - (cy + ch), cw, ch, bitmask); + break; + case 270: // UP this way: > + glsym_glStartTiling(cy, gw - (cx + cw), ch, cw, bitmask); + break; + default: // assume up is up + glsym_glStartTiling(cx, cy, cw, ch, bitmask); + break; + } +} + +void +evas_gl_common_tiling_done(Evas_Engine_GL_Context *gc EINA_UNUSED) +{ + if (glsym_glEndTiling) + { + glsym_glEndTiling(GL_COLOR_BUFFER_BIT0_QCOM); + } +} + + +void evas_gl_common_context_done(Evas_Engine_GL_Context *gc) { if (gc->master_clip.used) @@ -2836,10 +2874,16 @@ shader_array_flush(Evas_Engine_GL_Context *gc) if (!gc->master_clip.used) { if (!fbo) - start_tiling(gc, gc->rot, gw, gh, - gc->master_clip.x, - gh - gc->master_clip.y - gc->master_clip.h, - gc->master_clip.w, gc->master_clip.h, 0); + { + start_tiling(gc, gc->rot, gw, gh, + gc->master_clip.x, + gh - gc->master_clip.y - gc->master_clip.h, + gc->master_clip.w, gc->master_clip.h, + gc->preserve_bit); + + if (!gc->preserve_bit) + gc->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM; + } else start_tiling(gc, 0, gw, gh, gc->master_clip.x, gc->master_clip.y, @@ -3195,14 +3239,14 @@ shader_array_flush(Evas_Engine_GL_Context *gc) } int -evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* buf_name, int frame) +evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* buf_name, int frame, const char *suffix) { RGBA_Image *im = NULL; DATA32 *data1, *data2; char fname[100]; int ok = 0; - sprintf(fname, "./%s/evas_win_%s-fc_%03d.png", dname, buf_name, frame); + sprintf(fname, "./%s/win_%s-fc_%03d_%s.png", dname, buf_name, frame, suffix); data1 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32)); data2 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32)); 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 c74754f..f8e7037 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.c +++ b/src/modules/evas/engines/gl_common/evas_gl_core.c @@ -1409,7 +1409,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h) { EVGL_Surface *sfc = NULL; char *s = NULL; - int direct_override = 0; + int direct_override = 0, direct_mem_opt = 0; // Check if engine is valid if (!evgl_engine) @@ -1441,6 +1441,16 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h) evgl_engine->direct_override = 1; } + // Check if Direct Rendering Memory Optimzation flag is on + // Creates resources on demand when it fallsback to fbo rendering + if (!evgl_engine->direct_mem_opt) + if ((s = getenv("EVAS_GL_DIRECT_MEM_OPT"))) + { + direct_mem_opt = atoi(s); + if (direct_mem_opt == 1) + evgl_engine->direct_mem_opt = 1; + } + // Allocate surface structure sfc = calloc(1, sizeof(EVGL_Surface)); if (!sfc) @@ -1672,6 +1682,12 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) // Unset if ((!sfc) && (!ctx)) { + if (rsc->current_ctx) + { + if (rsc->direct.partial.enabled) + evgl_direct_partial_render_end(); + } + if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0)) { ERR("Error doing make_current(NULL, NULL)."); @@ -1687,6 +1703,12 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) return 1; } + // Disable partial rendering for previous context + if ((rsc->current_ctx) && (rsc->current_ctx != ctx)) + { + evas_gl_common_tiling_done(NULL); + rsc->current_ctx->partial_render = 0; + } // Allocate or free resources depending on what mode (direct of fbo) it's // running only if the env var EVAS_GL_DIRECT_MEM_OPT is set. @@ -1707,15 +1729,22 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) } else { - // Create internal buffers if not yet created - if (!sfc->buffers_allocated) + if (evgl_engine->direct_override) + { + DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!"); + } + else { - if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1)) + // Create internal buffers if not yet created + if (!sfc->buffers_allocated) { - ERR("Unable Create Specificed Surfaces. Unsupported format!"); - return 0; + if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1)) + { + ERR("Unable Create Specificed Surfaces. Unsupported format!"); + return 0; + }; + sfc->buffers_allocated = 1; } - sfc->buffers_allocated = 1; } } } @@ -1742,6 +1771,20 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) glBindFramebuffer(GL_FRAMEBUFFER, 0); ctx->current_fbo = 0; } + + if (ctx->current_fbo == 0) + { + // If master clip is set and clip is greater than 0, do partial render + if (rsc->direct.partial.enabled) + { + if (!ctx->partial_render) + { + evgl_direct_partial_render_start(); + ctx->partial_render = 1; + } + } + } + rsc->direct.rendered = 1; } else @@ -1749,10 +1792,22 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) // Attach fbo and the buffers if (ctx->current_sfc != sfc) { - if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo)) + if ((evgl_engine->direct_mem_opt) && (evgl_engine->direct_override)) { - ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo); - return 0; + DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!"); + } + else + { + // If it's transitioning from direct render to fbo render + // Call end tiling + if (rsc->direct.partial.enabled) + evgl_direct_partial_render_end(); + + if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo)) + { + ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo); + return 0; + } } // Bind to the previously bound buffer @@ -1879,6 +1934,28 @@ evgl_api_get() return &gl_funcs; } + +void +evgl_direct_partial_info_set(int pres) +{ + EVGL_Resource *rsc; + + if (!(rsc=_evgl_tls_resource_get())) return; + + rsc->direct.partial.enabled = EINA_TRUE; + rsc->direct.partial.preserve = pres; +} + +void +evgl_direct_partial_info_clear() +{ + EVGL_Resource *rsc; + + if (!(rsc=_evgl_tls_resource_get())) return; + + rsc->direct.partial.enabled = EINA_FALSE; +} + void evgl_direct_override_get(int *override, int *force_off) { @@ -1886,6 +1963,41 @@ evgl_direct_override_get(int *override, int *force_off) *force_off = evgl_engine->direct_force_off; } +void +evgl_direct_partial_render_start() +{ + EVGL_Resource *rsc; + + if (!(rsc=_evgl_tls_resource_get())) return; + + evas_gl_common_tiling_start(NULL, + rsc->direct.rot, + rsc->direct.win_w, + rsc->direct.win_h, + rsc->direct.clip.x, + rsc->direct.win_h - rsc->direct.clip.y - rsc->direct.clip.h, + rsc->direct.clip.w, + rsc->direct.clip.h, + rsc->direct.partial.preserve); + + if (!rsc->direct.partial.preserve) + rsc->direct.partial.preserve = GL_COLOR_BUFFER_BIT0_QCOM; +} + +void +evgl_direct_partial_render_end() +{ + EVGL_Context *ctx; + ctx = _evgl_current_context_get(); + + if (!ctx) return; + + if (ctx->partial_render) + { + evas_gl_common_tiling_done(NULL); + ctx->partial_render = 0; + } +} //-----------------------------------------------------// diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.h b/src/modules/evas/engines/gl_common/evas_gl_core.h index 587e8b0..9ff5c06 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.h +++ b/src/modules/evas/engines/gl_common/evas_gl_core.h @@ -31,11 +31,16 @@ const char *evgl_string_query(int name); void *evgl_proc_address_get(const char *name); int evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns); Evas_GL_API *evgl_api_get(); -int evgl_direct_rendered(); - -void evgl_direct_info_set(int win_w, int win_h, int rot, int img_x, int img_y, int img_w, int img_h, int clip_x, int clip_y, int clip_w, int clip_h); -void evgl_direct_info_clear(); +int evgl_direct_rendered(); void evgl_direct_override_get(int *override, int *force_off); +void evgl_direct_info_set(int win_w, int win_h, int rot, + int img_x, int img_y, int img_w, int img_h, + int clip_x, int clip_y, int clip_w, int clip_h); +void evgl_direct_info_clear(); +void evgl_direct_partial_info_set(int pres); +void evgl_direct_partial_info_clear(); +void evgl_direct_partial_render_start(); +void evgl_direct_partial_render_end(); #endif //_EVAS_GL_CORE_H 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 85ccf9e..fce0fab 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h +++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h @@ -134,6 +134,9 @@ struct _EVGL_Context int viewport_updated; int viewport_coord[4]; + // Partial Rendering + int partial_render; + EVGL_Surface *current_sfc; }; @@ -225,9 +228,14 @@ struct _EVGL_Resource int x, y, w, h; } clip; - Eina_Bool enabled : 1; + struct { + int preserve; + Eina_Bool enabled : 1; + } partial; + Eina_Bool enabled : 1; } direct; + }; struct _EVGL_Engine diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c index d4185cd..d899ad9 100644 --- a/src/modules/evas/engines/gl_x11/evas_engine.c +++ b/src/modules/evas/engines/gl_x11/evas_engine.c @@ -1414,6 +1414,8 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i rect = (Tilebuf_Rect *)re->cur_rect; if (re->rects) { + re->win->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM; + switch (re->mode) { case MODE_COPY: @@ -1574,13 +1576,15 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode) if (swap_buffer_debug) { char fname[100]; + char suffix[100]; int ret = 0; snprintf(fname, sizeof(fname), "%p", (void*)re->win); ret = evas_gl_common_buffer_dump(re->win->gl_context, (const char*)dname, (const char*)fname, - re->frame_cnt); + re->frame_cnt, + suffix); if (!ret) swap_buffer_debug_mode = 0; } } @@ -1616,31 +1620,31 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode) { case 0: rects[i + 0] = r->x; - rects[i + 1] = gh - r->y; + rects[i + 1] = gh - (r->y + r->h); rects[i + 2] = r->w; rects[i + 3] = r->h; break; case 90: rects[i + 0] = r->y; - rects[i + 1] = gw - (gw - (r->x + r->w)); + rects[i + 1] = r->x; rects[i + 2] = r->h; rects[i + 3] = r->w; break; case 180: rects[i + 0] = gw - (r->x + r->w); - rects[i + 1] = gh - (gh - (r->y + r->h)); + rects[i + 1] = r->y; rects[i + 2] = r->w; rects[i + 3] = r->h; break; case 270: rects[i + 0] = gh - (r->y + r->h); - rects[i + 1] = gw - r->x; + rects[i + 1] = gw - (r->x + r->w); rects[i + 2] = r->h; rects[i + 3] = r->w; break; default: rects[i + 0] = r->x; - rects[i + 1] = gh - r->y; + rects[i + 1] = gh - (r->y + r->h); rects[i + 2] = r->w; rects[i + 3] = r->h; break; @@ -3007,21 +3011,42 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, re->win->gl_context->dc = context; - // Set necessary info for direct rendering - evgl_direct_info_set(re->win->gl_context->w, - re->win->gl_context->h, - re->win->gl_context->rot, - dst_x, dst_y, dst_w, dst_h, - re->win->gl_context->dc->clip.x, - re->win->gl_context->dc->clip.y, - re->win->gl_context->dc->clip.w, - re->win->gl_context->dc->clip.h); + if (re->func.get_pixels) + { + if ((re->win->gl_context->master_clip.enabled) && + (re->win->gl_context->master_clip.w > 0) && + (re->win->gl_context->master_clip.h > 0)) + { + // Pass the preserve flag info the evas_gl + evgl_direct_partial_info_set(re->win->gl_context->preserve_bit); + } - // Call pixel get function - re->func.get_pixels(re->func.get_pixels_data, re->func.obj); + // Set necessary info for direct rendering + evgl_direct_info_set(re->win->gl_context->w, + re->win->gl_context->h, + re->win->gl_context->rot, + dst_x, dst_y, dst_w, dst_h, + re->win->gl_context->dc->clip.x, + re->win->gl_context->dc->clip.y, + re->win->gl_context->dc->clip.w, + re->win->gl_context->dc->clip.h); + + // Call pixel get function + re->func.get_pixels(re->func.get_pixels_data, re->func.obj); + + // Call end tile if it's being used + if ((re->win->gl_context->master_clip.enabled) && + (re->win->gl_context->master_clip.w > 0) && + (re->win->gl_context->master_clip.h > 0)) + { + evgl_direct_partial_render_end(); + evgl_direct_partial_info_clear(); + re->win->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM; + } - // Clear direct rendering info - evgl_direct_info_clear(); + // Reset direct rendering info + evgl_direct_info_clear(); + } } else { @@ -3278,10 +3303,23 @@ eng_gl_context_destroy(void *data, void *context) static int eng_gl_make_current(void *data, void *surface, void *context) { + Render_Engine *re = (Render_Engine *)data; EVGL_Surface *sfc = (EVGL_Surface *)surface; EVGL_Context *ctx = (EVGL_Context *)context; EVGLINIT(data, 0); + if ((sfc) && (ctx)) + { + if ((re->win->gl_context->havestuff) || + (re->win->gl_context->master_clip.used)) + { + eng_window_use(re->win); + evas_gl_common_context_flush(re->win->gl_context); + if (re->win->gl_context->master_clip.used) + evas_gl_common_context_done(re->win->gl_context); + } + } + return evgl_make_current(data, sfc, ctx); } @@ -3544,8 +3582,14 @@ eng_context_flush(void *data) Render_Engine *re; re = (Render_Engine *)data; - eng_window_use(re->win); - evas_gl_common_context_flush(re->win->gl_context); + if ((re->win->gl_context->havestuff) || + (re->win->gl_context->master_clip.used)) + { + eng_window_use(re->win); + evas_gl_common_context_flush(re->win->gl_context); + if (re->win->gl_context->master_clip.used) + evas_gl_common_context_done(re->win->gl_context); + } } static int diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index ea6c7d3..2de0276 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -1231,13 +1231,15 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode) if (swap_buffer_debug) { char fname[100]; + char suffix[100]; int ret = 0; sprintf(fname, "%p", (void*)re->win); ret = evas_gl_common_buffer_dump(re->win->gl_context, (const char*)dname, (const char*)fname, - re->frame_cnt); + re->frame_cnt, + suffix); if (!ret) swap_buffer_debug_mode = 0; } } @@ -1272,31 +1274,31 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode) { case 0: rects[i + 0] = r->x; - rects[i + 1] = gh - r->y; + rects[i + 1] = gh - (r->y + r->h); rects[i + 2] = r->w; rects[i + 3] = r->h; break; case 90: rects[i + 0] = r->y; - rects[i + 1] = gw - (gw - (r->x + r->w)); + rects[i + 1] = r->x; rects[i + 2] = r->h; rects[i + 3] = r->w; break; case 180: rects[i + 0] = gw - (r->x + r->w); - rects[i + 1] = gh - (gh - (r->y + r->h)); + rects[i + 1] = r->y; rects[i + 2] = r->w; rects[i + 3] = r->h; break; case 270: rects[i + 0] = gh - (r->y + r->h); - rects[i + 1] = gw - r->x; + rects[i + 1] = gw - (r->x + r->w); rects[i + 2] = r->h; rects[i + 3] = r->w; break; default: rects[i + 0] = r->x; - rects[i + 1] = gh - r->y; + rects[i + 1] = gh - (r->y + r->h); rects[i + 2] = r->w; rects[i + 3] = r->h; break; --