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 void
_evas_vg_eo_base_destructor(Eo *eo_obj, Evas_VG_Data *pd) _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); 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_do(e, eo_event_callback_del(EVAS_CANVAS_EVENT_RENDER_POST, _cleanup_reference, pd));
eo_unref(pd->root); 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); 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) if (do_async)
eina_array_push(&vd->cleanup, eo_ref(nd->renderer)); 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 // to another Ector_Surface as long as that Ector_Surface is a
// child of the main Ector_Surface (necessary for Evas_Map). // 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 */ /* render object to surface with context, and offxet by x,y */
obj->layer->evas->engine.func->context_color_set(output, obj->layer->evas->engine.func->context_color_set(output,
context, context,
@ -221,13 +229,14 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED,
obj->cur->render_op); obj->cur->render_op);
obj->layer->evas->engine.func->ector_begin(output, context, obj->layer->evas->engine.func->ector_begin(output, context,
ector, surface, ector, surface,
vd->engine_data,
obj->cur->geometry.x + x, obj->cur->geometry.y + y, obj->cur->geometry.x + x, obj->cur->geometry.y + y,
do_async); do_async);
_evas_vg_render(obj, vd, _evas_vg_render(obj, vd,
output, context, surface, output, context, surface,
vd->root, NULL, vd->root, NULL,
do_async); 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 static void

View File

@ -1448,9 +1448,11 @@ struct _Evas_Func
Ector_Surface *(*ector_create) (void *data); Ector_Surface *(*ector_create) (void *data);
void (*ector_destroy) (void *data, Ector_Surface *surface); 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_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, Ector_Renderer *r, Eina_Array *clips, 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, 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 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 (!im)
{ {
if (err) *err = EVAS_LOAD_ERROR_GENERIC; if (err) *err = EVAS_LOAD_ERROR_GENERIC;
ERR("No image provided.");
return NULL; 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 (!im_new)
{ {
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
ERR("Rotation failed.");
return im; return im;
} }
evas_gl_common_image_free(im); evas_gl_common_image_free(im);
@ -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 (!im->tex->pt->dyn.data)
{ {
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
ERR("Ressource allocation failed.");
return im; return im;
} }
im->tex->pt->dyn.checked_out++; 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 (!ok)
{ {
if (err) *err = EVAS_LOAD_ERROR_GENERIC; if (err) *err = EVAS_LOAD_ERROR_GENERIC;
ERR("Lock failed.");
return NULL; 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 (!im_new)
{ {
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
ERR("Allocation failed.");
return NULL; return NULL;
} }
@ -840,6 +845,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
if (!ok) if (!ok)
{ {
if (err) *err = EVAS_LOAD_ERROR_GENERIC; if (err) *err = EVAS_LOAD_ERROR_GENERIC;
ERR("Unlock failed.");
return NULL; return NULL;
} }
*image_data = im_new->im->image.data; *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); evas_gl_common_image_free(im);
im = im2; im = im2;
} }
evas_gl_common_image_dirty(im, 0, 0, 0, 0);
break; break;
case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422P709_PL:
@ -2460,7 +2467,7 @@ _evas_render_op_to_ector_rop(Evas_Render_Op op)
} }
static void 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_GL_Image *dst = surface;
Evas_Engine_GL_Context *gc; 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); 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 static void
eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector, eng_ector_free(void *engine_data)
void *surface, int x, int y, Eina_Bool do_async EINA_UNUSED) {
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; Evas_Engine_GL_Context *gl_context;
Render_Engine_GL_Generic *re = data; Render_Engine_GL_Generic *re = data;
Evas_GL_Ector *buffer = engine_data;
int w, h; int w, h;
void *temp;
re->window_use(re->software.ob); re->window_use(re->software.ob);
gl_context = re->window_gl_context_get(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; w = gl_context->w; h = gl_context->h;
temp = software_buffer; if (!buffer->gl || buffer->gl->w != w || buffer->gl->h != h)
software_buffer = realloc(software_buffer, sizeof (unsigned int) * w * h);
if (!software_buffer)
{ {
ERR("Realloc failed!!"); int err = EVAS_LOAD_ERROR_NONE;
software_buffer = temp;
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 ; return ;
} }
memset(software_buffer, 0, sizeof (unsigned int) * w * h); /* 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(buffer->software, 0, sizeof (unsigned int) * w * h);
if (use_cairo) if (use_cairo)
{ {
eo_do(ector, 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)); ector_surface_reference_point_set(x, y));
} }
else else
{ {
eo_do(ector, 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)); ector_surface_reference_point_set(x, y));
} }
} }
static void static void
eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector, 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; Evas_Engine_GL_Context *gl_context;
Render_Engine_GL_Generic *re = data; Render_Engine_GL_Generic *re = data;
Evas_GL_Image *im; Evas_GL_Ector *buffer = engine_data;
int w, h; int w, h;
Eina_Bool mul_use; Eina_Bool mul_use;
@ -2592,7 +2641,7 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
ector_software_surface_set(NULL, 0, 0)); 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) if (!mul_use)
{ {
@ -2607,9 +2656,7 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
// Later on, we don't want that information and today when // Later on, we don't want that information and today when
// using GL backend, you just need to turn on Evas_Map on // using GL backend, you just need to turn on Evas_Map on
// the Evas_Object_VG. // 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_draw(gl_context, buffer->gl, 0, 0, w, h, 0, 0, w, h, 0);
evas_gl_common_image_free(im);
// restore gl state // restore gl state
gl_context->dc->mul.use = mul_use; gl_context->dc->mul.use = mul_use;
@ -2764,6 +2811,8 @@ module_open(Evas_Module *em)
ORD(ector_begin); ORD(ector_begin);
ORD(ector_renderer_draw); ORD(ector_renderer_draw);
ORD(ector_end); ORD(ector_end);
ORD(ector_new);
ORD(ector_free);
/* now advertise out own api */ /* now advertise out own api */
em->functions = (void *)(&func); em->functions = (void *)(&func);

View File

@ -3795,7 +3795,7 @@ _draw_thread_ector_draw(void *data)
} }
static void 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_Image *dst = surface;
RGBA_Draw_Context *dc = context; 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); 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 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) if (do_async)
{ {
@ -3963,7 +3974,7 @@ eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface
} }
static void 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) if (do_async)
{ {
@ -4182,7 +4193,9 @@ static Evas_Func func =
eng_ector_destroy, eng_ector_destroy,
eng_ector_begin, eng_ector_begin,
eng_ector_renderer_draw, eng_ector_renderer_draw,
eng_ector_end eng_ector_end,
eng_ector_new,
eng_ector_free
/* FUTURE software generic calls go here */ /* FUTURE software generic calls go here */
}; };