evas - add a prepare stage for objects before render

preparing an object is a good idea. especially with gl. you want to do
texture uploads BEFORE using textures all in one batch. otherwise this
may mean the gl implementation has to make a copy of your data in a
tmp location then copy it in later when texture becomes "unused" as it
may be in use at the moment, or it may have to stall and wait.

i have seen somewhere around 7-10% speedups on nvidia and intel
drivers with this on given a very special test case i brewed up (1000
32x32 images where i change 1 pixel every frame). this should have
impact really when we are modifying textures a lot. this is all i've
implemented for now, but this should/would/could do much more like
re-order map, proxy renders to render FIRST in a pre-render list
instead of inline and to pre-render fbo/buffer content for complex
objects like text or textblock etc.
This commit is contained in:
Carsten Haitzler 2016-11-15 11:22:14 +09:00
parent dbebf2835f
commit a479745e4f
13 changed files with 66 additions and 1 deletions

View File

@ -51,6 +51,7 @@ static int evas_object_image_get_opaque_rect(Evas_Object *eo_obj,
void *type_private_data,
Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
static int evas_object_image_can_map(Evas_Object *eo_obj);
static void evas_object_image_render_prepare(Evas_Object *obj, Evas_Object_Protected_Data *pd);
static void evas_object_image_filled_resize_listener(void *data, Evas *eo_e, Evas_Object *eo_obj, void *einfo);
@ -78,6 +79,7 @@ static const Evas_Object_Func object_func =
evas_object_image_has_opaque_rect,
evas_object_image_get_opaque_rect,
evas_object_image_can_map,
evas_object_image_render_prepare, // render_prepare
NULL
};
@ -111,6 +113,20 @@ Eina_Cow *evas_object_image_load_opts_cow = NULL;
Eina_Cow *evas_object_image_pixels_cow = NULL;
Eina_Cow *evas_object_image_state_cow = NULL;
static void
evas_object_image_render_prepare(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
{
Evas_Image_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
// if image data not loaded or in texture then upload
if ((o->cur->u.file) || (o->written) || (o->cur->frame != 0))
{
if (o->engine_data) ENFN->image_prepare(ENDT, o->engine_data);
return;
}
// XXX: if image is a proxy, PREPEND to prerender list in evas canvas
}
void
_evas_image_cleanup(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
{

View File

@ -85,6 +85,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -75,6 +75,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -83,6 +83,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
evas_object_rectangle_render2_walk
};

View File

@ -119,6 +119,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -143,6 +143,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -622,6 +622,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -144,6 +144,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -57,6 +57,7 @@ static const Evas_Object_Func object_func =
NULL,
NULL,
NULL,
NULL, // render_prepare
NULL
};

View File

@ -2725,7 +2725,16 @@ evas_render_updates_internal(Evas *eo_e,
e->engine.func->output_redraws_rect_del(e->engine.data.output,
r->x, r->y, r->w, r->h);
}
/* build obscure objects list of active objects that obscure */
static int prepare = -1;
if (prepare == -1)
{
if (getenv("EVAS_PREPARE")) prepare = !!atoi(getenv("EVAS_PREPARE"));
else prepare = 1;
}
/* build obscure objects list of active objects that obscure as well
* as objects that may need data (image data loads, texture updates,
* pre-render buffers/fbo's etc.) that are not up to date yet */
for (i = 0; i < e->active_objects.count; ++i)
{
obj = eina_array_data_get(&e->active_objects, i);
@ -2742,6 +2751,11 @@ evas_render_updates_internal(Evas *eo_e,
(!obj->is_smart)))
/* obscuring_objects = eina_list_append(obscuring_objects, obj); */
OBJ_ARRAY_PUSH(&e->obscuring_objects, obj);
if (prepare)
{
if (obj->func->render_prepare)
obj->func->render_prepare(eo_obj, obj);
}
}
eina_evlog("-render_phase5", eo_e, 0.0, NULL);

View File

@ -1289,6 +1289,10 @@ struct _Evas_Object_Func
Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
int (*can_map) (Evas_Object *obj);
// new - add to prepare list during render if object needs some pre-render
// preparation - may include rendering content to buffer or loading data
// from disk or uploading to texture etc.
void (*render_prepare) (Evas_Object *obj, Evas_Object_Protected_Data *pd);
// new render2 functions
@ -1384,6 +1388,8 @@ struct _Evas_Func
/* new api for direct data set (not put) */
void *(*image_data_slice_add) (void *data, void *image, const Eina_Slice *slice, Eina_Bool copy, int w, int h, int stride, Evas_Colorspace space, int plane, Eina_Bool alpha);
void (*image_prepare) (void *data, void *image);
int (*image_native_init) (void *data, Evas_Native_Surface_Type type);
void (*image_native_shutdown) (void *data, Evas_Native_Surface_Type type);
void *(*image_native_set) (void *data, void *image, void *native);

View File

@ -3089,6 +3089,16 @@ fail:
return NULL;
}
static void
eng_image_prepare(void *engdata EINA_UNUSED, void *image)
{
Evas_GL_Image *im = image;
if (!im) return;
evas_gl_common_image_update(im->gc, im);
}
static int
module_open(Evas_Module *em)
{
@ -3174,6 +3184,8 @@ module_open(Evas_Module *em)
ORD(image_data_maps_get);
ORD(image_data_slice_add);
ORD(image_prepare);
ORD(font_cache_flush);
ORD(font_cache_set);
ORD(font_cache_get);

View File

@ -1937,6 +1937,14 @@ fail:
return NULL;
}
static void
eng_image_prepare(void *engdata EINA_UNUSED, void *image EINA_UNUSED)
{
// software rendering doesnt want/need to prepare at this point
// XXX: though this could push along any loading threads or start
// some thread jobs for loading in the bg.
}
static void
_image_flip_horizontal(DATA32 *pixels_out, const DATA32 *pixels_in,
int iw, int ih)
@ -4649,6 +4657,7 @@ static Evas_Func func =
eng_image_data_unmap,
eng_image_data_maps_get,
eng_image_data_slice_add,
eng_image_prepare,
eng_image_native_init,
eng_image_native_shutdown,
eng_image_native_set,