From 9e0670a7051cb7cee928078b362ae8642908902f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 31 Dec 2015 14:33:03 +0900 Subject: [PATCH] Evas filters & Ector GL: Prepare ground work for GL buffers This fixes crashes, adds safety, and notes a couple of things that are not yet implemented: - Make an Evas_GL_Image from an RGBA_Image so we can draw it on the canvas. This means Evas.Ector.GL.RGBA_Image.Buffer - Readable Evas_GL_Image objects with gl_read_pixels --> Implement proper map() & unmap() for GL buffers --- src/lib/evas/filters/evas_filter.c | 12 ++++--- src/lib/evas/include/evas_private.h | 2 +- .../gl_generic/evas_ector_gl_image_buffer.c | 13 +++++--- .../gl_generic/evas_ector_gl_image_buffer.eo | 2 +- .../evas/engines/gl_generic/evas_engine.c | 27 +++++++++++++--- .../evas_ector_software_buffer.c | 31 +++++++++++-------- .../engines/software_generic/evas_engine.c | 2 +- 7 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index b3068d7466..801c5a6d05 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -40,6 +40,8 @@ _evas_image_get(Ector_Buffer *buf) { void *image = NULL; if (!buf) return NULL; + /* FIXME: This MAY return RGBA_Image because engine_image_set MAY pass an + * RGBA_Image... Baaaaah */ eo_do(buf, evas_ector_buffer_engine_image_get(NULL, &image)); return image; } @@ -73,7 +75,7 @@ evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async) if (ctx->gl_engine) { // FIXME!!! - CRI("gl support not implemented"); + ERR("GL support not fully implemented! Repair work is in progress!"); } return ctx; } @@ -142,7 +144,7 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, } _filter_buffer_backing_free(fb); XDBG("Source #%d '%s' has dimensions %dx%d", fb->id, fb->source_name, fb->w, fb->h); - fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface); + fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface, EINA_FALSE); fb->alpha_only = EINA_FALSE; } } @@ -204,7 +206,7 @@ _ector_buffer_create(Evas_Filter_Buffer const *fb, void *data) // This should be fixed by implementing full support in ector // Note: dropped support for cserve2, that was not needed anyway - cspace = fb->alpha_only ? E_ALPHA : E_ARGB; + cspace = fb->alpha_only ? EVAS_COLORSPACE_GRY8 : EVAS_COLORSPACE_ARGB8888; #if 0 // ideal code return fb->ENFN->ector_buffer_new(fb->ENDT, fb->ctx->evas->evas, @@ -230,7 +232,7 @@ _ector_buffer_create(Evas_Filter_Buffer const *fb, void *data) data = ((RGBA_Image *) ie)->image.data; memset(data, 0, fb->w * fb->h * (fb->alpha_only ? 1 : 4)); } - return fb->ENFN->ector_buffer_wrap(fb->ENDT, fb->ctx->evas->evas, ie); + return fb->ENFN->ector_buffer_wrap(fb->ENDT, fb->ctx->evas->evas, ie, EINA_TRUE); } Eina_Bool @@ -396,7 +398,7 @@ _filter_buffer_new_from_evas_surface(Evas_Filter_Context *ctx, void *image) fb->id = ++(ctx->last_buffer_id); fb->ctx = ctx; - fb->buffer = ENFN->ector_buffer_wrap(ENDT, ctx->evas->evas, image); + fb->buffer = ENFN->ector_buffer_wrap(ENDT, ctx->evas->evas, image, EINA_FALSE); ENFN->image_size_get(ENDT, image, &fb->w, &fb->h); fb->alpha_only = (ENFN->image_colorspace_get(ENDT, image) == EVAS_COLORSPACE_GRY8); diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 8ca3c2b7f1..b9f8a33733 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1450,7 +1450,7 @@ struct _Evas_Func Ector_Surface *(*ector_create) (void *data); void (*ector_destroy) (void *data, Ector_Surface *surface); - Ector_Buffer *(*ector_buffer_wrap) (void *data, Evas *e, void *engine_image); + Ector_Buffer *(*ector_buffer_wrap) (void *data, Evas *e, void *engine_image, Eina_Bool is_rgba_image); Ector_Buffer *(*ector_buffer_new) (void *data, Evas *e, void *pixels, int width, int height, int stride, Efl_Gfx_Colorspace cspace, Eina_Bool writeable, int l, int r, int t, int b, Ector_Buffer_Flag flags); 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); diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c index 101f0d9b99..c8de1d8aad 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c @@ -42,8 +42,7 @@ _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ect } pd->evas = eo_xref(evas, obj); - pd->image = ENFN->image_ref(ENDT, im); - if (!pd->image) return; + EINA_SAFETY_ON_NULL_RETURN(im); if (im->tex && im->tex->pt) { @@ -60,9 +59,11 @@ _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ect if (!im->tex->pt->fb) l = r = t = b = 1; } + + pd->image = ENFN->image_ref(ENDT, im); eo_do(obj, ector_gl_buffer_base_attach(im->tex->pt->texture, im->tex->pt->fb, - evas_gl_common_gl_format_to_colorspace(im->tex->pt->format), + (Efl_Gfx_Colorspace) evas_gl_common_gl_format_to_colorspace(im->tex->pt->format), im->tex->w, im->tex->h, im->tex->x, im->tex->y, im->tex->pt->w, im->tex->pt->h, @@ -70,7 +71,9 @@ _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ect } else { - ERR("What do we do now?"); + // FIXME: This might be required to support texture upload here + ERR("Image has no attached texture! Unsupported!"); + pd->image = NULL; } } @@ -87,7 +90,7 @@ EOLIAN static Eo_Base * _evas_ector_gl_image_buffer_eo_base_constructor(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd) { eo_do_super(obj, MY_CLASS, obj = eo_constructor()); - pd->base = eo_data_ref(obj, ECTOR_GL_BUFFER_CLASS); + pd->base = eo_data_ref(obj, ECTOR_GL_BUFFER_BASE_MIXIN); pd->base->generic = eo_data_ref(obj, ECTOR_GENERIC_BUFFER_MIXIN); pd->base->generic->eo = obj; return obj; diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo index 0b72cda8a9..82cebb4e3d 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo @@ -1,4 +1,4 @@ -class Evas.Ector.GL.Image.Buffer (Evas.Ector.GL.Buffer) +class Evas.Ector.GL.Image.Buffer (Evas.Ector.GL.Buffer, Evas.Ector.Buffer) { [[An Ector GL buffer wrapping an existing Evas_GL_Image.]] legacy_prefix: null; diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 78a73f41d1..27aae7fe1b 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -4,6 +4,10 @@ #include "software/Ector_Software.h" #include "cairo/Ector_Cairo.h" #include "gl/Ector_GL.h" +#include "evas_ector_buffer.eo.h" +#include "evas_ector_gl_buffer.eo.h" +#include "evas_ector_gl_image_buffer.eo.h" +#include "../software_generic/evas_ector_software_buffer.eo.h" #if defined HAVE_DLSYM && ! defined _WIN32 # include /* dlopen,dlclose,etc */ @@ -2465,10 +2469,25 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector) } static Ector_Buffer * -eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image) +eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image, Eina_Bool is_rgba_image) { -#warning FIXME: implement me - return NULL; + Ector_Buffer *buf = NULL; + EINA_SAFETY_ON_NULL_RETURN_VAL(engine_image, NULL); + if (is_rgba_image) + { + Image_Entry *ie = engine_image; + + buf = eo_add(EVAS_ECTOR_SOFTWARE_BUFFER_CLASS, e, + evas_ector_buffer_engine_image_set(e, ie)); + } + else + { + Evas_GL_Image *im = engine_image; + + buf = eo_add(EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS, e, + evas_ector_buffer_engine_image_set(e, im)); + } + return buf; } static Ector_Buffer * @@ -2477,7 +2496,7 @@ eng_ector_buffer_new(void *data EINA_UNUSED, Evas *e, void *pixels, Efl_Gfx_Colorspace cspace, Eina_Bool writeable, int l, int r, int t, int b, Ector_Buffer_Flag flags) { -#warning FIXME: implement me + CRI("Not implemented."); return NULL; } diff --git a/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c b/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c index 22efa05329..d46b2c1119 100644 --- a/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c +++ b/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c @@ -5,7 +5,6 @@ #include #include "evas_common_private.h" #include "evas_private.h" -#include "draw.h" #include "evas_ector_buffer.eo.h" #include "evas_ector_software_buffer.eo.h" @@ -15,28 +14,26 @@ typedef struct { Ector_Software_Buffer_Base_Data *base; Evas *evas; - Image_Entry *image; + RGBA_Image *image; } Evas_Ector_Software_Buffer_Data; -#define ENFN e->engine.func -#define ENDT e->engine.data.output +// Note: Don't use ENFN, ENDT here because the GL engine may also use SW buffers +// eg. in the filters. EOLIAN static void _evas_ector_software_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_Software_Buffer_Data *pd, Evas *evas, void *image) { - Evas_Public_Data *e = eo_data_scope_get(evas, EVAS_CANVAS_CLASS); - Image_Entry *ie = image; - RGBA_Image *im; + RGBA_Image *im = image; Eina_Bool b; + EINA_SAFETY_ON_NULL_RETURN(image); if (eo_do_ret(obj, b, eo_finalized_get())) { CRI("engine_image must be set at construction time only"); return; } - im = (RGBA_Image *) ie; if (!im->image.data) { CRI("image has no pixels yet"); @@ -44,12 +41,13 @@ _evas_ector_software_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ect } pd->evas = eo_xref(evas, obj); - pd->image = ENFN->image_ref(ENDT, ie); + evas_cache_image_ref(&im->cache_entry); + pd->image = im; if (!pd->image) return; eo_do(obj, ector_buffer_pixels_set(im->image.data, im->cache_entry.w, im->cache_entry.h, 0, - im->cache_entry.space, + (Efl_Gfx_Colorspace) im->cache_entry.space, EINA_TRUE, 0, 0, 0, 0)); } @@ -58,7 +56,16 @@ _evas_ector_software_buffer_evas_ector_buffer_engine_image_get(Eo *obj EINA_UNUS Evas_Ector_Software_Buffer_Data *pd, Evas **evas, void **image) { + Evas_Public_Data *e = eo_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); + if (evas) *evas = pd->evas; + if (e->engine.func->gl_surface_read_pixels) + { + ERR("Invalid: requesting engine_image from a GL image from a simple SW buffer!"); + if (image) *image = NULL; + return; + } + if (image) *image = pd->image; } @@ -82,10 +89,8 @@ _evas_ector_software_buffer_eo_base_finalize(Eo *obj, Evas_Ector_Software_Buffer EOLIAN static void _evas_ector_software_buffer_eo_base_destructor(Eo *obj, Evas_Ector_Software_Buffer_Data *pd) { - Evas_Public_Data *e = eo_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); - eo_data_xunref(obj, pd->base, obj); - ENFN->image_free(ENDT, pd->image); + evas_cache_image_drop(&pd->image->cache_entry); eo_xunref(pd->evas, obj); eo_do_super(obj, MY_CLASS, eo_destructor()); } diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index a32c7e60c6..06d2a5d4ca 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -3758,7 +3758,7 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector) } static Ector_Buffer * -eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image) +eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image, Eina_Bool is_rgba_image EINA_UNUSED) { Image_Entry *ie = engine_image; Ector_Buffer *buf = NULL;