ector: improve uploading of GL texture for vector graphism

This rely on a faster code path to upload dynamic texture. Once we get support
for gbm, we should see significant performance improvement in speed, but this
first step is already a 5 times improvement (Ok, we get from really bad, to not
really useful...).
This commit is contained in:
Cedric BAIL 2015-11-19 13:15:51 +01:00
parent beacff7959
commit 412191e5f8
4 changed files with 109 additions and 36 deletions

View File

@ -113,8 +113,13 @@ _cleanup_reference(void *data,
void
_evas_vg_eo_base_destructor(Eo *eo_obj, Evas_VG_Data *pd)
{
Evas_Object_Protected_Data *obj;
Evas *e = evas_object_evas_get(eo_obj);
obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
if (pd->engine_data)
obj->layer->evas->engine.func->ector_free(pd->engine_data);
eo_do(e, eo_event_callback_del(EVAS_CANVAS_EVENT_RENDER_POST, _cleanup_reference, pd));
eo_unref(pd->root);
@ -179,7 +184,7 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Evas_VG_Data *vd,
nd = eo_data_scope_get(n, EFL_VG_BASE_CLASS);
obj->layer->evas->engine.func->ector_renderer_draw(output, context, surface, nd->renderer, clips, do_async);
obj->layer->evas->engine.func->ector_renderer_draw(output, context, surface, vd->engine_data, nd->renderer, clips, do_async);
if (do_async)
eina_array_push(&vd->cleanup, eo_ref(nd->renderer));
@ -202,6 +207,9 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED,
// to another Ector_Surface as long as that Ector_Surface is a
// child of the main Ector_Surface (necessary for Evas_Map).
if (!vd->engine_data)
vd->engine_data = obj->layer->evas->engine.func->ector_new(output, context, ector, surface);
/* render object to surface with context, and offxet by x,y */
obj->layer->evas->engine.func->context_color_set(output,
context,
@ -221,13 +229,14 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED,
obj->cur->render_op);
obj->layer->evas->engine.func->ector_begin(output, context,
ector, surface,
vd->engine_data,
obj->cur->geometry.x + x, obj->cur->geometry.y + y,
do_async);
_evas_vg_render(obj, vd,
output, context, surface,
vd->root, NULL,
do_async);
obj->layer->evas->engine.func->ector_end(output, context, ector, surface, do_async);
obj->layer->evas->engine.func->ector_end(output, context, ector, surface, vd->engine_data, do_async);
}
static void

View File

@ -1448,9 +1448,11 @@ struct _Evas_Func
Ector_Surface *(*ector_create) (void *data);
void (*ector_destroy) (void *data, Ector_Surface *surface);
void (*ector_begin) (void *data, void *context, Ector_Surface *ector, void *surface, int x, int y, Eina_Bool do_async);
void (*ector_renderer_draw) (void *data, void *context, void *surface, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async);
void (*ector_end) (void *data, void *context, Ector_Surface *ector, void *surface, Eina_Bool do_async);
void (*ector_begin) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, int x, int y, Eina_Bool do_async);
void (*ector_renderer_draw) (void *data, void *context, void *surface, void *engine_data, Ector_Renderer *r, Eina_Array *clips, Eina_Bool do_async);
void (*ector_end) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, Eina_Bool do_async);
void* (*ector_new) (void *data, void *context, Ector_Surface *ector, void *surface);
void (*ector_free) (void *engine_data);
};
struct _Evas_Image_Save_Func

View File

@ -721,6 +721,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!im)
{
if (err) *err = EVAS_LOAD_ERROR_GENERIC;
ERR("No image provided.");
return NULL;
}
@ -734,6 +735,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!im_new)
{
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
ERR("Rotation failed.");
return im;
}
evas_gl_common_image_free(im);
@ -745,7 +747,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
#ifdef GL_GLES
re->window_use(re->software.ob);
if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.img) &&
if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.img) &&
(im->cs.space == EVAS_COLORSPACE_ARGB8888))
{
if (im->tex->pt->dyn.checked_out > 0)
@ -779,6 +781,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!im->tex->pt->dyn.data)
{
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
ERR("Ressource allocation failed.");
return im;
}
im->tex->pt->dyn.checked_out++;
@ -821,6 +824,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!ok)
{
if (err) *err = EVAS_LOAD_ERROR_GENERIC;
ERR("Lock failed.");
return NULL;
}
@ -830,6 +834,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!im_new)
{
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
ERR("Allocation failed.");
return NULL;
}
@ -840,6 +845,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!ok)
{
if (err) *err = EVAS_LOAD_ERROR_GENERIC;
ERR("Unlock failed.");
return NULL;
}
*image_data = im_new->im->image.data;
@ -974,6 +980,7 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
evas_gl_common_image_free(im);
im = im2;
}
evas_gl_common_image_dirty(im, 0, 0, 0, 0);
break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
@ -2460,7 +2467,7 @@ _evas_render_op_to_ector_rop(Evas_Render_Op op)
}
static void
eng_ector_renderer_draw(void *data, void *context, void *surface, Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async EINA_UNUSED)
eng_ector_renderer_draw(void *data, void *context, void *surface, void *engine_data EINA_UNUSED, Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async EINA_UNUSED)
{
Evas_GL_Image *dst = surface;
Evas_Engine_GL_Context *gc;
@ -2526,16 +2533,43 @@ eng_ector_renderer_draw(void *data, void *context, void *surface, Ector_Renderer
eina_array_free(c);
}
static void *software_buffer = NULL;
typedef struct _Evas_GL_Ector Evas_GL_Ector;
struct _Evas_GL_Ector
{
Evas_GL_Image *gl;
DATA32 *software;
Eina_Bool tofree;
};
static void*
eng_ector_new(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector EINA_UNUSED, void *surface EINA_UNUSED)
{
Evas_GL_Ector *r;
r = calloc(1, sizeof (Evas_GL_Ector));
return r;
}
static void
eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector,
void *surface, int x, int y, Eina_Bool do_async EINA_UNUSED)
eng_ector_free(void *engine_data)
{
Evas_GL_Ector *r = engine_data;
if (r->gl) evas_gl_common_image_free(r->gl);
if (r->tofree) free(r->software);
free(r);
}
static void
eng_ector_begin(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
void *surface, void *engine_data,
int x, int y, Eina_Bool do_async EINA_UNUSED)
{
Evas_Engine_GL_Context *gl_context;
Render_Engine_GL_Generic *re = data;
Evas_GL_Ector *buffer = engine_data;
int w, h;
void *temp;
re->window_use(re->software.ob);
gl_context = re->window_gl_context_get(re->software.ob);
@ -2544,36 +2578,51 @@ eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface
w = gl_context->w; h = gl_context->h;
temp = software_buffer;
software_buffer = realloc(software_buffer, sizeof (unsigned int) * w * h);
if (!software_buffer)
if (!buffer->gl || buffer->gl->w != w || buffer->gl->h != h)
{
ERR("Realloc failed!!");
software_buffer = temp;
return;
int err = EVAS_LOAD_ERROR_NONE;
if (buffer->gl) evas_gl_common_image_free(buffer->gl);
if (buffer->tofree) free(buffer->software);
buffer->software = NULL;
buffer->gl = evas_gl_common_image_new(gl_context, w, h, 1, EVAS_COLORSPACE_ARGB8888);
if (!buffer->gl)
{
ERR("Creation of an image for vector graphics [%i, %i] failed\n", w, h);
return ;
}
/* evas_gl_common_image_content_hint_set(buffer->gl, EVAS_IMAGE_CONTENT_HINT_DYNAMIC); */
buffer->gl = eng_image_data_get(data, buffer->gl, 1, &buffer->software, &err, &buffer->tofree);
if (!buffer->gl && err != EVAS_LOAD_ERROR_NONE)
{
ERR("Mapping of an image for vector graphics [%i, %i] failed with %i\n", w, h, err);
return ;
}
}
memset(software_buffer, 0, sizeof (unsigned int) * w * h);
memset(buffer->software, 0, sizeof (unsigned int) * w * h);
if (use_cairo)
{
eo_do(ector,
ector_cairo_software_surface_set(software_buffer, w, h),
ector_cairo_software_surface_set(buffer->software, w, h),
ector_surface_reference_point_set(x, y));
}
else
{
eo_do(ector,
ector_software_surface_set(software_buffer, w, h),
ector_software_surface_set(buffer->software, w, h),
ector_surface_reference_point_set(x, y));
}
}
static void
eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
void *surface EINA_UNUSED, Eina_Bool do_async EINA_UNUSED)
void *surface EINA_UNUSED, void *engine_data,
Eina_Bool do_async EINA_UNUSED)
{
Evas_Engine_GL_Context *gl_context;
Render_Engine_GL_Generic *re = data;
Evas_GL_Image *im;
Evas_GL_Ector *buffer = engine_data;
int w, h;
Eina_Bool mul_use;
@ -2592,24 +2641,22 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
ector_software_surface_set(NULL, 0, 0));
}
im = evas_gl_common_image_new_from_copied_data(gl_context, w, h, software_buffer, 1, EVAS_COLORSPACE_ARGB8888);
eng_image_data_put(data, buffer->gl, buffer->software);
if (!mul_use)
{
// @hack as image_draw uses below fields to do colour multiplication.
gl_context->dc->mul.col = ector_color_multiply(0xffffffff,gl_context->dc->col.col);
gl_context->dc->mul.use = EINA_TRUE;
}
{
// @hack as image_draw uses below fields to do colour multiplication.
gl_context->dc->mul.col = ector_color_multiply(0xffffffff, gl_context->dc->col.col);
gl_context->dc->mul.use = EINA_TRUE;
}
// We actually just bluntly push the pixel all over the
// destination surface. We don't have the actual information
// of the widget size. This is not a problem.
// Later on, we don't want that information and today when
// using GL backend, you just need to turn on Evas_Map on
// the Evas_Object_VG.
evas_gl_common_image_draw(gl_context, im, 0, 0, w, h, 0, 0, w, h, 0);
evas_gl_common_image_free(im);
evas_gl_common_image_draw(gl_context, buffer->gl, 0, 0, w, h, 0, 0, w, h, 0);
// restore gl state
gl_context->dc->mul.use = mul_use;
@ -2764,6 +2811,8 @@ module_open(Evas_Module *em)
ORD(ector_begin);
ORD(ector_renderer_draw);
ORD(ector_end);
ORD(ector_new);
ORD(ector_free);
/* now advertise out own api */
em->functions = (void *)(&func);

View File

@ -3795,7 +3795,7 @@ _draw_thread_ector_draw(void *data)
}
static void
eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async)
eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, void *engine_data EINA_UNUSED, Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async)
{
RGBA_Image *dst = surface;
RGBA_Draw_Context *dc = context;
@ -3919,8 +3919,19 @@ _draw_thread_ector_surface_set(void *data)
eina_mempool_free(_mp_command_ector_surface, ector_surface);
}
static void*
eng_ector_new(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector EINA_UNUSED, void *surface EINA_UNUSED)
{
return NULL;
}
static void
eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector, void *surface, int x, int y, Eina_Bool do_async)
eng_ector_free(void *engine_data EINA_UNUSED)
{
}
static void
eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector, void *surface, void *engine_data EINA_UNUSED, int x, int y, Eina_Bool do_async)
{
if (do_async)
{
@ -3963,7 +3974,7 @@ eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface
}
static void
eng_ector_end(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector, void *surface EINA_UNUSED, Eina_Bool do_async)
eng_ector_end(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector, void *surface EINA_UNUSED, void *engine_data EINA_UNUSED, Eina_Bool do_async)
{
if (do_async)
{
@ -4182,7 +4193,9 @@ static Evas_Func func =
eng_ector_destroy,
eng_ector_begin,
eng_ector_renderer_draw,
eng_ector_end
eng_ector_end,
eng_ector_new,
eng_ector_free
/* FUTURE software generic calls go here */
};