forked from enlightenment/efl
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:
parent
dbebf2835f
commit
a479745e4f
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -85,6 +85,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
evas_object_rectangle_render2_walk
|
||||
};
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -143,6 +143,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -622,6 +622,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ static const Evas_Object_Func object_func =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // render_prepare
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue