From 8e6f0aa11c11609682039b02b8b9e84f6c240fec Mon Sep 17 00:00:00 2001 From: "Sung W. Park" Date: Mon, 17 Jun 2013 17:53:33 +0900 Subject: [PATCH] Evas: add partial rendering support for evasgl direct rendering Evas_GL Direct rendering is an optimization path that renders directly to the window if conditions are met. Because evas gl backend used to re-render the entire screen, evas_gl direct rendering didin't have to concern with partial region rendering. Now that partial rendering/swapping has been applied to evas gl- backend, evas_gl direct rendering also had to take into account clip regions. in order to properly apply it, some adjustments were made to the engine functions and etc. --- ChangeLog | 4 + NEWS | 1 + src/lib/evas/canvas/evas_object_image.c | 91 +++++--- src/lib/evas/include/evas_private.h | 3 +- .../evas/engines/gl_common/evas_gl_api.c | 206 ++++++++++++++---- .../evas/engines/gl_common/evas_gl_core.c | 61 ++++-- .../evas/engines/gl_common/evas_gl_core.h | 4 +- .../engines/gl_common/evas_gl_core_private.h | 32 +-- src/modules/evas/engines/gl_x11/evas_engine.c | 49 ++++- .../engines/software_generic/evas_engine.c | 3 +- .../evas/engines/wayland_egl/evas_engine.c | 53 ++++- 11 files changed, 386 insertions(+), 121 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a50b67f60..278d62e3bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-06-17 Sung W. Park (sung_) + + * Evas: add partial rendering support for Evas_GL direct rendering + 2013-06-17 Cedric Bail * Edje: Use Eo array of callbacks to reduce edje memory foot print. diff --git a/NEWS b/NEWS index 2cad3edeba..0451613c31 100644 --- a/NEWS +++ b/NEWS @@ -332,4 +332,5 @@ Fixes: * Evas: improve stability of Evas_Cserve2. * Evas: Fix gif cannot decode alpha value correctly. * Evas: Fix bs if app call image object update add after call api like fileset. + * Evas: Fix evas_gl direct rendering to support partial redraw. diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 7ef73d5401..bced46c22d 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -125,6 +125,7 @@ struct _Evas_Object_Image Eina_Bool proxyerror : 1; Eina_Bool proxy_src_clip : 1; Eina_Bool written : 1; + Eina_Bool direct_render : 1; }; /* private methods for image objects */ @@ -3822,47 +3823,89 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v o->proxyrendering = EINA_FALSE; } + // Clear out the pixel get stuff.. + if (obj->layer->evas->engine.func->gl_get_pixels_set) + { + obj->layer->evas->engine.func->gl_get_pixels_set(output, NULL, NULL, NULL); + } + if (pixels) { Evas_Coord idw, idh, idx, idy; int ix, iy, iw, ih; - int img_set = 0; + int direct_override = 0; + int direct_force_off = 0; if (o->dirty_pixels) { if (o->pixels->func.get_pixels) { - if (obj->layer->evas->engine.func->context_flush) - obj->layer->evas->engine.func->context_flush(output); - // 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->map->cur.map) ) + if (obj->layer->evas->engine.func->image_native_get) { - if (obj->layer->evas->engine.func->gl_img_obj_set) + Evas_Native_Surface *ns; + ns = obj->layer->evas->engine.func->image_native_get(obj->layer->evas->engine.data.output, o->engine_data); + if ( (ns) && + (ns->type == EVAS_NATIVE_SURFACE_OPENGL) && + (ns->data.opengl.texture_id) && + (!ns->data.opengl.framebuffer_id) ) { - obj->layer->evas->engine.func->gl_img_obj_set(output, eo_obj, o->cur->has_alpha); - img_set = 1; + + // Check if we can do direct rendering... + if (obj->layer->evas->engine.func->gl_direct_override_get) + obj->layer->evas->engine.func->gl_direct_override_get(output, &direct_override, &direct_force_off); + 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->map->cur.map) && + (!o->cur->has_alpha)) || + (direct_override)) && + (!direct_force_off) ) + { + + if (obj->layer->evas->engine.func->gl_get_pixels_set) + { + obj->layer->evas->engine.func->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj); + } + + o->direct_render = EINA_TRUE; + } + else + o->direct_render = EINA_FALSE; + + } + + if ( (ns) && + (ns->type == EVAS_NATIVE_SURFACE_X11)) + { + if (obj->layer->evas->engine.func->context_flush) + obj->layer->evas->engine.func->context_flush(output); } } - o->pixels->func.get_pixels(o->pixels->func.get_pixels_data, eo_obj); + if (!o->direct_render) + o->pixels->func.get_pixels(o->pixels->func.get_pixels_data, eo_obj); + if (o->engine_data != pixels) - pixels = o->engine_data; + pixels = o->engine_data; o->engine_data = obj->layer->evas->engine.func->image_dirty_region (obj->layer->evas->engine.data.output, o->engine_data, 0, 0, o->cur->image.w, o->cur->image.h); } o->dirty_pixels = EINA_FALSE; } + else + { + // Check if the it's not dirty but it has direct rendering + if (o->direct_render) + { + obj->layer->evas->engine.func->gl_get_pixels_set(output, o->pixels->func.get_pixels, o->pixels->func.get_pixels_data, eo_obj); + } + } + if ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && (obj->map->cur.usemap)) { evas_object_map_update(eo_obj, x, y, imagew, imageh, uvw, uvh); @@ -4101,16 +4144,6 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v 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/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 0fa07c2c78..b2f2948810 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -877,7 +877,8 @@ 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); + void (*gl_direct_override_get) (void *data, int *override, int *force_off); + void (*gl_get_pixels_set) (void *data, void *get_pixels, void *get_pixels_data, void *obj); 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/evas/engines/gl_common/evas_gl_api.c b/src/modules/evas/engines/gl_common/evas_gl_api.c index a8cbc42ab8..968f7e10b3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api.c +++ b/src/modules/evas/engines/gl_common/evas_gl_api.c @@ -153,21 +153,51 @@ _evgl_glReleaseShaderCompiler(void) // Calls related to Evas GL Direct Rendering //-------------------------------------------------------------// // 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 +// returns: imgc[4] (oc[4]) original image object dimension in gl coord +// returns: objc[4] (nc[4]) tranformed (x, y, width, heigth) in gl coord +// returns: cc[4] cliped coordinate in original coordinate static void -compute_gl_coordinates(Evas_Object *obj, int rot, int clip, +compute_gl_coordinates(Evas_Object *obj, int rot, int clip_image, int x, int y, int width, int height, - int imgc[4], int objc[4]) + int clip[4], + int imgc[4], int objc[4], int cc[4]) { Evas_Object_Protected_Data *pd = eo_data_scope_get(obj, EVAS_OBJ_CLASS); + + int obj_x, obj_y, obj_w, obj_h; + int clip_x, clip_y, clip_w, clip_h; + int out_w, out_h; + + // Original Coordinates + obj_x = pd->cur->geometry.x; + obj_y = pd->cur->geometry.y; + obj_w = pd->cur->geometry.w; + obj_h = pd->cur->geometry.h; + + // Clip Region + clip_x = clip[0]; + clip_y = clip[1]; + clip_w = clip[2]; + clip_h = clip[3]; + + // Output Window Size + out_w = pd->layer->evas->output.w; + out_h = pd->layer->evas->output.h; + + if (rot == 0) { // oringinal image object coordinate in gl coordinate - imgc[0] = pd->cur->geometry.x; - imgc[1] = pd->layer->evas->output.h - pd->cur->geometry.y - pd->cur->geometry.h; - imgc[2] = imgc[0] + pd->cur->geometry.w; - imgc[3] = imgc[1] + pd->cur->geometry.h; + imgc[0] = obj_x; + imgc[1] = out_h - obj_y - obj_h; + imgc[2] = imgc[0] + obj_w; + imgc[3] = imgc[1] + obj_h; + + // clip coordinates in gl coordinate + cc[0] = clip_x; + cc[1] = out_h - clip_y - clip_h; + cc[2] = cc[0] + clip_w; + cc[3] = cc[1] + clip_h; // transformed (x,y,width,height) in gl coordinate objc[0] = imgc[0] + x; @@ -178,14 +208,20 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip, else if (rot == 180) { // oringinal image object coordinate in gl coordinate - imgc[0] = pd->layer->evas->output.w - pd->cur->geometry.x - pd->cur->geometry.w; - imgc[1] = pd->cur->geometry.y; - imgc[2] = imgc[0] + pd->cur->geometry.w; - imgc[3] = imgc[1] + pd->cur->geometry.h; + imgc[0] = out_w - obj_x - obj_w; + imgc[1] = obj_y; + imgc[2] = imgc[0] + obj_w; + imgc[3] = imgc[1] + obj_h; + + // clip coordinates in gl coordinate + cc[0] = out_w - clip_x - clip_w; + cc[1] = clip_y; + cc[2] = cc[0] + clip_w; + cc[3] = cc[1] + clip_h; // transformed (x,y,width,height) in gl coordinate - objc[0] = imgc[0] + pd->cur->geometry.w - x - width; - objc[1] = imgc[1] + pd->cur->geometry.h - y - height; + objc[0] = imgc[0] + obj_w - x - width; + objc[1] = imgc[1] + obj_h - y - height; objc[2] = objc[0] + width; objc[3] = objc[1] + height; @@ -193,13 +229,19 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip, else if (rot == 90) { // oringinal image object coordinate in gl coordinate - imgc[0] = pd->cur->geometry.y; - imgc[1] = pd->cur->geometry.x; - imgc[2] = imgc[0] + pd->cur->geometry.h; - imgc[3] = imgc[1] + pd->cur->geometry.w; + imgc[0] = obj_y; + imgc[1] = obj_x; + imgc[2] = imgc[0] + obj_h; + imgc[3] = imgc[1] + obj_w; + + // clip coordinates in gl coordinate + cc[0] = clip_y; + cc[1] = clip_x; + cc[2] = cc[0] + clip_h; + cc[3] = cc[1] + clip_w; // transformed (x,y,width,height) in gl coordinate - objc[0] = imgc[0] + pd->cur->geometry.h - y - height; + objc[0] = imgc[0] + obj_h - y - height; objc[1] = imgc[1] + x; objc[2] = objc[0] + height; objc[3] = objc[1] + width; @@ -207,14 +249,20 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip, else if (rot == 270) { // oringinal image object coordinate in gl coordinate - imgc[0] = pd->layer->evas->output.h - pd->cur->geometry.y - pd->cur->geometry.h; - imgc[1] = pd->layer->evas->output.w - pd->cur->geometry.x - pd->cur->geometry.w; - imgc[2] = imgc[0] + pd->cur->geometry.h; - imgc[3] = imgc[1] + pd->cur->geometry.w; + imgc[0] = out_h - obj_y - obj_h; + imgc[1] = out_w - obj_x - obj_w; + imgc[2] = imgc[0] + obj_h; + imgc[3] = imgc[1] + obj_w; + + // clip coordinates in gl coordinate + cc[0] = out_h - clip_y - clip_h; + cc[1] = out_w - clip_x - clip_w; + cc[2] = cc[0] + clip_h; + cc[3] = cc[1] + clip_w; // transformed (x,y,width,height) in gl coordinate objc[0] = imgc[0] + y; - objc[1] = imgc[1] + pd->cur->geometry.w - x - width; + objc[1] = imgc[1] + obj_w - x - width; objc[2] = objc[0] + height; objc[3] = objc[1] + width; } @@ -224,7 +272,7 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip, return; } - if (clip) + if (clip_image) { // Clip against original image object if (objc[0] < imgc[0]) objc[0] = imgc[0]; @@ -245,6 +293,11 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip, objc[2] = objc[2]-objc[0]; // width objc[3] = objc[3]-objc[1]; // height + + cc[2] = cc[2]-cc[0]; // width + cc[3] = cc[3]-cc[1]; // height + + //DBG( "\e[1;32m Img[%d %d %d %d] Original [%d %d %d %d] Transformed[%d %d %d %d] Clip[%d %d %d %d] Clipped[%d %d %d %d] \e[m", obj_x, obj_y, obj_w, obj_h, imgc[0], imgc[1], imgc[2], imgc[3], objc[0], objc[1], objc[2], objc[3], clip[0], clip[1], clip[2], clip[3], cc[0], cc[1], cc[2], cc[3]); } static void @@ -255,6 +308,7 @@ _evgl_glClear(GLbitfield mask) Evas_Object *img; int rot = 0; int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0}; + int cc[4] = {0,0,0,0}; if (!(rsc=_evgl_tls_resource_get())) { @@ -288,16 +342,33 @@ _evgl_glClear(GLbitfield mask) img = rsc->direct_img_obj; rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); - compute_gl_coordinates(img, rot, 0, 0, 0, 0, 0, oc, nc); - 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]); + compute_gl_coordinates(img, rot, 1, + ctx->scissor_coord[0], + ctx->scissor_coord[1], + ctx->scissor_coord[2], + ctx->scissor_coord[3], + rsc->clip, oc, nc, cc); + + if (rsc->master_clip) + { + RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]); + glScissor(nc[0], nc[1], nc[2], nc[3]); + } + else + glScissor(nc[0], nc[1], nc[2], nc[3]); ctx->direct_scissor = 0; } else - glScissor(oc[0], oc[1], oc[2], oc[3]); + { + compute_gl_coordinates(img, rot, 0, 0, 0, 0, 0, rsc->clip, oc, nc, cc); + + if (rsc->master_clip) + glScissor(cc[0], cc[1], cc[2], cc[3]); + else + glScissor(oc[0], oc[1], oc[2], oc[3]); + } glClear(mask); } @@ -422,6 +493,7 @@ _evgl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum forma Evas_Object *img; int rot = 0; int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0}; + int cc[4] = {0,0,0,0}; if (!(rsc=_evgl_tls_resource_get())) @@ -451,7 +523,7 @@ _evgl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum forma img = rsc->direct_img_obj; rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); - compute_gl_coordinates(img, rot, 1, x, y, width, height, oc, nc); + compute_gl_coordinates(img, rot, 1, x, y, width, height, rsc->clip, oc, nc, cc); glReadPixels(nc[0], nc[1], nc[2], nc[3], format, type, pixels); } else @@ -473,6 +545,7 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) Evas_Object *img; int rot = 0; int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0}; + int cc[4] = {0,0,0,0}; if (!(rsc=_evgl_tls_resource_get())) { @@ -504,9 +577,8 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) img = rsc->direct_img_obj; rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); - - compute_gl_coordinates(img, rot, 1, x, y, width, height, oc, nc); - glScissor(nc[0], nc[1], nc[2], nc[3]); + + compute_gl_coordinates(img, rot, 1, x, y, width, height, rsc->clip, oc, nc, cc); // Keep a copy of the original coordinates ctx->scissor_coord[0] = x; @@ -514,11 +586,13 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) ctx->scissor_coord[2] = width; ctx->scissor_coord[3] = height; - // Update direct rendering coordinates - ctx->dr_scissor_coord[0] = nc[0]; - ctx->dr_scissor_coord[1] = nc[1]; - ctx->dr_scissor_coord[2] = nc[2]; - ctx->dr_scissor_coord[3] = nc[3]; + if (rsc->master_clip) + { + RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]); + glScissor(nc[0], nc[1], nc[2], nc[3]); + } + else + glScissor(nc[0], nc[1], nc[2], nc[3]); ctx->direct_scissor = 0; @@ -558,6 +632,7 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) Evas_Object *img; int rot = 0; int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0}; + int cc[4] = {0,0,0,0}; if (!(rsc=_evgl_tls_resource_get())) { @@ -591,18 +666,40 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) img = rsc->direct_img_obj; rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); - compute_gl_coordinates(img, rot, 0, x, y, width, height, oc, nc); - 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]); + // Recompute the scissor coordinates + compute_gl_coordinates(img, rot, 1, + ctx->scissor_coord[0], + ctx->scissor_coord[1], + ctx->scissor_coord[2], + ctx->scissor_coord[3], + rsc->clip, oc, nc, cc); + + if (rsc->master_clip) + { + RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]); + glScissor(nc[0], nc[1], nc[2], nc[3]); + } + else + glScissor(nc[0], nc[1], nc[2], nc[3]); + ctx->direct_scissor = 0; + + // Compute the viewport coordinate + compute_gl_coordinates(img, rot, 0, x, y, width, height, rsc->clip, oc, nc, cc); + glViewport(nc[0], nc[1], nc[2], nc[3]); } else - glScissor(oc[0], oc[1], oc[2], oc[3]); + { + compute_gl_coordinates(img, rot, 0, x, y, width, height, rsc->clip, oc, nc, cc); + if (rsc->master_clip) + glScissor(cc[0], cc[1], cc[2], cc[3]); + else + glScissor(oc[0], oc[1], oc[2], oc[3]); - glViewport(nc[0], nc[1], nc[2], nc[3]); + glViewport(nc[0], nc[1], nc[2], nc[3]); + } // Keep a copy of the original coordinates ctx->viewport_coord[0] = x; @@ -2433,6 +2530,22 @@ _normal_gl_api_get(Evas_GL_API *funcs) evgl_api_ext_get(funcs); } +static void +_direct_scissor_off_api_get(Evas_GL_API *funcs) +{ + +#define ORD(f) EVAS_API_OVERRIDE(f, funcs,) + // For Direct Rendering + ORD(glClear); + ORD(glDisable); + ORD(glEnable); + ORD(glGetIntegerv); + ORD(glReadPixels); + ORD(glScissor); + ORD(glViewport); +#undef ORD +} + static void _debug_gl_api_get(Evas_GL_API *funcs) @@ -2596,4 +2709,7 @@ _evgl_api_get(Evas_GL_API *funcs, int debug) _debug_gl_api_get(funcs); else _normal_gl_api_get(funcs); + + if (evgl_engine->direct_scissor_off) + _direct_scissor_off_api_get(funcs); } 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 be6a4daa22..5145e0dfc8 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.c +++ b/src/modules/evas/engines/gl_common/evas_gl_core.c @@ -448,7 +448,7 @@ _surface_cap_check() ERR("EVGL Engine not initialized!"); return 0; } - + // Check Surface Cap for MSAA if (evgl_engine->caps.msaa_supported) { @@ -507,7 +507,7 @@ _surface_cap_load(Eet_File *ef) free(data); data = NULL; - // !!!FIXME + // !!!FIXME // Should use eet functionality instead of just reading using sscanfs... for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i) { @@ -544,7 +544,7 @@ _surface_cap_save(Eet_File *ef) if (eet_write(ef, "num_fbo_fmts", data, strlen(data) + 1, 1) < 0) return 0; - // !!!FIXME + // !!!FIXME // Should use eet functionality instead of just writing out using snprintfs... for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i) { @@ -831,7 +831,7 @@ _surface_context_list_print() 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]) + 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]); @@ -1247,10 +1247,10 @@ _evgl_not_in_pixel_get() EVGL_Context *ctx = rsc->current_ctx; - if ((!evgl_engine->direct_force_off) && + if ((!evgl_engine->direct_force_off) && (rsc->id == evgl_engine->main_tid) && - (ctx) && - (ctx->current_sfc) && + (ctx) && + (ctx->current_sfc) && (ctx->current_sfc->direct_fb_opt) && (!rsc->direct_img_obj)) return 1; @@ -1285,14 +1285,14 @@ _evgl_direct_enabled() EVGL_Engine * evgl_engine_init(void *eng_data, EVGL_Interface *efunc) { - int direct_mem_opt = 0, direct_off = 0, debug_mode = 0; + int direct_mem_opt = 0, direct_off = 0, direct_soff = 0, debug_mode = 0; char *s = NULL; if (evgl_engine) return evgl_engine; // Initialize Log Domain if (_evas_gl_log_dom < 0) - _evas_gl_log_dom = eina_log_domain_register("EvasGL", EVAS_DEFAULT_LOG_COLOR); + _evas_gl_log_dom = eina_log_domain_register("EvasGL", EVAS_DEFAULT_LOG_COLOR); if (_evas_gl_log_dom < 0) { EINA_LOG_ERR("Can not create a module log domain."); @@ -1333,9 +1333,9 @@ evgl_engine_init(void *eng_data, EVGL_Interface *efunc) // Initialize Extensions if (efunc->proc_address_get && efunc->ext_string_get) - evgl_api_ext_init(efunc->proc_address_get, efunc->ext_string_get(eng_data)); + evgl_api_ext_init(efunc->proc_address_get, efunc->ext_string_get(eng_data)); else - ERR("Proc address get function not available. Extension not initialized."); + ERR("Proc address get function not available. Extension not initialized."); DBG("GLUE Extension String: %s", efunc->ext_string_get(eng_data)); DBG("GL Extension String: %s", glGetString(GL_EXTENSIONS)); @@ -1352,19 +1352,25 @@ evgl_engine_init(void *eng_data, EVGL_Interface *efunc) s = getenv("EVAS_GL_DIRECT_MEM_OPT"); if (s) direct_mem_opt = atoi(s); if (direct_mem_opt == 1) - evgl_engine->direct_mem_opt = 1; + evgl_engine->direct_mem_opt = 1; // Check if Direct Rendering Override Force Off flag is on s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF"); if (s) direct_off = atoi(s); if (direct_off == 1) - evgl_engine->direct_force_off = 1; + evgl_engine->direct_force_off = 1; + + // Check if Direct Rendering Override Force Off flag is on + s = getenv("EVAS_GL_DIRECT_SCISSOR_OFF"); + if (s) direct_soff = atoi(s); + if (direct_soff == 1) + evgl_engine->direct_scissor_off = 1; // Check if API Debug mode is on s = getenv("EVAS_GL_API_DEBUG"); if (s) debug_mode = atoi(s); if (debug_mode == 1) - evgl_engine->api_debug_mode = 1; + evgl_engine->api_debug_mode = 1; // Maint Thread ID (get tid not available in eina thread yet) evgl_engine->main_tid = 0; @@ -1825,7 +1831,7 @@ evgl_direct_rendered() } void -evgl_direct_img_obj_set(Evas_Object *img, int alpha, int rot) +evgl_direct_img_obj_set(Evas_Object *img, int rot) { EVGL_Resource *rsc; @@ -1833,7 +1839,7 @@ evgl_direct_img_obj_set(Evas_Object *img, int alpha, int rot) // Normally direct rendering isn't allowed if alpha is on and // rotation is not 0. BUT, if override is on, allow it. - if ((alpha) || (rot!=0)) + if (rot!=0) { if (evgl_engine->direct_override) rsc->direct_img_obj = img; @@ -1862,6 +1868,29 @@ evgl_api_get() return &gl_funcs; } + +void +evgl_direct_img_clip_set(int c, int x, int y, int w, int h) +{ + EVGL_Resource *rsc; + + if (!(rsc=_evgl_tls_resource_get())) return; + + rsc->master_clip = c; + rsc->clip[0] = x; + rsc->clip[1] = y; + rsc->clip[2] = w; + rsc->clip[3] = h; + +} + +void +evgl_direct_override_get(int *override, int *force_off) +{ + *override = evgl_engine->direct_override; + *force_off = evgl_engine->direct_force_off; +} + //-----------------------------------------------------// 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 71d557aed4..edcb52c3d6 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.h +++ b/src/modules/evas/engines/gl_common/evas_gl_core.h @@ -32,8 +32,10 @@ extern void *evgl_proc_address_get(const char *name); extern int evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns); extern Evas_GL_API *evgl_api_get(); extern int evgl_direct_rendered(); -extern void evgl_direct_img_obj_set(Evas_Object *img, int alpha, int rot); +extern void evgl_direct_img_obj_set(Evas_Object *img, int rot); extern Evas_Object *evgl_direct_img_obj_get(); +extern void evgl_direct_img_clip_set(int c, int x, int y, int w, int h); +extern void evgl_direct_override_get(int *override, int *force_off); #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 ffd63e7772..fe296aee6d 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 @@ -18,7 +18,7 @@ extern int _evas_gl_log_dom; #ifdef DBG # undef DBG #endif -#define DBG(...) EINA_LOG_DOM_DBG(_evas_gl_log_dom, __VA_ARGS__) +#define DBG(...) EINA_LOG_DOM_DBG(_evas_gl_log_dom, __VA_ARGS__) #ifdef INF # undef INF #endif @@ -40,7 +40,7 @@ struct _EVGL_Interface // Returns the native display of evas engine. void *(*display_get)(void *data); - // Returns the Window surface that evas uses for direct rendering opt. + // Returns the Window surface that evas uses for direct rendering opt void *(*evas_surface_get)(void *data); void *(*native_window_create)(void *data); int (*native_window_destroy)(void *data, void *window); @@ -129,7 +129,6 @@ struct _EVGL_Context int scissor_enabled; int scissor_updated; int scissor_coord[4]; - int dr_scissor_coord[4]; int direct_scissor; int viewport_updated; @@ -142,7 +141,7 @@ typedef enum _EVGL_Color_Bit { COLOR_NONE = 0, COLOR_RGB_888 = 0x1, - COLOR_RGBA_8888 = 0x3, // XXX: eh? not 0x2 + COLOR_RGBA_8888 = 0x3, } EVGL_Color_Bit; @@ -150,20 +149,20 @@ typedef enum _EVGL_Depth_Bit { DEPTH_NONE = 0, DEPTH_BIT_8 = 0x1, - DEPTH_BIT_16 = 0x3, // XXX: eh? not 0x2 - DEPTH_BIT_24 = 0x7, // XXX: eh? not 0x4 - DEPTH_BIT_32 = 0xF, // XXX: eh? not 0x8 - DEPTH_STENCIL = 0xFF, // XXX: eh? not 0x80 + DEPTH_BIT_16 = 0x3, + DEPTH_BIT_24 = 0x7, + DEPTH_BIT_32 = 0xF, + DEPTH_STENCIL = 0xFF, } EVGL_Depth_Bit; typedef enum _EVGL_Stencil_Bit { STENCIL_NONE = 0, STENCIL_BIT_1 = 0x1, - STENCIL_BIT_2 = 0x3, // XXX: eh? not 0x2 - STENCIL_BIT_4 = 0x7, // XXX: eh? not 0x4 - STENCIL_BIT_8 = 0xF, // XXX: eh? not 0x8 - STENCIL_BIT_16 = 0x1F, // XXX: eh? not 0x10 + STENCIL_BIT_2 = 0x3, + STENCIL_BIT_4 = 0x7, + STENCIL_BIT_8 = 0xF, + STENCIL_BIT_16 = 0x1F, } EVGL_Stencil_Bit; @@ -212,6 +211,10 @@ struct _EVGL_Resource int direct_rendered; Evas_Object *direct_img_obj; + int get_pixels_set; + + int master_clip; + int clip[4]; }; struct _EVGL_Engine @@ -236,9 +239,12 @@ struct _EVGL_Engine int direct_mem_opt; int api_debug_mode; - // Force Off fo Debug purposes + // Force Off for Debug purposes int direct_force_off; + // Force Direct Scissoring off for Debug purposes + int direct_scissor_off; + // Keep track of all the current surfaces/contexts Eina_List *surfaces; Eina_List *contexts; diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c index 08e337e4eb..f467c29fac 100644 --- a/src/modules/evas/engines/gl_x11/evas_engine.c +++ b/src/modules/evas/engines/gl_x11/evas_engine.c @@ -53,6 +53,12 @@ struct _Render_Engine int lost_back; int prev_age; Eina_Bool evgl_initted : 1; + + struct { + Evas_Object_Image_Pixels_Get_Cb get_pixels; + void *get_pixels_data; + Evas_Object *obj; + } func; }; static int initted = 0; @@ -1505,7 +1511,7 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode) } } else - eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]); + eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]); //xx if (!safe_native) eglWaitGL(); if (re->info->callback.post_swap) { @@ -2803,10 +2809,30 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) && (n->ns.data.opengl.framebuffer_id == 0) && - (evgl_direct_rendered())) + re->func.get_pixels) { DBG("Rendering Directly to the window: %p", data); - evas_object_image_pixels_dirty_set(evgl_direct_img_obj_get(), EINA_TRUE); + + re->win->gl_context->dc = context; + + if (re->func.get_pixels) + { + + // Pass the clip info the evas_gl + evgl_direct_img_clip_set(1, + 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 + evgl_direct_img_obj_set(re->func.obj, re->win->gl_context->rot); + re->func.get_pixels(re->func.get_pixels_data, re->func.obj); + evgl_direct_img_obj_set(NULL, 0); + + // Reset clip + evgl_direct_img_clip_set(0, 0, 0, 0, 0); + } } else { @@ -3086,13 +3112,23 @@ eng_gl_api_get(void *data) return evgl_api_get(); } + static void -eng_gl_img_obj_set(void *data EINA_UNUSED, void *image, int has_alpha) +eng_gl_direct_override_get(void *data, int *override, int *force_off) +{ + EVGLINIT(data, ); + evgl_direct_override_get(override, force_off); +} + +static void +eng_gl_get_pixels_set(void *data, void *get_pixels, void *get_pixels_data, void *obj) { Render_Engine *re = (Render_Engine *)data; EVGLINIT(data, ); - evgl_direct_img_obj_set(image, has_alpha, re->win->gl_context->rot); + re->func.get_pixels = get_pixels; + re->func.get_pixels_data = get_pixels_data; + re->func.obj = (Evas_Object*)obj; } //--------------------------------// @@ -3405,7 +3441,8 @@ 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(gl_direct_override_get); + ORD(gl_get_pixels_set); ORD(image_load_error_get); diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 75a9bbb1a0..b13943e24f 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -2661,7 +2661,8 @@ 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 + NULL, // need software mesa for gl rendering <- gl_direct_override + NULL, // need software mesa for gl rendering <- gl_get_pixels_set eng_image_load_error_get, eng_font_run_font_end_get, eng_image_animated_get, diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index 40aeb4c0ae..6ed5e968c5 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -41,6 +41,12 @@ struct _Render_Engine Eina_Bool lost_back : 1; Eina_Bool end : 1; Eina_Bool evgl_initted : 1; + + struct { + Evas_Object_Image_Pixels_Get_Cb get_pixels; + void *get_pixels_data; + Evas_Object *obj; + } func; }; typedef struct _Native Native; @@ -1392,14 +1398,22 @@ eng_gl_api_get(void *data) return evgl_api_get(); } -static void -eng_gl_img_obj_set(void *data, void *image, int has_alpha) +static void +eng_gl_direct_override_get(void *data, int *override, int *force_off) { - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; EVGLINIT(data, ); - evgl_direct_img_obj_set(image, has_alpha, re->win->gl_context->rot); + evgl_direct_override_get(override, force_off); +} + +static void +eng_gl_get_pixels_set(void *data, void *get_pixels, void *get_pixels_data, void *obj) +{ + Render_Engine *re = (Render_Engine *)data; + + EVGLINIT(data, ); + re->func.get_pixels = get_pixels; + re->func.get_pixels_data = get_pixels_data; + re->func.obj = (Evas_Object*)obj; } static void @@ -1905,10 +1919,30 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) && (n->ns.data.opengl.framebuffer_id == 0) && - (evgl_direct_rendered())) + re->func.get_pixels) { DBG("Rendering Directly to the window: %p", data); - evas_object_image_pixels_dirty_set(evgl_direct_img_obj_get(), EINA_TRUE); + + re->win->gl_context->dc = context; + + if (re->func.get_pixels) + { + + // Pass the clip info the evas_gl + evgl_direct_img_clip_set(1, + 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 + evgl_direct_img_obj_set(re->func.obj, re->win->gl_context->rot); + re->func.get_pixels(re->func.get_pixels_data, re->func.obj); + evgl_direct_img_obj_set(NULL, 0); + + // Reset clip + evgl_direct_img_clip_set(0, 0, 0, 0, 0); + } } else { @@ -2523,7 +2557,8 @@ 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(gl_direct_override_get); + ORD(gl_get_pixels_set); ORD(rectangle_draw); ORD(line_draw);