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.
This commit is contained in:
Sung W. Park 2014-02-15 02:33:47 +09:00
parent 1fae9e5e21
commit 2b4a7b438d
8 changed files with 298 additions and 52 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);
@ -1045,6 +1046,43 @@ evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot)
if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc);
}
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)
{
@ -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));

View File

@ -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)
{
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1))
DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
}
else
{
// 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;
}
}
//-----------------------------------------------------//

View File

@ -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);
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_override_get(int *override, int *force_off);
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

View File

@ -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

View File

@ -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);
// Clear direct rendering info
evgl_direct_info_clear();
// 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;
}
// 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

View File

@ -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;