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.
This commit is contained in:
Sung W. Park 2013-06-17 17:53:33 +09:00
parent 316be3e6c7
commit 8e6f0aa11c
11 changed files with 386 additions and 121 deletions

View File

@ -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 2013-06-17 Cedric Bail
* Edje: Use Eo array of callbacks to reduce edje memory foot print. * Edje: Use Eo array of callbacks to reduce edje memory foot print.

1
NEWS
View File

@ -332,4 +332,5 @@ Fixes:
* Evas: improve stability of Evas_Cserve2. * Evas: improve stability of Evas_Cserve2.
* Evas: Fix gif cannot decode alpha value correctly. * 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 bs if app call image object update add after call api like fileset.
* Evas: Fix evas_gl direct rendering to support partial redraw.

View File

@ -125,6 +125,7 @@ struct _Evas_Object_Image
Eina_Bool proxyerror : 1; Eina_Bool proxyerror : 1;
Eina_Bool proxy_src_clip : 1; Eina_Bool proxy_src_clip : 1;
Eina_Bool written : 1; Eina_Bool written : 1;
Eina_Bool direct_render : 1;
}; };
/* private methods for image objects */ /* 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; 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) if (pixels)
{ {
Evas_Coord idw, idh, idx, idy; Evas_Coord idw, idh, idx, idy;
int ix, iy, iw, ih; int ix, iy, iw, ih;
int img_set = 0; int direct_override = 0;
int direct_force_off = 0;
if (o->dirty_pixels) if (o->dirty_pixels)
{ {
if (o->pixels->func.get_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 if (obj->layer->evas->engine.func->image_native_get)
// 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->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) if (o->engine_data != pixels)
pixels = o->engine_data; pixels = o->engine_data;
o->engine_data = obj->layer->evas->engine.func->image_dirty_region o->engine_data = obj->layer->evas->engine.func->image_dirty_region
(obj->layer->evas->engine.data.output, o->engine_data, (obj->layer->evas->engine.data.output, o->engine_data,
0, 0, o->cur->image.w, o->cur->image.h); 0, 0, o->cur->image.w, o->cur->image.h);
} }
o->dirty_pixels = EINA_FALSE; 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)) 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); 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; 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;
}
}
} }
} }

View File

@ -877,7 +877,8 @@ struct _Evas_Func
void *(*gl_proc_address_get) (void *data, const char *name); void *(*gl_proc_address_get) (void *data, const char *name);
int (*gl_native_surface_get) (void *data, void *surface, void *native_surface); int (*gl_native_surface_get) (void *data, void *surface, void *native_surface);
void *(*gl_api_get) (void *data); 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 (*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); 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);

View File

@ -153,21 +153,51 @@ _evgl_glReleaseShaderCompiler(void)
// Calls related to Evas GL Direct Rendering // Calls related to Evas GL Direct Rendering
//-------------------------------------------------------------// //-------------------------------------------------------------//
// Transform from Evas Coordinat to GL Coordinate // Transform from Evas Coordinat to GL Coordinate
// returns: oc[4] original image object dimension in gl coord // returns: imgc[4] (oc[4]) original image object dimension in gl coord
// returns: nc[4] tranformed (x, y, width, heigth) 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 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 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); 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) if (rot == 0)
{ {
// oringinal image object coordinate in gl coordinate // oringinal image object coordinate in gl coordinate
imgc[0] = pd->cur->geometry.x; imgc[0] = obj_x;
imgc[1] = pd->layer->evas->output.h - pd->cur->geometry.y - pd->cur->geometry.h; imgc[1] = out_h - obj_y - obj_h;
imgc[2] = imgc[0] + pd->cur->geometry.w; imgc[2] = imgc[0] + obj_w;
imgc[3] = imgc[1] + pd->cur->geometry.h; 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 // transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + x; objc[0] = imgc[0] + x;
@ -178,14 +208,20 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip,
else if (rot == 180) else if (rot == 180)
{ {
// oringinal image object coordinate in gl coordinate // oringinal image object coordinate in gl coordinate
imgc[0] = pd->layer->evas->output.w - pd->cur->geometry.x - pd->cur->geometry.w; imgc[0] = out_w - obj_x - obj_w;
imgc[1] = pd->cur->geometry.y; imgc[1] = obj_y;
imgc[2] = imgc[0] + pd->cur->geometry.w; imgc[2] = imgc[0] + obj_w;
imgc[3] = imgc[1] + pd->cur->geometry.h; 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 // transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + pd->cur->geometry.w - x - width; objc[0] = imgc[0] + obj_w - x - width;
objc[1] = imgc[1] + pd->cur->geometry.h - y - height; objc[1] = imgc[1] + obj_h - y - height;
objc[2] = objc[0] + width; objc[2] = objc[0] + width;
objc[3] = objc[1] + height; objc[3] = objc[1] + height;
@ -193,13 +229,19 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip,
else if (rot == 90) else if (rot == 90)
{ {
// oringinal image object coordinate in gl coordinate // oringinal image object coordinate in gl coordinate
imgc[0] = pd->cur->geometry.y; imgc[0] = obj_y;
imgc[1] = pd->cur->geometry.x; imgc[1] = obj_x;
imgc[2] = imgc[0] + pd->cur->geometry.h; imgc[2] = imgc[0] + obj_h;
imgc[3] = imgc[1] + pd->cur->geometry.w; 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 // 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[1] = imgc[1] + x;
objc[2] = objc[0] + height; objc[2] = objc[0] + height;
objc[3] = objc[1] + width; objc[3] = objc[1] + width;
@ -207,14 +249,20 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip,
else if (rot == 270) else if (rot == 270)
{ {
// oringinal image object coordinate in gl coordinate // oringinal image object coordinate in gl coordinate
imgc[0] = pd->layer->evas->output.h - pd->cur->geometry.y - pd->cur->geometry.h; imgc[0] = out_h - obj_y - obj_h;
imgc[1] = pd->layer->evas->output.w - pd->cur->geometry.x - pd->cur->geometry.w; imgc[1] = out_w - obj_x - obj_w;
imgc[2] = imgc[0] + pd->cur->geometry.h; imgc[2] = imgc[0] + obj_h;
imgc[3] = imgc[1] + pd->cur->geometry.w; 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 // transformed (x,y,width,height) in gl coordinate
objc[0] = imgc[0] + y; 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[2] = objc[0] + height;
objc[3] = objc[1] + width; objc[3] = objc[1] + width;
} }
@ -224,7 +272,7 @@ compute_gl_coordinates(Evas_Object *obj, int rot, int clip,
return; return;
} }
if (clip) if (clip_image)
{ {
// Clip against original image object // Clip against original image object
if (objc[0] < imgc[0]) objc[0] = imgc[0]; 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[2] = objc[2]-objc[0]; // width
objc[3] = objc[3]-objc[1]; // height 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 static void
@ -255,6 +308,7 @@ _evgl_glClear(GLbitfield mask)
Evas_Object *img; Evas_Object *img;
int rot = 0; int rot = 0;
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,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())) if (!(rsc=_evgl_tls_resource_get()))
{ {
@ -288,16 +342,33 @@ _evgl_glClear(GLbitfield mask)
img = rsc->direct_img_obj; img = rsc->direct_img_obj;
rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); 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)) if ((ctx->scissor_updated) && (ctx->scissor_enabled))
{ {
glScissor(ctx->dr_scissor_coord[0], ctx->dr_scissor_coord[1], compute_gl_coordinates(img, rot, 1,
ctx->dr_scissor_coord[2], ctx->dr_scissor_coord[3]); 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; ctx->direct_scissor = 0;
} }
else 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); glClear(mask);
} }
@ -422,6 +493,7 @@ _evgl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum forma
Evas_Object *img; Evas_Object *img;
int rot = 0; int rot = 0;
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,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())) 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; img = rsc->direct_img_obj;
rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); 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); glReadPixels(nc[0], nc[1], nc[2], nc[3], format, type, pixels);
} }
else else
@ -473,6 +545,7 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
Evas_Object *img; Evas_Object *img;
int rot = 0; int rot = 0;
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,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())) 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; img = rsc->direct_img_obj;
rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); 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);
glScissor(nc[0], nc[1], nc[2], nc[3]);
// Keep a copy of the original coordinates // Keep a copy of the original coordinates
ctx->scissor_coord[0] = x; 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[2] = width;
ctx->scissor_coord[3] = height; ctx->scissor_coord[3] = height;
// Update direct rendering coordinates if (rsc->master_clip)
ctx->dr_scissor_coord[0] = nc[0]; {
ctx->dr_scissor_coord[1] = nc[1]; RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]);
ctx->dr_scissor_coord[2] = nc[2]; glScissor(nc[0], nc[1], nc[2], nc[3]);
ctx->dr_scissor_coord[3] = nc[3]; }
else
glScissor(nc[0], nc[1], nc[2], nc[3]);
ctx->direct_scissor = 0; ctx->direct_scissor = 0;
@ -558,6 +632,7 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
Evas_Object *img; Evas_Object *img;
int rot = 0; int rot = 0;
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,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())) 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; img = rsc->direct_img_obj;
rot = evgl_engine->funcs->rotation_angle_get(rsc->current_eng); 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)) if ((ctx->scissor_updated) && (ctx->scissor_enabled))
{ {
glScissor(ctx->dr_scissor_coord[0], ctx->dr_scissor_coord[1], // Recompute the scissor coordinates
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; 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 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 // Keep a copy of the original coordinates
ctx->viewport_coord[0] = x; ctx->viewport_coord[0] = x;
@ -2433,6 +2530,22 @@ _normal_gl_api_get(Evas_GL_API *funcs)
evgl_api_ext_get(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 static void
_debug_gl_api_get(Evas_GL_API *funcs) _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); _debug_gl_api_get(funcs);
else else
_normal_gl_api_get(funcs); _normal_gl_api_get(funcs);
if (evgl_engine->direct_scissor_off)
_direct_scissor_off_api_get(funcs);
} }

View File

@ -448,7 +448,7 @@ _surface_cap_check()
ERR("EVGL Engine not initialized!"); ERR("EVGL Engine not initialized!");
return 0; return 0;
} }
// Check Surface Cap for MSAA // Check Surface Cap for MSAA
if (evgl_engine->caps.msaa_supported) if (evgl_engine->caps.msaa_supported)
{ {
@ -507,7 +507,7 @@ _surface_cap_load(Eet_File *ef)
free(data); free(data);
data = NULL; data = NULL;
// !!!FIXME // !!!FIXME
// Should use eet functionality instead of just reading using sscanfs... // Should use eet functionality instead of just reading using sscanfs...
for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i) 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) if (eet_write(ef, "num_fbo_fmts", data, strlen(data) + 1, 1) < 0)
return 0; return 0;
// !!!FIXME // !!!FIXME
// Should use eet functionality instead of just writing out using snprintfs... // Should use eet functionality instead of just writing out using snprintfs...
for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i) 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( 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); 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 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]); 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; EVGL_Context *ctx = rsc->current_ctx;
if ((!evgl_engine->direct_force_off) && if ((!evgl_engine->direct_force_off) &&
(rsc->id == evgl_engine->main_tid) && (rsc->id == evgl_engine->main_tid) &&
(ctx) && (ctx) &&
(ctx->current_sfc) && (ctx->current_sfc) &&
(ctx->current_sfc->direct_fb_opt) && (ctx->current_sfc->direct_fb_opt) &&
(!rsc->direct_img_obj)) (!rsc->direct_img_obj))
return 1; return 1;
@ -1285,14 +1285,14 @@ _evgl_direct_enabled()
EVGL_Engine * EVGL_Engine *
evgl_engine_init(void *eng_data, EVGL_Interface *efunc) 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; char *s = NULL;
if (evgl_engine) return evgl_engine; if (evgl_engine) return evgl_engine;
// Initialize Log Domain // Initialize Log Domain
if (_evas_gl_log_dom < 0) 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) if (_evas_gl_log_dom < 0)
{ {
EINA_LOG_ERR("Can not create a module log domain."); 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 // Initialize Extensions
if (efunc->proc_address_get && efunc->ext_string_get) 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 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("GLUE Extension String: %s", efunc->ext_string_get(eng_data));
DBG("GL Extension String: %s", glGetString(GL_EXTENSIONS)); 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"); s = getenv("EVAS_GL_DIRECT_MEM_OPT");
if (s) direct_mem_opt = atoi(s); if (s) direct_mem_opt = atoi(s);
if (direct_mem_opt == 1) 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 // Check if Direct Rendering Override Force Off flag is on
s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF"); s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF");
if (s) direct_off = atoi(s); if (s) direct_off = atoi(s);
if (direct_off == 1) 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 // Check if API Debug mode is on
s = getenv("EVAS_GL_API_DEBUG"); s = getenv("EVAS_GL_API_DEBUG");
if (s) debug_mode = atoi(s); if (s) debug_mode = atoi(s);
if (debug_mode == 1) 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) // Maint Thread ID (get tid not available in eina thread yet)
evgl_engine->main_tid = 0; evgl_engine->main_tid = 0;
@ -1825,7 +1831,7 @@ evgl_direct_rendered()
} }
void 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; 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 // Normally direct rendering isn't allowed if alpha is on and
// rotation is not 0. BUT, if override is on, allow it. // rotation is not 0. BUT, if override is on, allow it.
if ((alpha) || (rot!=0)) if (rot!=0)
{ {
if (evgl_engine->direct_override) if (evgl_engine->direct_override)
rsc->direct_img_obj = img; rsc->direct_img_obj = img;
@ -1862,6 +1868,29 @@ evgl_api_get()
return &gl_funcs; 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;
}
//-----------------------------------------------------// //-----------------------------------------------------//

View File

@ -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 int evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns);
extern Evas_GL_API *evgl_api_get(); extern Evas_GL_API *evgl_api_get();
extern int evgl_direct_rendered(); 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 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 #endif //_EVAS_GL_CORE_H

View File

@ -18,7 +18,7 @@ extern int _evas_gl_log_dom;
#ifdef DBG #ifdef DBG
# undef DBG # undef DBG
#endif #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 #ifdef INF
# undef INF # undef INF
#endif #endif
@ -40,7 +40,7 @@ struct _EVGL_Interface
// Returns the native display of evas engine. // Returns the native display of evas engine.
void *(*display_get)(void *data); 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 *(*evas_surface_get)(void *data);
void *(*native_window_create)(void *data); void *(*native_window_create)(void *data);
int (*native_window_destroy)(void *data, void *window); int (*native_window_destroy)(void *data, void *window);
@ -129,7 +129,6 @@ struct _EVGL_Context
int scissor_enabled; int scissor_enabled;
int scissor_updated; int scissor_updated;
int scissor_coord[4]; int scissor_coord[4];
int dr_scissor_coord[4];
int direct_scissor; int direct_scissor;
int viewport_updated; int viewport_updated;
@ -142,7 +141,7 @@ typedef enum _EVGL_Color_Bit
{ {
COLOR_NONE = 0, COLOR_NONE = 0,
COLOR_RGB_888 = 0x1, COLOR_RGB_888 = 0x1,
COLOR_RGBA_8888 = 0x3, // XXX: eh? not 0x2 COLOR_RGBA_8888 = 0x3,
} EVGL_Color_Bit; } EVGL_Color_Bit;
@ -150,20 +149,20 @@ typedef enum _EVGL_Depth_Bit
{ {
DEPTH_NONE = 0, DEPTH_NONE = 0,
DEPTH_BIT_8 = 0x1, DEPTH_BIT_8 = 0x1,
DEPTH_BIT_16 = 0x3, // XXX: eh? not 0x2 DEPTH_BIT_16 = 0x3,
DEPTH_BIT_24 = 0x7, // XXX: eh? not 0x4 DEPTH_BIT_24 = 0x7,
DEPTH_BIT_32 = 0xF, // XXX: eh? not 0x8 DEPTH_BIT_32 = 0xF,
DEPTH_STENCIL = 0xFF, // XXX: eh? not 0x80 DEPTH_STENCIL = 0xFF,
} EVGL_Depth_Bit; } EVGL_Depth_Bit;
typedef enum _EVGL_Stencil_Bit typedef enum _EVGL_Stencil_Bit
{ {
STENCIL_NONE = 0, STENCIL_NONE = 0,
STENCIL_BIT_1 = 0x1, STENCIL_BIT_1 = 0x1,
STENCIL_BIT_2 = 0x3, // XXX: eh? not 0x2 STENCIL_BIT_2 = 0x3,
STENCIL_BIT_4 = 0x7, // XXX: eh? not 0x4 STENCIL_BIT_4 = 0x7,
STENCIL_BIT_8 = 0xF, // XXX: eh? not 0x8 STENCIL_BIT_8 = 0xF,
STENCIL_BIT_16 = 0x1F, // XXX: eh? not 0x10 STENCIL_BIT_16 = 0x1F,
} EVGL_Stencil_Bit; } EVGL_Stencil_Bit;
@ -212,6 +211,10 @@ struct _EVGL_Resource
int direct_rendered; int direct_rendered;
Evas_Object *direct_img_obj; Evas_Object *direct_img_obj;
int get_pixels_set;
int master_clip;
int clip[4];
}; };
struct _EVGL_Engine struct _EVGL_Engine
@ -236,9 +239,12 @@ struct _EVGL_Engine
int direct_mem_opt; int direct_mem_opt;
int api_debug_mode; int api_debug_mode;
// Force Off fo Debug purposes // Force Off for Debug purposes
int direct_force_off; int direct_force_off;
// Force Direct Scissoring off for Debug purposes
int direct_scissor_off;
// Keep track of all the current surfaces/contexts // Keep track of all the current surfaces/contexts
Eina_List *surfaces; Eina_List *surfaces;
Eina_List *contexts; Eina_List *contexts;

View File

@ -53,6 +53,12 @@ struct _Render_Engine
int lost_back; int lost_back;
int prev_age; int prev_age;
Eina_Bool evgl_initted : 1; 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; static int initted = 0;
@ -1505,7 +1511,7 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
} }
} }
else 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(); //xx if (!safe_native) eglWaitGL();
if (re->info->callback.post_swap) 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) && if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) &&
(n->ns.data.opengl.framebuffer_id == 0) && (n->ns.data.opengl.framebuffer_id == 0) &&
(evgl_direct_rendered())) re->func.get_pixels)
{ {
DBG("Rendering Directly to the window: %p", data); 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 else
{ {
@ -3086,13 +3112,23 @@ eng_gl_api_get(void *data)
return evgl_api_get(); return evgl_api_get();
} }
static void 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; Render_Engine *re = (Render_Engine *)data;
EVGLINIT(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_proc_address_get);
ORD(gl_native_surface_get); ORD(gl_native_surface_get);
ORD(gl_api_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); ORD(image_load_error_get);

View File

@ -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_proc_address_get
NULL, // need software mesa for gl rendering <- gl_native_surface_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_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_image_load_error_get,
eng_font_run_font_end_get, eng_font_run_font_end_get,
eng_image_animated_get, eng_image_animated_get,

View File

@ -41,6 +41,12 @@ struct _Render_Engine
Eina_Bool lost_back : 1; Eina_Bool lost_back : 1;
Eina_Bool end : 1; Eina_Bool end : 1;
Eina_Bool evgl_initted : 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; typedef struct _Native Native;
@ -1392,14 +1398,22 @@ eng_gl_api_get(void *data)
return evgl_api_get(); return evgl_api_get();
} }
static void static void
eng_gl_img_obj_set(void *data, void *image, int has_alpha) eng_gl_direct_override_get(void *data, int *override, int *force_off)
{ {
Render_Engine *re;
if (!(re = (Render_Engine *)data)) return;
EVGLINIT(data, ); 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 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) && if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) &&
(n->ns.data.opengl.framebuffer_id == 0) && (n->ns.data.opengl.framebuffer_id == 0) &&
(evgl_direct_rendered())) re->func.get_pixels)
{ {
DBG("Rendering Directly to the window: %p", data); 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 else
{ {
@ -2523,7 +2557,8 @@ module_open(Evas_Module *em)
ORD(gl_proc_address_get); ORD(gl_proc_address_get);
ORD(gl_native_surface_get); ORD(gl_native_surface_get);
ORD(gl_api_get); ORD(gl_api_get);
ORD(gl_img_obj_set); ORD(gl_direct_override_get);
ORD(gl_get_pixels_set);
ORD(rectangle_draw); ORD(rectangle_draw);
ORD(line_draw); ORD(line_draw);