From 2ef8d6f39af839c23551239216cea100254f80df Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Wed, 18 Jan 2017 11:47:25 +0900 Subject: [PATCH] evas filters: Refactor ector and gfx filters A LOT Alright, so this is a massive patch that is the result of trying to get rid of unused or poorly implemented classes in ector. Originally ector was meant to support VG but extend to things like filters as well. At the moment, ector's design makes it quite hard to plug in the filters. For now I think it's easier to implement the GL support for the filters directly in the engine, where I hope to interfere as little as possible. This massive patch keeps only the required minimum to support a versatile gl buffer that can be mapped, drawn or rendered to (FBO). It's extremely inefficient as it relies on glReadPixels and lots of texture uploads, as well as conversions between ARGB and Alpha. Another type of GL buffer is a wrap around an existing GL image, but that one is read-only (map or draw: no write map, no FBO). No, all the filters run fine, and the high-level implementation (evas_filters.c) does not need to know whether the underlying engine is SW or GL. One problem though appears with the blending or blurring of some Alpha buffers, the colors are wrong. This patch removes more lines than it adds so it must be good ;) --- src/Makefile_Ector.am | 6 - src/Makefile_Evas.am | 2 - src/bin/elementary/test_gfx_filters.c | 22 +- .../cairo/ector_cairo_software_surface.c | 7 +- src/lib/ector/ector_buffer.c | 9 - src/lib/ector/ector_buffer.eo | 38 +- src/lib/ector/ector_buffer.h | 15 - src/lib/ector/ector_renderer.h | 1 - src/lib/ector/ector_renderer_buffer.c | 45 -- src/lib/ector/ector_renderer_buffer.eo | 17 - src/lib/ector/gl/Ector_GL.h | 1 - src/lib/ector/gl/ector_gl_buffer.eo | 2 +- src/lib/ector/gl/ector_gl_buffer_base.c | 65 --- src/lib/ector/gl/ector_gl_buffer_base.eo | 60 --- src/lib/ector/software/Ector_Software.h | 1 - .../software/ector_renderer_software_buffer.c | 72 --- .../ector_renderer_software_buffer.eo | 20 - .../ector/software/ector_software_buffer.c | 138 ++--- .../software/ector_software_buffer_base.eo | 2 - .../ector/software/ector_software_private.h | 2 - .../software/ector_software_rasterizer.c | 49 -- .../ector/software/ector_software_surface.c | 13 +- src/lib/evas/filters/evas_filter.c | 494 +++++++----------- src/lib/evas/filters/evas_filter_parser.c | 146 +++--- src/lib/evas/filters/evas_filter_private.h | 12 +- src/lib/evas/include/evas_ector_buffer.eo | 43 +- src/lib/evas/include/evas_filter.h | 19 +- src/lib/evas/include/evas_private.h | 4 +- .../evas/engines/gl_common/evas_gl_common.h | 1 + .../evas/engines/gl_common/evas_gl_image.c | 61 +++ .../evas/engines/gl_common/evas_gl_texture.c | 1 + .../engines/gl_generic/evas_ector_gl_buffer.c | 344 ++++++++++++ .../gl_generic/evas_ector_gl_buffer.eo | 36 +- .../gl_generic/evas_ector_gl_image_buffer.c | 281 +++++----- .../gl_generic/evas_ector_gl_image_buffer.eo | 11 +- .../evas_ector_gl_rgbaimage_buffer.c | 117 ----- .../evas_ector_gl_rgbaimage_buffer.eo | 10 - .../evas/engines/gl_generic/evas_engine.c | 90 +--- .../gl_generic/filters/gl_filter_blend.c | 37 +- .../evas_ector_software_buffer.c | 60 +-- .../evas_ector_software_buffer.eo | 5 +- .../engines/software_generic/evas_engine.c | 75 +-- .../filters/evas_filter_displace.c | 4 +- .../filters/evas_filter_fill.c | 10 +- .../filters/evas_filter_mask.c | 6 +- 45 files changed, 1088 insertions(+), 1366 deletions(-) delete mode 100644 src/lib/ector/ector_renderer_buffer.c delete mode 100644 src/lib/ector/ector_renderer_buffer.eo delete mode 100644 src/lib/ector/gl/ector_gl_buffer_base.c delete mode 100644 src/lib/ector/gl/ector_gl_buffer_base.eo delete mode 100644 src/lib/ector/software/ector_renderer_software_buffer.c delete mode 100644 src/lib/ector/software/ector_renderer_software_buffer.eo delete mode 100644 src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.c delete mode 100644 src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.eo diff --git a/src/Makefile_Ector.am b/src/Makefile_Ector.am index df6e6d2532..7baa0767d1 100644 --- a/src/Makefile_Ector.am +++ b/src/Makefile_Ector.am @@ -5,7 +5,6 @@ ector_eolian_files_generic = \ lib/ector/ector_buffer.eo \ lib/ector/ector_renderer.eo \ lib/ector/ector_renderer_shape.eo \ - lib/ector/ector_renderer_buffer.eo \ lib/ector/ector_renderer_gradient.eo \ lib/ector/ector_renderer_gradient_radial.eo \ lib/ector/ector_renderer_gradient_linear.eo @@ -28,7 +27,6 @@ ector_eolian_files_software = \ lib/ector/software/ector_software_buffer_base.eo \ lib/ector/software/ector_renderer_software.eo \ lib/ector/software/ector_renderer_software_shape.eo \ - lib/ector/software/ector_renderer_software_buffer.eo \ lib/ector/software/ector_renderer_software_gradient_radial.eo \ lib/ector/software/ector_renderer_software_gradient_linear.eo ector_eolian_software_h = $(ector_eolian_files_software:%.eo=%.eo.h) @@ -37,7 +35,6 @@ ector_eolian_software_h = $(ector_eolian_files_software:%.eo=%.eo.h) ector_eolian_files_gl = \ lib/ector/gl/ector_gl_surface.eo \ lib/ector/gl/ector_gl_buffer.eo \ - lib/ector/gl/ector_gl_buffer_base.eo \ lib/ector/gl/ector_renderer_gl.eo \ lib/ector/gl/ector_renderer_gl_shape.eo \ lib/ector/gl/ector_renderer_gl_gradient_radial.eo \ @@ -84,7 +81,6 @@ lib/ector/ector_gl_internal.h \ lib/ector/ector_buffer.c \ lib/ector/ector_renderer_shape.c \ lib/ector/ector_renderer.c \ -lib/ector/ector_renderer_buffer.c \ lib/ector/ector_renderer_gradient.c \ lib/ector/ector_renderer_gradient_radial.c \ lib/ector/ector_renderer_gradient_linear.c @@ -121,7 +117,6 @@ lib_ector_libector_la_SOURCES += \ lib/ector/software/ector_renderer_software_gradient_linear.c \ lib/ector/software/ector_renderer_software_gradient_radial.c \ lib/ector/software/ector_renderer_software_shape.c \ -lib/ector/software/ector_renderer_software_buffer.c \ lib/ector/software/ector_software_gradient.c \ lib/ector/software/ector_software_rasterizer.c \ lib/ector/software/ector_software_surface.c \ @@ -138,7 +133,6 @@ lib/ector/gl/ector_renderer_gl_gradient_radial.c \ lib/ector/gl/ector_renderer_gl_shape.c \ lib/ector/gl/ector_renderer_gl.c \ lib/ector/gl/ector_gl_buffer.c \ -lib/ector/gl/ector_gl_buffer_base.c \ lib/ector/gl/ector_gl_surface.c \ lib/ector/gl/ector_gl_private.h \ lib/ector/gl/shader/ector_gl_shaders.x \ diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index f925cdab65..83557dfb92 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -842,7 +842,6 @@ modules/evas/engines/gl_generic/Evas_Engine_GL_Generic.h \ modules/evas/engines/gl_generic/Evas_Engine_GL_Shared.h \ modules/evas/engines/gl_generic/evas_ector_gl_buffer.c \ modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c \ -modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.c \ modules/evas/engines/gl_generic/filters/gl_engine_filter.h \ modules/evas/engines/gl_generic/filters/gl_filter_blend.c \ $(NULL) @@ -850,7 +849,6 @@ $(NULL) evas_gl_generic_eolian_files = \ modules/evas/engines/gl_generic/evas_ector_gl_buffer.eo \ modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo \ -modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.eo \ $(NULL) evas_gl_generic_eolian_c = $(evas_gl_generic_eolian_files:%.eo=%.eo.c) diff --git a/src/bin/elementary/test_gfx_filters.c b/src/bin/elementary/test_gfx_filters.c index b9855292ca..d67f616ac8 100644 --- a/src/bin/elementary/test_gfx_filters.c +++ b/src/bin/elementary/test_gfx_filters.c @@ -47,6 +47,8 @@ static const Filter_Image images_anim[] = { /* builtin filter examples */ static const Filter templates[] = { { "Custom", NULL, NULL }, + { "Simple blend", + "blend { color = 'darkblue' }", NULL }, { "Black shadow", "if not myColor then myColor = color('yellow') end\n" "blur { 6, ox = 2, oy = 2, color = 'black' }\n" @@ -521,13 +523,19 @@ test_gfx_filters(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *eve efl_ui_text_scrollable_set(efl_added, 1)); efl_event_callback_add(o, EFL_UI_TEXT_EVENT_CHANGED_USER, _code_changed, win); - // Insert filter code inside style string: DEFAULT='blah blah ' - buf = eina_strbuf_new(); - eina_strbuf_append(buf, efl_canvas_text_style_get(o, NULL)); - eina_strbuf_insert(buf, " gfx_filter=code", eina_strbuf_length_get(buf) - 1); - efl_gfx_filter_program_set(o, code_filter, "code"); - efl_canvas_text_style_set(o, NULL, eina_strbuf_string_get(buf)); - eina_strbuf_free(buf); + // HACK: For now only set filter on code if engine is not GL (WIP) + const char *engine = ecore_evas_engine_name_get + (ecore_evas_ecore_evas_get(evas_object_evas_get(win))); + if (engine && !strstr(engine, "gl")) + { + // Insert filter code inside style string: DEFAULT='blah blah ' + buf = eina_strbuf_new(); + eina_strbuf_append(buf, efl_canvas_text_style_get(o, NULL)); + eina_strbuf_insert(buf, " gfx_filter=code", eina_strbuf_length_get(buf) - 1); + efl_gfx_filter_program_set(o, code_filter, "code"); + efl_canvas_text_style_set(o, NULL, eina_strbuf_string_get(buf)); + eina_strbuf_free(buf); + } // FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME // Efl.Ui.Text doesn't seem to trigger the proper events during edit diff --git a/src/lib/ector/cairo/ector_cairo_software_surface.c b/src/lib/ector/cairo/ector_cairo_software_surface.c index d96fdd517e..98dd8e0a4f 100644 --- a/src/lib/ector/cairo/ector_cairo_software_surface.c +++ b/src/lib/ector/cairo/ector_cairo_software_surface.c @@ -51,9 +51,8 @@ struct _Ector_Cairo_Software_Surface_Data EOLIAN static Eina_Bool _ector_cairo_software_surface_ector_buffer_pixels_set(Eo *obj, Ector_Cairo_Software_Surface_Data *pd, - void *pixels, int width, int height, int stride, - Efl_Gfx_Colorspace cspace, Eina_Bool writable, - unsigned char l, unsigned char r, unsigned char t, unsigned char b) + void *pixels, int width, int height, + Efl_Gfx_Colorspace cspace, Eina_Bool writable) { cairo_t *ctx = NULL; Eina_Bool ok = EINA_FALSE; @@ -73,7 +72,7 @@ _ector_cairo_software_surface_ector_buffer_pixels_set(Eo *obj, Ector_Cairo_Softw cairo_surface_destroy(pd->surface); pd->surface = NULL; - ok = ector_buffer_pixels_set(efl_super(obj, MY_CLASS), pixels, width, height, stride, cspace, writable, l, r, t, b); + ok = ector_buffer_pixels_set(efl_super(obj, MY_CLASS), pixels, width, height, cspace, writable); if (ok && pixels) { diff --git a/src/lib/ector/ector_buffer.c b/src/lib/ector/ector_buffer.c index 9fe9ed6930..51dbd1496a 100644 --- a/src/lib/ector/ector_buffer.c +++ b/src/lib/ector/ector_buffer.c @@ -14,15 +14,6 @@ _ector_buffer_cspace_get(Eo *obj EINA_UNUSED, Ector_Buffer_Data *pd) return pd->cspace; } -EOLIAN static void -_ector_buffer_border_get(Eo *obj EINA_UNUSED, Ector_Buffer_Data *pd EINA_UNUSED, int *l, int *r, int *t, int *b) -{ - if (l) *l = pd->l; - if (r) *r = pd->r; - if (t) *t = pd->t; - if (b) *b = pd->b; -} - EOLIAN static void _ector_buffer_size_get(Eo *obj EINA_UNUSED, Ector_Buffer_Data *pd, int *w, int *h) { diff --git a/src/lib/ector/ector_buffer.eo b/src/lib/ector/ector_buffer.eo index 0b8782ff68..f90bb1df1d 100644 --- a/src/lib/ector/ector_buffer.eo +++ b/src/lib/ector/ector_buffer.eo @@ -24,6 +24,7 @@ enum Ector.Buffer.Access_Flag { mixin Ector.Buffer { [[2D pixel buffer interface for Ector + @since 1.17 ]] eo_prefix: ector_buffer; @@ -76,38 +77,11 @@ mixin Ector.Buffer @in pixels: void_ptr; [[If $null, allocates an empty buffer]] @in width: int; [[Buffer width]] @in height: int; [[Buffer height]] - @in stride: int; [[Can be 0]] @in cspace: Efl.Gfx.Colorspace; [[Buffer colorspace]] @in writable: bool; [[Buffer is writable]] - @in l: ubyte; [[Left border pixels, usually 0 or 1]] - @in r: ubyte; [[Right border pixels, usually 0 or 1]] - @in t: ubyte; [[Top border pixels, usually 0 or 1]] - @in b: ubyte; [[Bottom border pixels, usually 0 or 1]] } return: bool; [[True if pixels_set was successful]] } - span_get @pure_virtual { - [[Get a single horizontal span of length w starting from (x,y) - - Call span_free() to release it. This function will try not to - allocate any new buffer, whenever possible. This means the data - might be mapped directly from the backing memory buffer. - ]] - params { - @in x: int; [[Ranges from -l to w+r-1]] - @in y: int; [[Ranges from -t to h+b-1]] - @in w: uint; [[Ranges from 1 to w+l+r]] - @in cspace: Efl.Gfx.Colorspace; [[Requested colorspace, may trigger conversion on the fly.]] - @out length: uint; [[Length in bytes of the returned buffer]] - } - return: ptr(uint8); [[A temporary memory buffer containing the pixels requested.]] - } - span_free @pure_virtual { - [[Must be called as soon as possible after span_get]] - params { - data: ptr(uint8); [[Data to be freed]] - } - } @property flags { [[The capabilities of this buffer]] get {} @@ -115,16 +89,6 @@ mixin Ector.Buffer flag: Ector.Buffer.Flag; [[A bitmask of capability flags]] } } - @property border { - [[Duplicated pixel borders of this buffer, used for GL scaling]] - get {} - values { - l: int; [[Left border]] - r: int; [[Right border]] - t: int; [[Top border]] - b: int; [[Bottom border]] - } - } } events { detached; [[Emitted whenever the previously attached pixels are detached during pixels_set]] diff --git a/src/lib/ector/ector_buffer.h b/src/lib/ector/ector_buffer.h index e19c7fe4a6..9c91bfd4a4 100644 --- a/src/lib/ector/ector_buffer.h +++ b/src/lib/ector/ector_buffer.h @@ -18,13 +18,11 @@ typedef Eo Ector_Buffer; typedef struct _Ector_Buffer_Data Ector_Buffer_Data; typedef struct _Ector_Software_Buffer_Base_Data Ector_Software_Buffer_Base_Data; -typedef struct _Ector_GL_Buffer_Base_Data Ector_GL_Buffer_Base_Data; struct _Ector_Buffer_Data { Ector_Buffer *eo; unsigned int w, h; - unsigned char l, r, t, b; Efl_Gfx_Colorspace cspace; Eina_Bool immutable : 1; // pixels_set is forbidden }; @@ -45,17 +43,4 @@ struct _Ector_Software_Buffer_Base_Data Eina_Bool nofree : 1; // pixel data should not be free()'ed }; -struct _Ector_GL_Buffer_Base_Data -{ - Ector_Buffer_Data *generic; - int texid; - int fboid; - struct { - // x,y offset within the atlas - // w,h size of the atlas itself - int x, y, w, h; - } atlas; - Eina_Bool whole : 1; -}; - #endif diff --git a/src/lib/ector/ector_renderer.h b/src/lib/ector/ector_renderer.h index e2e2e65f58..c8d20d2fb3 100644 --- a/src/lib/ector/ector_renderer.h +++ b/src/lib/ector/ector_renderer.h @@ -3,7 +3,6 @@ #include "ector_renderer.eo.h" #include "ector_renderer_shape.eo.h" -#include "ector_renderer_buffer.eo.h" #include "ector_renderer_gradient.eo.h" #include "ector_renderer_gradient_linear.eo.h" #include "ector_renderer_gradient_radial.eo.h" diff --git a/src/lib/ector/ector_renderer_buffer.c b/src/lib/ector/ector_renderer_buffer.c deleted file mode 100644 index 56bb6f13e1..0000000000 --- a/src/lib/ector/ector_renderer_buffer.c +++ /dev/null @@ -1,45 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#else -# define EFL_BETA_API_SUPPORT -#endif - -#include -#include "ector_private.h" -#include "ector_renderer_buffer.eo.h" - -#define MY_CLASS ECTOR_RENDERER_BUFFER_MIXIN - -EOLIAN static void -_ector_renderer_buffer_efl_gfx_fill_fill_get(Eo *obj EINA_UNUSED, Ector_Renderer_Buffer_Data *pd, int *x, int *y, int *w, int *h) -{ - if (x) *x = pd->fill.x; - if (y) *y = pd->fill.y; - if (w) *w = pd->fill.w; - if (h) *h = pd->fill.h; -} - -EOLIAN static void -_ector_renderer_buffer_efl_gfx_fill_fill_set(Eo *obj EINA_UNUSED, Ector_Renderer_Buffer_Data *pd, int x, int y, int w, int h) -{ - if (w < 0) w = 0; - if (h < 0) h = 0; - pd->fill.x = x; - pd->fill.y = y; - pd->fill.w = w; - pd->fill.h = h; -} - -EOLIAN static void -_ector_renderer_buffer_buffer_set(Eo *obj EINA_UNUSED, Ector_Renderer_Buffer_Data *pd, Ector_Buffer *buf) -{ - _efl_xrefplace(&pd->eo_buffer, buf, obj); -} - -EOLIAN static Ector_Buffer * -_ector_renderer_buffer_buffer_get(Eo *obj EINA_UNUSED, Ector_Renderer_Buffer_Data *pd) -{ - return pd->eo_buffer; -} - -#include "ector_renderer_buffer.eo.c" diff --git a/src/lib/ector/ector_renderer_buffer.eo b/src/lib/ector/ector_renderer_buffer.eo deleted file mode 100644 index b3e97d2053..0000000000 --- a/src/lib/ector/ector_renderer_buffer.eo +++ /dev/null @@ -1,17 +0,0 @@ -mixin Ector.Renderer.Buffer (Efl.Interface, Ector.Renderer, Efl.Gfx.Fill) -{ - [[Ector buffers have a default fill set to repeat]] - eo_prefix: ector_renderer_buffer; - methods { - @property buffer { - set { [[Sets the source buffer for this renderer, adds a ref]] } - get { [[Return the current source, no ref change]] } - values { - buf: Ector.Buffer; [[Buffer]] - } - } - } - implements { - Efl.Gfx.Fill.fill { get; set; } - } -} diff --git a/src/lib/ector/gl/Ector_GL.h b/src/lib/ector/gl/Ector_GL.h index 04d76c0af1..df6ece47b7 100644 --- a/src/lib/ector/gl/Ector_GL.h +++ b/src/lib/ector/gl/Ector_GL.h @@ -15,7 +15,6 @@ typedef Eo Ector_Cairo_Surface; typedef unsigned int GLuint; typedef short GLshort; -#include "gl/ector_gl_buffer_base.eo.h" #include "gl/ector_gl_buffer.eo.h" #include "gl/ector_gl_surface.eo.h" #include "gl/ector_renderer_gl.eo.h" diff --git a/src/lib/ector/gl/ector_gl_buffer.eo b/src/lib/ector/gl/ector_gl_buffer.eo index 67b96ae4e9..03171eac8c 100644 --- a/src/lib/ector/gl/ector_gl_buffer.eo +++ b/src/lib/ector/gl/ector_gl_buffer.eo @@ -1,4 +1,4 @@ -class Ector.GL.Buffer (Efl.Object, Ector.GL.Buffer.Base) +class Ector.GL.Buffer (Efl.Object, Ector.Buffer) { [[Ector GL buffer class]] data: null; diff --git a/src/lib/ector/gl/ector_gl_buffer_base.c b/src/lib/ector/gl/ector_gl_buffer_base.c deleted file mode 100644 index 954988a0fb..0000000000 --- a/src/lib/ector/gl/ector_gl_buffer_base.c +++ /dev/null @@ -1,65 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "Ector_GL.h" -#include "ector_gl_private.h" -#include "ector_buffer.h" -#include "ector_gl_buffer_base.eo.h" - -#define MY_CLASS ECTOR_GL_BUFFER_BASE_MIXIN - -EOLIAN static int -_ector_gl_buffer_base_texture_get(Eo *obj EINA_UNUSED, Ector_GL_Buffer_Base_Data *pd) -{ - return pd->texid; -} - -EOLIAN static int -_ector_gl_buffer_base_fbo_get(Eo *obj EINA_UNUSED, Ector_GL_Buffer_Base_Data *pd) -{ - return pd->fboid; -} - -EOLIAN static Eina_Bool -_ector_gl_buffer_base_whole_get(Eo *obj EINA_UNUSED, Ector_GL_Buffer_Base_Data *pd) -{ - return pd->whole; -} - -EOLIAN static void -_ector_gl_buffer_base_vertices_get(Eo *obj EINA_UNUSED, Ector_GL_Buffer_Base_Data *pd, double *x, double *y, double *w, double *h) -{ - if (x) *x = (double) pd->atlas.x / pd->atlas.w; - if (y) *y = (double) pd->atlas.y / pd->atlas.h; - if (w) *w = (double) pd->generic->w / pd->atlas.w; - if (h) *h = (double) pd->generic->h / pd->atlas.h; -} - -EOLIAN static void -_ector_gl_buffer_base_attach(Eo *obj EINA_UNUSED, Ector_GL_Buffer_Base_Data *pd, - int texid, int fboid, Efl_Gfx_Colorspace cspace, - int imw, int imh, int tx, int ty, int tw, int th, - int l, int r, int t, int b) -{ - EINA_SAFETY_ON_NULL_RETURN(pd->generic); - EINA_SAFETY_ON_FALSE_RETURN(!pd->generic->immutable); - - pd->generic->cspace = cspace; - pd->generic->w = imw; - pd->generic->h = imh; - pd->atlas.x = tx; - pd->atlas.y = ty; - pd->atlas.w = tw; - pd->atlas.h = th; - pd->generic->l = l; - pd->generic->r = r; - pd->generic->t = t; - pd->generic->b = b; - if (!(tx - l) && !(ty - t) && ((tw + l + r) == imw) && ((th + t + b) == imh)) - pd->whole = EINA_TRUE; - pd->fboid = fboid; - pd->texid = texid; -} - -#include "ector_gl_buffer_base.eo.c" diff --git a/src/lib/ector/gl/ector_gl_buffer_base.eo b/src/lib/ector/gl/ector_gl_buffer_base.eo deleted file mode 100644 index 2a1718246b..0000000000 --- a/src/lib/ector/gl/ector_gl_buffer_base.eo +++ /dev/null @@ -1,60 +0,0 @@ -mixin Ector.GL.Buffer.Base (Ector.Buffer) -{ - [[Ector GL buffer base class]] - methods { - @property texture { - [[GL texture ID]] - get {} - values { - texid: int; [[GL texture ID]] - } - } - @property fbo { - [[Framebuffer object ID]] - get {} - values { - fboid: int; [[GL framebuffer ID, 0 if there is no FBO]] - } - } - @property whole { - [[If $true, the image is covering the entire GL texture, ie. it's not - part of an atlas. - ]] - get {} - values { - is_whole: bool; [[$true if the image is covering the whole GL texture, $false otherwise]] - } - } - @property vertices { - [[Returns the texture vertices to draw this image with no rotation - - The 4 points are then defined as (x,y), (x+w,y), (x,y+h), (x+w,y+h). - ]] - get {} - values { - x: double; [[X position of this image inside the texture atlas, from 0 to 1]] - y: double; [[Y position of this image inside the texture atlas, from 0 to 1]] - w: double; [[Width of this image inside the texture atlas, from 0 to 1]] - h: double; [[Height of this image inside the texture atlas, from 0 to 1]] - } - } - attach @protected { - [[Attach to an existing texture (or FBO). Used from child classes.]] - params { - texid: int; [[GL texture ID]] - fboid: int; [[Framebuffer object ID]] - cspace: Efl.Gfx.Colorspace; [[Colorspace]] - imw: int; [[Image width]] - imh: int; [[Image height]] - tx: int; [[Texture X coordinate]] - ty: int; [[Texture Y coordinate]] - tw: int; [[Texture width]] - th: int; [[Texture height]] - l: int; [[Left padding]] - r: int; [[Right padding]] - t: int; [[Top padding]] - b: int; [[Bottom padding]] - } - } - } -} diff --git a/src/lib/ector/software/Ector_Software.h b/src/lib/ector/software/Ector_Software.h index f53526c5b2..7c94b895cf 100644 --- a/src/lib/ector/software/Ector_Software.h +++ b/src/lib/ector/software/Ector_Software.h @@ -10,7 +10,6 @@ #include "software/ector_software_buffer_base.eo.h" #include "software/ector_renderer_software.eo.h" #include "software/ector_renderer_software_shape.eo.h" -#include "software/ector_renderer_software_buffer.eo.h" #include "software/ector_renderer_software_gradient_linear.eo.h" #include "software/ector_renderer_software_gradient_radial.eo.h" diff --git a/src/lib/ector/software/ector_renderer_software_buffer.c b/src/lib/ector/software/ector_renderer_software_buffer.c deleted file mode 100644 index 9d524af72e..0000000000 --- a/src/lib/ector/software/ector_renderer_software_buffer.c +++ /dev/null @@ -1,72 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#else -# define EFL_BETA_API_SUPPORT -#endif - -#include -#include "Ector_Software.h" -#include "ector_private.h" -#include "ector_software_private.h" - -#define MY_CLASS ECTOR_RENDERER_SOFTWARE_BUFFER_CLASS - -typedef struct -{ - Ector_Renderer_Data *base; - Software_Rasterizer *surface; - Ector_Buffer *eo_buffer; -} Ector_Renderer_Software_Buffer_Data; - - -EOLIAN static void -_ector_renderer_software_buffer_buffer_set(Eo *obj, Ector_Renderer_Software_Buffer_Data *pd, Ector_Buffer *buf) -{ - _efl_xrefplace(&pd->eo_buffer, buf, obj); -} - -EOLIAN static Ector_Buffer * -_ector_renderer_software_buffer_buffer_get(Eo *obj EINA_UNUSED, Ector_Renderer_Software_Buffer_Data *pd) -{ - return pd->eo_buffer; -} - -EOLIAN static Eina_Bool -_ector_renderer_software_buffer_ector_renderer_software_fill(Eo *obj, Ector_Renderer_Software_Buffer_Data *pd) -{ - Ector_Software_Buffer *buffer = efl_data_scope_get(obj, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN); - ector_software_rasterizer_buffer_set(pd->surface, buffer); - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_ector_renderer_software_buffer_ector_renderer_prepare(Eo *obj, Ector_Renderer_Software_Buffer_Data *pd) -{ - if (!pd->surface) - pd->surface = efl_data_xref(pd->base->surface, ECTOR_SOFTWARE_SURFACE_CLASS, obj); - - return EINA_TRUE; -} - -EOLIAN static unsigned int -_ector_renderer_software_buffer_ector_renderer_crc_get(Eo *obj, Ector_Renderer_Software_Buffer_Data *pd) -{ - Ector_Software_Buffer_Base_Data *buffer = efl_data_scope_get(pd->eo_buffer, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN); - unsigned int crc; - - crc = ector_renderer_crc_get(efl_super(obj, MY_CLASS)); - crc = eina_crc((const char *) buffer, sizeof(*buffer), crc, EINA_FALSE); - if (pd->surface) - crc = eina_crc((const char *) pd->surface, sizeof(*pd->surface), crc, EINA_FALSE); - - return crc; -} - -EOLIAN static void -_ector_renderer_software_buffer_efl_object_destructor(Eo *obj, Ector_Renderer_Software_Buffer_Data *pd) -{ - efl_data_xunref(pd->base->surface, pd->surface, obj); - efl_destructor(efl_super(obj, MY_CLASS)); -} - -#include "ector_renderer_software_buffer.eo.c" diff --git a/src/lib/ector/software/ector_renderer_software_buffer.eo b/src/lib/ector/software/ector_renderer_software_buffer.eo deleted file mode 100644 index 91878f2286..0000000000 --- a/src/lib/ector/software/ector_renderer_software_buffer.eo +++ /dev/null @@ -1,20 +0,0 @@ -class Ector.Renderer.Software.Buffer (Ector.Renderer.Software, Ector.Renderer.Buffer) -{ - [[Ecto software renderer buffer class]] - methods { - @property buffer { - [[Buffer property]] - set {} - get {} - values { - buf: Ector.Buffer; [[Buffer]] - } - } - } - implements { - Ector.Renderer.prepare; - Ector.Renderer.crc { get; } - Ector.Renderer.Software.fill; - Efl.Object.destructor; - } -} diff --git a/src/lib/ector/software/ector_software_buffer.c b/src/lib/ector/software/ector_software_buffer.c index 499206309d..d44962bbec 100644 --- a/src/lib/ector/software/ector_software_buffer.c +++ b/src/lib/ector/software/ector_software_buffer.c @@ -16,24 +16,13 @@ typedef struct _Ector_Software_Buffer_Map { EINA_INLIST; uint8_t *ptr; - unsigned int size; // in bytes + unsigned int size, stride; // in bytes unsigned int x, y, w, h; Efl_Gfx_Colorspace cspace; Eina_Bool allocated; Ector_Buffer_Access_Flag mode; } Ector_Software_Buffer_Map; -static inline int -_min_stride_calc(int width, Efl_Gfx_Colorspace cspace) -{ - switch (cspace) - { - case EFL_GFX_COLORSPACE_ARGB8888: return width * 4; - case EFL_GFX_COLORSPACE_GRY8: return width; - default: return 0; - } -} - /* FIXME: Conversion routines don't belong here */ static inline void _pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len) @@ -64,10 +53,7 @@ _ector_software_buffer_base_pixels_clear(Eo *obj, Ector_Software_Buffer_Base_Dat return; if (pd->internal.maps) - { - CRI("Can not call pixels_clear when the buffer is mapped."); - return; - } + fail("Can not call pixels_clear when the buffer is mapped."); efl_event_callback_call(obj, ECTOR_BUFFER_EVENT_DETACHED, pd->pixels.u8); if (!pd->nofree) @@ -76,54 +62,37 @@ _ector_software_buffer_base_pixels_clear(Eo *obj, Ector_Software_Buffer_Base_Dat } pd->pixels.u8 = NULL; pd->nofree = EINA_FALSE; + + return; + +on_fail: + return; } EOLIAN static Eina_Bool _ector_software_buffer_base_ector_buffer_pixels_set(Eo *obj, Ector_Software_Buffer_Base_Data *pd, - void *pixels, int width, int height, int stride, - Efl_Gfx_Colorspace cspace, Eina_Bool writable, - unsigned char l, unsigned char r, - unsigned char t, unsigned char b) + void *pixels, int width, int height, + Efl_Gfx_Colorspace cspace, Eina_Bool writable) { - unsigned px; + unsigned pxs, stride; if (pd->generic->immutable) - { - ERR("This buffer is immutable."); - return EINA_FALSE; - } + fail("This buffer is immutable."); if (pd->internal.maps) - { - ERR("Can not call pixels_set when the buffer is mapped."); - return EINA_FALSE; - } + fail("Can not call pixels_set when the buffer is mapped."); - // safety check - px = _min_stride_calc(1, cspace); - if (px && ((unsigned long long)(uintptr_t)pixels) & (px - 1)) - ERR("Pixel data is not aligned to %u bytes!", px); + if (cspace == EFL_GFX_COLORSPACE_ARGB8888) + pxs = 4; + else if (cspace == EFL_GFX_COLORSPACE_GRY8) + pxs = 1; + else + fail("Unsupported colorspace: %u", cspace); - if ((cspace != EFL_GFX_COLORSPACE_ARGB8888) && - (cspace != EFL_GFX_COLORSPACE_GRY8)) - { - ERR("Unsupported colorspace: %u", cspace); - return EINA_FALSE; - } - - if (!stride) - stride = _min_stride_calc(width + l + r, cspace); - else if (stride < _min_stride_calc(width + l + r, cspace)) - { - ERR("Invalid stride %u for width %u (+%u+%u) cspace %u. pixels_set failed.", - stride, width, l, r, cspace); - _ector_software_buffer_base_pixels_clear(obj, pd); - return EINA_FALSE; - } - - if ((px > 1) && (stride & (px - 1))) - ERR("Stride (%d) is not aligned to the pixel size (%d)", stride, px); + if (((unsigned long long)(uintptr_t)pixels) & (pxs - 1)) + fail ("Pixel data is not aligned to %u bytes!", pxs); + stride = width * pxs; if (pd->pixels.u8 && (pd->pixels.u8 != pixels)) _ector_software_buffer_base_pixels_clear(obj, pd); @@ -135,31 +104,30 @@ _ector_software_buffer_base_ector_buffer_pixels_set(Eo *obj, Ector_Software_Buff } else { - pd->pixels.u8 = calloc(stride * (height + t + b), 1); + pd->pixels.u8 = calloc(stride * height, 1); pd->nofree = EINA_FALSE; pd->writable = EINA_TRUE; } pd->generic->w = width; pd->generic->h = height; - pd->generic->l = l; - pd->generic->r = r; - pd->generic->t = t; - pd->generic->b = b; pd->generic->cspace = cspace; pd->stride = stride; - pd->pixel_size = px; + pd->pixel_size = pxs; return EINA_TRUE; + +on_fail: + return EINA_FALSE; } EOLIAN static void * _ector_software_buffer_base_ector_buffer_map(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Base_Data *pd, - unsigned int *length, Ector_Buffer_Access_Flag mode, - unsigned int x, unsigned int y, unsigned int w, unsigned int h, - Efl_Gfx_Colorspace cspace EINA_UNUSED, unsigned int *stride) + unsigned int *length, Ector_Buffer_Access_Flag mode, + unsigned int x, unsigned int y, unsigned int w, unsigned int h, + Efl_Gfx_Colorspace cspace EINA_UNUSED, unsigned int *stride) { Ector_Software_Buffer_Map *map = NULL; Eina_Bool need_cow = EINA_FALSE; - unsigned int off, k, dst_stride; + unsigned int off, k, dst_stride, pxs, pxs_dest; if (!w) w = pd->generic->w; if (!h) h = pd->generic->h; @@ -172,6 +140,14 @@ _ector_software_buffer_base_ector_buffer_map(Eo *obj EINA_UNUSED, Ector_Software if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) && !pd->writable) fail("Can not map a read-only buffer for writing"); + pxs = (pd->generic->cspace == EFL_GFX_COLORSPACE_ARGB8888) ? 4 : 1; + if (cspace == EFL_GFX_COLORSPACE_ARGB8888) + pxs_dest = 4; + else if (cspace == EFL_GFX_COLORSPACE_GRY8) + pxs_dest = 1; + else + fail("Unsupported colorspace: %u", cspace); + if ((mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) && (mode & ECTOR_BUFFER_ACCESS_FLAG_COW)) { @@ -186,20 +162,21 @@ _ector_software_buffer_base_ector_buffer_map(Eo *obj EINA_UNUSED, Ector_Software map = calloc(1, sizeof(*map)); if (!map) fail("Out of memory"); + off = (pxs * x) + (pd->stride * y); + dst_stride = w * pxs_dest; + map->mode = mode; map->cspace = cspace; + map->stride = dst_stride; map->x = x; map->y = y; map->w = w; map->h = h; - off = _min_stride_calc(x + pd->generic->l, pd->generic->cspace) + (pd->stride * (y + pd->generic->t)); - dst_stride = _min_stride_calc(w, cspace); - if (cspace != pd->generic->cspace) { // convert on the fly - map->size = _min_stride_calc(w, cspace) * h; + map->size = w * h * pxs_dest; map->allocated = EINA_TRUE; map->ptr = malloc(map->size); if (!map->ptr) fail("Out of memory"); @@ -218,7 +195,7 @@ _ector_software_buffer_base_ector_buffer_map(Eo *obj EINA_UNUSED, Ector_Software else if (need_cow) { // copy-on-write access - map->size = _min_stride_calc(w, cspace) * h; + map->size = w * h * pxs_dest; map->allocated = EINA_TRUE; map->ptr = malloc(map->size); if (!map->ptr) fail("Out of memory"); @@ -261,7 +238,7 @@ _ector_software_buffer_base_ector_buffer_unmap(Eo *obj EINA_UNUSED, Ector_Softwa { if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) { - unsigned k, dst_stride; + unsigned k; if (map->cspace != pd->generic->cspace) { @@ -282,12 +259,10 @@ _ector_software_buffer_base_ector_buffer_unmap(Eo *obj EINA_UNUSED, Ector_Softwa } else { - dst_stride = _min_stride_calc(map->w, map->cspace); for (k = 0; k < map->h; k++) { memcpy(pd->pixels.u8 + map->x + (k + map->y) * pd->stride, - map->ptr + k * dst_stride, - dst_stride); + map->ptr + k * map->stride, map->stride); } } } @@ -301,33 +276,14 @@ _ector_software_buffer_base_ector_buffer_unmap(Eo *obj EINA_UNUSED, Ector_Softwa CRI("Tried to unmap a non-mapped region!"); } -EOLIAN static uint8_t * -_ector_software_buffer_base_ector_buffer_span_get(Eo *obj, Ector_Software_Buffer_Base_Data *pd, - int x, int y, unsigned int w, Efl_Gfx_Colorspace cspace, - unsigned int *length) -{ - // ector_buffer_map - return _ector_software_buffer_base_ector_buffer_map - (obj, pd, length, ECTOR_BUFFER_ACCESS_FLAG_READ, x, y, w, 1, cspace, NULL); -} - -EOLIAN static void -_ector_software_buffer_base_ector_buffer_span_free(Eo *obj, Ector_Software_Buffer_Base_Data *pd, - uint8_t *data) -{ - // ector_buffer_unmap - return _ector_software_buffer_base_ector_buffer_unmap - (obj, pd, data, (unsigned int) -1); -} - EOLIAN static Ector_Buffer_Flag _ector_software_buffer_base_ector_buffer_flags_get(Eo *obj EINA_UNUSED, Ector_Software_Buffer_Base_Data *pd) { return ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_DRAWABLE | ECTOR_BUFFER_FLAG_CPU_READABLE_FAST | - ECTOR_BUFFER_FLAG_RENDERABLE | (pd->writable ? (ECTOR_BUFFER_FLAG_CPU_WRITABLE | + ECTOR_BUFFER_FLAG_RENDERABLE | ECTOR_BUFFER_FLAG_CPU_WRITABLE_FAST) : 0); } diff --git a/src/lib/ector/software/ector_software_buffer_base.eo b/src/lib/ector/software/ector_software_buffer_base.eo index f3145d87aa..2a3b63ee67 100644 --- a/src/lib/ector/software/ector_software_buffer_base.eo +++ b/src/lib/ector/software/ector_software_buffer_base.eo @@ -10,8 +10,6 @@ mixin Ector.Software.Buffer.Base (Ector.Buffer) implements { Ector.Buffer.flags { get; } Ector.Buffer.pixels_set; - Ector.Buffer.span_get; - Ector.Buffer.span_free; Ector.Buffer.map; Ector.Buffer.unmap; } diff --git a/src/lib/ector/software/ector_software_private.h b/src/lib/ector/software/ector_software_private.h index d11ba3adc0..459de0105d 100644 --- a/src/lib/ector/software/ector_software_private.h +++ b/src/lib/ector/software/ector_software_private.h @@ -61,7 +61,6 @@ typedef enum _Span_Data_Type { Solid, LinearGradient, RadialGradient, - Image } Span_Data_Type; typedef struct _Span_Data @@ -114,7 +113,6 @@ void ector_software_rasterizer_transform_set(Software_Rasterizer *rasterizer, Ei void ector_software_rasterizer_color_set(Software_Rasterizer *rasterizer, int r, int g, int b, int a); void ector_software_rasterizer_linear_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *linear); void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasterizer, Ector_Renderer_Software_Gradient_Data *radial); -void ector_software_rasterizer_buffer_set(Software_Rasterizer *rasterizer, Ector_Software_Buffer *image); void ector_software_rasterizer_clip_rect_set(Software_Rasterizer *rasterizer, Eina_Array *clips); void ector_software_rasterizer_clip_shape_set(Software_Rasterizer *rasterizer, Shape_Rle_Data *clip); diff --git a/src/lib/ector/software/ector_software_rasterizer.c b/src/lib/ector/software/ector_software_rasterizer.c index b0ea4834af..9c91856ebb 100644 --- a/src/lib/ector/software/ector_software_rasterizer.c +++ b/src/lib/ector/software/ector_software_rasterizer.c @@ -76,45 +76,6 @@ _blend_gradient(int count, const SW_FT_Span *spans, void *user_data) } } -static void -_blend_image_argb(int count, const SW_FT_Span *spans, void *user_data) -{ - Span_Data *data = user_data; - RGBA_Comp_Func comp_func; - uint32_t *buffer, *target; - uint8_t *src8; - unsigned int l, length, sy = 0; - const int pix_stride = data->raster_buffer->stride / 4; - - /* FIXME: - * optimize eo call - * implement image scaling - * tile and repeat image properly - */ - - comp_func = efl_draw_func_span_get(data->op, data->mul_col, EINA_TRUE); - buffer = data->raster_buffer->pixels.u32 + ((pix_stride * data->offy) + data->offx); - - while (count--) - { - target = buffer + ((pix_stride * spans->y) + spans->x); - length = spans->len; - while (length) - { - l = MIN(length, data->buffer->generic->w); - src8 = ector_buffer_span_get(data->buffer->generic->eo, 0, sy, l, EFL_GFX_COLORSPACE_ARGB8888, NULL); - comp_func(target, (uint32_t *) src8, l, data->mul_col, spans->coverage); - ector_buffer_span_free(data->buffer->generic->eo, src8); - target += l; - length -= l; - } - ++spans; - ++sy; - if (sy >= data->buffer->generic->h) - sy = 0; - } -} - /*! \internal spans must be sorted on y @@ -318,9 +279,6 @@ _adjust_span_fill_methods(Span_Data *spdata) case RadialGradient: spdata->unclipped_blend = &_blend_gradient; break; - case Image: - spdata->unclipped_blend = &_blend_image_argb; - break; } // setup clipping @@ -568,13 +526,6 @@ void ector_software_rasterizer_radial_gradient_set(Software_Rasterizer *rasteriz rasterizer->fill_data.type = RadialGradient; } -void ector_software_rasterizer_buffer_set(Software_Rasterizer *rasterizer, - Ector_Software_Buffer *buffer) -{ - rasterizer->fill_data.buffer = efl_data_scope_get(buffer, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN); - rasterizer->fill_data.type = Image; -} - void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, int x, int y, uint32_t mul_col, Efl_Gfx_Render_Op op, Shape_Rle_Data* rle) diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c index f1492a2a28..1631449a73 100644 --- a/src/lib/ector/software/ector_software_surface.c +++ b/src/lib/ector/software/ector_software_surface.c @@ -12,8 +12,8 @@ static Ector_Renderer * _ector_software_surface_ector_surface_renderer_factory_new(Eo *obj, - Ector_Software_Surface_Data *pd EINA_UNUSED, - const Efl_Class *type) + Ector_Software_Surface_Data *pd EINA_UNUSED, + const Efl_Class *type) { if (type == ECTOR_RENDERER_SHAPE_MIXIN) return efl_add(ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); @@ -21,9 +21,8 @@ _ector_software_surface_ector_surface_renderer_factory_new(Eo *obj, return efl_add(ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); else if (type == ECTOR_RENDERER_GRADIENT_RADIAL_MIXIN) return efl_add(ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); - else if (type == ECTOR_RENDERER_BUFFER_MIXIN) - return efl_add(ECTOR_RENDERER_SOFTWARE_BUFFER_CLASS, NULL, ector_renderer_surface_set(efl_added, obj)); - ERR("Couldn't find class for type: %s\n", efl_class_name_get(type)); + + ERR("Couldn't find class for type: %s", efl_class_name_get(type)); return NULL; } @@ -49,8 +48,8 @@ _ector_software_surface_efl_object_destructor(Eo *obj, Ector_Software_Surface_Da static void _ector_software_surface_ector_surface_reference_point_set(Eo *obj EINA_UNUSED, - Ector_Software_Surface_Data *pd, - int x, int y) + Ector_Software_Surface_Data *pd, + int x, int y) { pd->x = x; pd->y = y; diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index d00aa44a23..98a1cb8820 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -29,29 +29,19 @@ static void _buffer_free(Evas_Filter_Buffer *fb); static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd); -static Ector_Buffer* _ector_buffer_create(Evas_Filter_Buffer const *fb, void *data); +static Evas_Filter_Buffer *_buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, Eina_Bool render, Eina_Bool draw); #define DRAW_COLOR_SET(r, g, b, a) do { cmd->draw.R = r; cmd->draw.G = g; cmd->draw.B = b; cmd->draw.A = a; } while (0) #define DRAW_CLIP_SET(_x, _y, _w, _h) do { cmd->draw.clip.x = _x; cmd->draw.clip.y = _y; cmd->draw.clip.w = _w; cmd->draw.clip.h = _h; } while (0) #define DRAW_FILL_SET(fmode) do { cmd->draw.fillmode = fmode; } while (0) -static inline void * -_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 */ - evas_ector_buffer_engine_image_get(buf, NULL, &image); - return image; -} - /* Main functions */ Evas_Filter_Context * evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data) { Evas_Filter_Context *ctx; + static int warned = 0; EINA_SAFETY_ON_NULL_RETURN_VAL(evas, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(evas->engine.func->gfx_filter_supports, NULL); @@ -65,6 +55,16 @@ evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data ctx->user_data = user_data; ctx->buffer_scaled_get = &evas_filter_buffer_scaled_get; + if (ENFN->gl_surface_read_pixels) + { + ctx->gl = EINA_TRUE; + if (!warned) + { + WRN("OpenGL support through SW functions, expect low performance!"); + warned = 1; + } + } + return ctx; } @@ -146,7 +146,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, EINA_FALSE); + fb->buffer = ENFN->ector_buffer_wrap(ENDT, obj->layer->evas->evas, source->proxy->surface); fb->alpha_only = EINA_FALSE; } } @@ -180,7 +180,8 @@ evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, } static Evas_Filter_Buffer * -_buffer_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only) +_buffer_empty_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, + Eina_Bool transient) { Evas_Filter_Buffer *fb; @@ -190,7 +191,7 @@ _buffer_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only) fb->id = ++(ctx->last_buffer_id); fb->ctx = ctx; fb->alpha_only = alpha_only; - fb->transient = EINA_TRUE; + fb->transient = transient; fb->w = w; fb->h = h; @@ -199,26 +200,19 @@ _buffer_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only) } static Ector_Buffer * -_ector_buffer_create(Evas_Filter_Buffer const *fb, void *data) +_ector_buffer_create(Evas_Filter_Buffer const *fb, Eina_Bool render, Eina_Bool draw) { - Evas_Colorspace cspace; + Efl_Gfx_Colorspace cspace = EFL_GFX_COLORSPACE_ARGB8888; Ector_Buffer_Flag flags; - // FIXME: We still rely on evas image structs (scaling and target render) - // This should be fixed by implementing full support in ector - // Note: dropped support for cserve2, that was not needed anyway - + // FIXME: Once all filters are GL buffers need not be CPU accessible flags = ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_CPU_WRITABLE; - if (fb->id == EVAS_FILTER_BUFFER_INPUT_ID) - flags |= ECTOR_BUFFER_FLAG_RENDERABLE; - else if (fb->id == EVAS_FILTER_BUFFER_OUTPUT_ID) - flags |= ECTOR_BUFFER_FLAG_DRAWABLE; + if (render) flags |= ECTOR_BUFFER_FLAG_RENDERABLE; + if (draw) flags |= ECTOR_BUFFER_FLAG_DRAWABLE; + if (fb->alpha_only) cspace = EFL_GFX_COLORSPACE_GRY8; - cspace = fb->alpha_only ? EVAS_COLORSPACE_GRY8 : EVAS_COLORSPACE_ARGB8888; return fb->ENFN->ector_buffer_new(fb->ENDT, fb->ctx->evas->evas, - data, fb->w, fb->h, 0, - (Efl_Gfx_Colorspace )cspace, EINA_TRUE, - 0, 0, 0, 0, flags); + fb->w, fb->h, cspace, flags); } Eina_Bool @@ -276,7 +270,7 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx) if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) sh = h; - fb = evas_filter_buffer_alloc_new(ctx, sw, sh, in->alpha_only); + fb = _buffer_alloc_new(ctx, sw, sh, in->alpha_only, 1, 1); XDBG("Allocated temporary buffer #%d of size %ux%u %s", fb ? fb->id : -1, sw, sh, in->alpha_only ? "alpha" : "rgba"); if (!fb) goto alloc_fail; @@ -292,7 +286,7 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx) if (in->w) sw = in->w; if (in->h) sh = in->h; - fb = evas_filter_buffer_alloc_new(ctx, sw, sh, in->alpha_only); + fb = _buffer_alloc_new(ctx, sw, sh, in->alpha_only, 1, 1); XDBG("Allocated temporary buffer #%d of size %ux%u %s", fb ? fb->id : -1, sw, sh, in->alpha_only ? "alpha" : "rgba"); if (!fb) goto alloc_fail; @@ -309,6 +303,8 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx) EINA_LIST_FOREACH(ctx->buffers, li, fb) { + Eina_Bool render = EINA_FALSE, draw = EINA_FALSE; + if (fb->buffer || fb->source) continue; @@ -318,7 +314,11 @@ evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx) continue; } - fb->buffer = _ector_buffer_create(fb, NULL); + render |= (fb->id == EVAS_FILTER_BUFFER_INPUT_ID); + render |= fb->is_render; + draw |= (fb->id == EVAS_FILTER_BUFFER_OUTPUT_ID); + + fb->buffer = _ector_buffer_create(fb, render, draw); XDBG("Allocated buffer #%d of size %ux%u %s: %p", fb->id, fb->w, fb->h, fb->alpha_only ? "alpha" : "rgba", fb->buffer); if (!fb->buffer) goto alloc_fail; @@ -338,64 +338,16 @@ evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only) EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); - fb = _buffer_new(ctx, 0, 0, alpha_only); + fb = _buffer_empty_new(ctx, 0, 0, alpha_only, EINA_FALSE); if (!fb) return -1; - fb->transient = EINA_FALSE; - XDBG("Created context buffer %d %s", fb->id, alpha_only ? "alpha" : "rgba"); return fb->id; } -Eina_Bool -_filter_buffer_data_set(Evas_Filter_Context *ctx, int bufid, void *data, - int w, int h, Eina_Bool alpha_only) -{ - Evas_Filter_Buffer *fb; - - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); - - fb = _filter_buffer_get(ctx, bufid); - if (!fb) return EINA_FALSE; - - _filter_buffer_backing_free(fb); - if (w <= 0 || h <= 0) - return EINA_FALSE; - - EINA_SAFETY_ON_FALSE_RETURN_VAL(fb->buffer == NULL, EINA_FALSE); - // TODO: Check input parameters? - fb->alpha_only = alpha_only; - fb->w = w; - fb->h = h; - - fb->buffer = _ector_buffer_create(fb, data); - return (fb->buffer != NULL); -} - -static int -_filter_buffer_new_from_evas_surface(Evas_Filter_Context *ctx, void *image) -{ - Evas_Filter_Buffer *fb; - - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); - - fb = calloc(1, sizeof(Evas_Filter_Buffer)); - if (!fb) return -1; - - fb->id = ++(ctx->last_buffer_id); - fb->ctx = ctx; - 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); - - ctx->buffers = eina_list_append(ctx->buffers, fb); - return fb->id; -} - -Evas_Filter_Buffer * -_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h, - Eina_Bool alpha_only) +static Evas_Filter_Buffer * +_buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only, + Eina_Bool render, Eina_Bool draw) { Evas_Filter_Buffer *fb; @@ -407,15 +359,18 @@ _filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h, fb->id = ++(ctx->last_buffer_id); fb->ctx = ctx; - ctx->buffers = eina_list_append(ctx->buffers, fb); - - if (!_filter_buffer_data_set(ctx, fb->id, data, w, h, alpha_only)) + fb->w = w; + fb->h = h; + fb->alpha_only = alpha_only; + fb->buffer = _ector_buffer_create(fb, render, draw); + if (!fb->buffer) { - ctx->buffers = eina_list_remove(ctx->buffers, fb); + ERR("Failed to create ector buffer!"); free(fb); return NULL; } + ctx->buffers = eina_list_append(ctx->buffers, fb); return fb; } @@ -440,17 +395,6 @@ _filter_buffer_get(Evas_Filter_Context *ctx, int bufid) return NULL; } -void * -evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid) -{ - Evas_Filter_Buffer *fb; - - fb = _filter_buffer_get(ctx, bufid); - if (!fb) return NULL; - - return _evas_image_get(fb->buffer); -} - void * evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid) { @@ -459,7 +403,7 @@ evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid) fb = _filter_buffer_get(ctx, bufid); if (!fb) return NULL; - return fb->ENFN->image_ref(fb->ENDT, _evas_image_get(fb->buffer)); + return evas_ector_buffer_drawable_image_get(fb->buffer, EINA_TRUE); } Eina_Bool @@ -468,10 +412,7 @@ evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, { if (!stolen_buffer) return EINA_FALSE; EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); - -#ifdef DEBUG EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_main_loop_is(), EINA_FALSE); -#endif ENFN->image_free(ENDT, stolen_buffer); return EINA_TRUE; @@ -511,19 +452,6 @@ _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd) free(cmd); } -Evas_Filter_Command * -_evas_filter_command_get(Evas_Filter_Context *ctx, int cmdid) -{ - Evas_Filter_Command *cmd; - - if (cmdid <= 0) return NULL; - - EINA_INLIST_FOREACH(ctx->commands, cmd) - if (cmd->id == cmdid) return cmd; - - return NULL; -} - Evas_Filter_Buffer * evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only) @@ -535,8 +463,7 @@ evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h, { if (buf->transient && !buf->locked && (buf->alpha_only == alpha_only)) { - if ((!w || (w == buf->w)) - && (!h || (h == buf->h))) + if ((!w || (w == buf->w)) && (!h || (h == buf->h))) { buf->locked = EINA_TRUE; return buf; @@ -544,14 +471,15 @@ evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h, } } - if (ctx->running) // && ctx->async) + if (ctx->running) { - ERR("Can not create a new buffer from this thread!"); + ERR("Can not create a new buffer while filter is running!"); return NULL; } - buf = _buffer_new(ctx, w, h, alpha_only); + buf = _buffer_empty_new(ctx, w, h, alpha_only, EINA_TRUE); buf->locked = EINA_TRUE; + return buf; } @@ -565,7 +493,7 @@ _filter_buffer_unlock_all(Evas_Filter_Context *ctx) buf->locked = EINA_FALSE; } -int +Evas_Filter_Command * evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, int bufid) { @@ -573,18 +501,18 @@ evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, Evas_Filter_Buffer *buf = NULL; int R, G, B, A, cx, cy, cw, ch; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(draw_context, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(draw_context, NULL); buf = _filter_buffer_get(ctx, bufid); if (!buf) { ERR("Buffer %d does not exist.", bufid); - return -1; + return NULL; } cmd = _command_new(ctx, EVAS_FILTER_MODE_FILL, buf, NULL, buf); - if (!cmd) return -1; + if (!cmd) return NULL; ENFN->context_color_get(ENDT, draw_context, &R, &G, &B, &A); DRAW_COLOR_SET(R, G, B, A); @@ -592,25 +520,26 @@ evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, ENFN->context_clip_get(ENDT, draw_context, &cx, &cy, &cw, &ch); DRAW_CLIP_SET(cx, cy, cw, ch); + XDBG("Add fill %d with color(%d,%d,%d,%d)", buf->id, R, G, B, A); + buf->dirty = EINA_TRUE; - return cmd->id; + return cmd; } -int +Evas_Filter_Command * evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, int inbuf, int outbuf, Evas_Filter_Blur_Type type, int dx, int dy, int ox, int oy, int count) { - Evas_Filter_Command *cmd = NULL; Evas_Filter_Buffer *in = NULL, *out = NULL, *tmp = NULL, *in_dy = NULL; Evas_Filter_Buffer *out_dy = NULL, *out_dx = NULL; Evas_Filter_Buffer *copybuf = NULL, *blur_out = NULL; Eina_Bool copy_back = EINA_FALSE, blend = EINA_FALSE; + Evas_Filter_Command *cmd = NULL; int R, G, B, A; DATA32 color; - int ret = 0, id; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(drawctx, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(drawctx, NULL); if (dx < 0) dx = 0; if (dy < 0) dy = 0; @@ -621,18 +550,10 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, } in = _filter_buffer_get(ctx, inbuf); - if (!in) - { - ERR("Buffer %d does not exist [input].", inbuf); - goto fail; - } + EINA_SAFETY_ON_FALSE_GOTO(in, fail); out = _filter_buffer_get(ctx, outbuf); - if (!out) - { - ERR("Buffer %d does not exist [output].", outbuf); - goto fail; - } + EINA_SAFETY_ON_FALSE_GOTO(out, fail); if (!in->alpha_only && out->alpha_only) DBG("Different color formats, implicit conversion may be slow"); @@ -676,7 +597,6 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, int tmp_ox = ox; int tmp_oy = oy; - id = -1; if (dx && dy) { tmp = evas_filter_temporary_buffer_get(ctx, 0, 0, alpha); @@ -690,14 +610,13 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, if (dx <= 2) type = EVAS_FILTER_BLUR_GAUSSIAN; else - type = EVAS_FILTER_BLUR_BOX; + type = EVAS_FILTER_BLUR_BOX; if (dy && (color != 0xFFFFFFFF)) ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255); - id = evas_filter_command_blur_add(ctx, drawctx, inbuf, tmp_out, - type, dx, 0, tmp_ox, tmp_oy, 0); - if (id < 0) goto fail; - cmd = _evas_filter_command_get(ctx, id); + cmd = evas_filter_command_blur_add(ctx, drawctx, inbuf, tmp_out, + type, dx, 0, tmp_ox, tmp_oy, 0); + if (!cmd) goto fail; cmd->blur.auto_count = EINA_TRUE; if (dy && (color != 0xFFFFFFFF)) ENFN->context_color_set(ENDT, drawctx, R, G, B, A); @@ -710,14 +629,13 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, else type = EVAS_FILTER_BLUR_BOX; - id = evas_filter_command_blur_add(ctx, drawctx, tmp_in, outbuf, - type, 0, dy, ox, oy, 0); - if (id < 0) goto fail; - cmd = _evas_filter_command_get(ctx, id); + cmd = evas_filter_command_blur_add(ctx, drawctx, tmp_in, outbuf, + type, 0, dy, ox, oy, 0); + if (!cmd) goto fail; cmd->blur.auto_count = EINA_TRUE; } - return id; + return cmd; } break; @@ -818,7 +736,6 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, cmd->blur.count = count; if (!dy && !blend) DRAW_COLOR_SET(R, G, B, A); - ret = cmd->id; } if (dy) @@ -832,45 +749,47 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx, cmd->blur.count = count; if (!blend) DRAW_COLOR_SET(R, G, B, A); - if (ret <= 0) ret = cmd->id; } if (copy_back) { + Evas_Filter_Command *copycmd; int render_op; if (!cmd) goto fail; XDBG("Add copy %d -> %d", copybuf->id, blur_out->id); - cmd->ENFN->context_color_set(cmd->ENDT, drawctx, 255, 255, 255, 255); - render_op = cmd->ENFN->context_render_op_get(cmd->ENDT, drawctx); - cmd->ENFN->context_render_op_set(cmd->ENDT, drawctx, EVAS_RENDER_COPY); - id = evas_filter_command_blend_add(ctx, drawctx, copybuf->id, blur_out->id, ox, oy, EVAS_FILTER_FILL_MODE_NONE); - cmd->ENFN->context_color_set(cmd->ENDT, drawctx, R, G, B, A); - cmd->ENFN->context_render_op_set(cmd->ENDT, drawctx, render_op); - if (id < 0) goto fail; + ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255); + render_op = ENFN->context_render_op_get(ENDT, drawctx); + ENFN->context_render_op_set(ENDT, drawctx, EVAS_RENDER_COPY); + copycmd = evas_filter_command_blend_add(ctx, drawctx, copybuf->id, blur_out->id, ox, oy, EVAS_FILTER_FILL_MODE_NONE); + ENFN->context_color_set(ENDT, drawctx, R, G, B, A); + ENFN->context_render_op_set(ENDT, drawctx, render_op); + if (!copycmd) goto fail; ox = oy = 0; } if (blend) { + Evas_Filter_Command *blendcmd; + XDBG("Add blend %d (%s) -> %d (%s)", blur_out->id, blur_out->alpha_only ? "Alpha" : "RGBA", out->id, out->alpha_only ? "Alpha" : "RGBA"); - id = evas_filter_command_blend_add(ctx, drawctx, blur_out->id, out->id, ox, oy, EVAS_FILTER_FILL_MODE_NONE); - if (id < 0) goto fail; + blendcmd = evas_filter_command_blend_add(ctx, drawctx, blur_out->id, out->id, ox, oy, EVAS_FILTER_FILL_MODE_NONE); + if (!blendcmd) goto fail; } out->dirty = EINA_TRUE; _filter_buffer_unlock_all(ctx); - return ret; + return cmd; fail: ERR("Failed to add blur"); _filter_buffer_unlock_all(ctx); - return -1; + return NULL; } -int +Evas_Filter_Command * evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *drawctx, int inbuf, int outbuf, int ox, int oy, Evas_Filter_Fill_Mode fillmode) @@ -879,30 +798,30 @@ evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *drawctx, Evas_Filter_Buffer *in, *out; int R, G, B, A; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); if (inbuf == outbuf) { XDBG("Skipping NOP blend operation %d --> %d", inbuf, outbuf); - return -1; + return NULL; } in = _filter_buffer_get(ctx, inbuf); if (!in) { ERR("Buffer %d does not exist [input].", inbuf); - return -1; + return NULL; } out = _filter_buffer_get(ctx, outbuf); if (!out) { ERR("Buffer %d does not exist [output].", outbuf); - return -1; + return NULL; } cmd = _command_new(ctx, EVAS_FILTER_MODE_BLEND, in, NULL, out); - if (!cmd) return -1; + if (!cmd) return NULL; ENFN->context_color_get(ENDT, drawctx, &R, &G, &B, &A); DRAW_COLOR_SET(R, G, B, A); @@ -915,24 +834,26 @@ evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *drawctx, &cmd->draw.clip.x, &cmd->draw.clip.y, &cmd->draw.clip.w, &cmd->draw.clip.h); + XDBG("Add blend %d -> %d", in->id, out->id); if (cmd->draw.clip_use) XDBG("Draw clip: %d,%d,%d,%d", cmd->draw.clip.x, cmd->draw.clip.y, cmd->draw.clip.w, cmd->draw.clip.h); out->dirty = EINA_TRUE; - return cmd->id; + return cmd; } -int +Evas_Filter_Command * evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int radius, Eina_Bool smooth) { - int blurcmd, threshcmd, blendcmd, tmin = 0, growbuf; + Evas_Filter_Command *blurcmd, *threshcmd, *blendcmd; + Evas_Filter_Buffer *tmp = NULL, *in, *out; int diam = abs(radius) * 2 + 1; DATA8 curve[256] = {0}; - Evas_Filter_Buffer *tmp = NULL, *in, *out; + int tmin = 0, growbuf; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); if (!radius) { @@ -941,12 +862,12 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, } in = _filter_buffer_get(ctx, inbuf); - EINA_SAFETY_ON_NULL_RETURN_VAL(in, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); if (inbuf != outbuf) { tmp = evas_filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only); - EINA_SAFETY_ON_NULL_RETURN_VAL(tmp, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(tmp, NULL); growbuf = tmp->id; } else @@ -955,7 +876,7 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, blurcmd = evas_filter_command_blur_add(ctx, draw_context, inbuf, growbuf, EVAS_FILTER_BLUR_DEFAULT, abs(radius), abs(radius), 0, 0, 0); - if (blurcmd < 0) return -1; + if (!blurcmd) return NULL; if (diam > 255) diam = 255; if (radius > 0) @@ -981,21 +902,21 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, } out = _filter_buffer_get(ctx, growbuf); - if (!out) return -1; + if (!out) return NULL; out->dirty = EINA_TRUE; if (growbuf != outbuf) { out = _filter_buffer_get(ctx, growbuf); - if (!out) return -1; + if (!out) return NULL; out->dirty = EINA_TRUE; } threshcmd = evas_filter_command_curve_add(ctx, draw_context, growbuf, growbuf, curve, EVAS_FILTER_CHANNEL_ALPHA); - if (threshcmd < 0) + if (!threshcmd) { - _command_del(ctx, _evas_filter_command_get(ctx, blurcmd)); - return -1; + _command_del(ctx, blurcmd); + return NULL; } if (tmp) @@ -1003,18 +924,18 @@ evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, blendcmd = evas_filter_command_blend_add(ctx, draw_context, tmp->id, outbuf, 0, 0, EVAS_FILTER_FILL_MODE_NONE); - if (blendcmd < 0) + if (!blendcmd) { - _command_del(ctx, _evas_filter_command_get(ctx, threshcmd)); - _command_del(ctx, _evas_filter_command_get(ctx, blurcmd)); - return -1; + _command_del(ctx, threshcmd); + _command_del(ctx, blurcmd); + return NULL; } } return blurcmd; } -int +Evas_Filter_Command * evas_filter_command_curve_add(Evas_Filter_Context *ctx, void *draw_context EINA_UNUSED, int inbuf, int outbuf, DATA8 *curve, @@ -1024,30 +945,28 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx, Evas_Filter_Buffer *in, *out; DATA8 *copy; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(curve, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(curve, NULL); in = _filter_buffer_get(ctx, inbuf); out = _filter_buffer_get(ctx, outbuf); - if (!in || !out) - { - ERR("Invalid buffer id: input %d [%p], output %d [%p]", - inbuf, in, outbuf, out); - return -1; - } + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); if (in->alpha_only != out->alpha_only) WRN("Incompatible formats for color curves, implicit conversion will be " "slow and may not produce the desired output."); + XDBG("Add curve %d -> %d", in->id, out->id); + copy = malloc(256 * sizeof(DATA8)); - if (!copy) return -1; + if (!copy) return NULL; cmd = _command_new(ctx, EVAS_FILTER_MODE_CURVE, in, NULL, out); if (!cmd) { free(copy); - return -1; + return NULL; } memcpy(copy, curve, 256 * sizeof(DATA8)); @@ -1055,10 +974,10 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx, cmd->curve.channel = channel; out->dirty = EINA_TRUE; - return cmd->id; + return cmd; } -int +Evas_Filter_Command * evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx, void *draw_context EINA_UNUSED, int inbuf, int outbuf, int dispbuf, @@ -1066,22 +985,18 @@ evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx, int intensity, Evas_Filter_Fill_Mode fillmode) { - Evas_Filter_Command *cmd; Evas_Filter_Buffer *in, *out, *map, *tmp = NULL, *disp_out; - int cmdid = -1; + Evas_Filter_Command *cmd = NULL; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); - EINA_SAFETY_ON_FALSE_RETURN_VAL(intensity >= 0, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(intensity >= 0, NULL); in = _filter_buffer_get(ctx, inbuf); out = _filter_buffer_get(ctx, outbuf); map = _filter_buffer_get(ctx, dispbuf); - if (!in || !out || !map) - { - ERR("Invalid buffer id: input %d [%p], output %d [%p], map %d [%p]", - inbuf, in, outbuf, out, dispbuf, map); - return -1; - } + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(map, NULL); if (in->alpha_only != out->alpha_only) DBG("Different color formats, implicit conversion may be slow"); @@ -1095,39 +1010,41 @@ evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx, if (in == out) { tmp = evas_filter_temporary_buffer_get(ctx, in->w, in->h, in->alpha_only); - if (!tmp) return -1; + if (!tmp) return NULL; disp_out = tmp; } else disp_out = out; cmd = _command_new(ctx, EVAS_FILTER_MODE_DISPLACE, in, map, disp_out); - if (!cmd) goto end; + if (!cmd) goto fail; DRAW_FILL_SET(fillmode); cmd->displacement.flags = flags & EVAS_FILTER_DISPLACE_BITMASK; cmd->displacement.intensity = intensity; cmd->draw.rop = _evas_to_gfx_render_op(ENFN->context_render_op_get(ENDT, draw_context)); - cmdid = cmd->id; if (tmp) { - if (evas_filter_command_blend_add(ctx, draw_context, disp_out->id, - out->id, 0, 0, - EVAS_FILTER_FILL_MODE_NONE) < 0) - { - _command_del(ctx, _evas_filter_command_get(ctx, cmdid)); - cmdid = -1; - } + Evas_Filter_Command *fillcmd; + + fillcmd = evas_filter_command_blend_add(ctx, draw_context, disp_out->id, + out->id, 0, 0, + EVAS_FILTER_FILL_MODE_NONE); + if (!fillcmd) goto fail; } out->dirty = EINA_TRUE; -end: _filter_buffer_unlock_all(ctx); - return cmdid; + return cmd; + +fail: + _filter_buffer_unlock_all(ctx); + _command_del(ctx, cmd); + return NULL; } -int +Evas_Filter_Command * evas_filter_command_mask_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int maskbuf, int outbuf, Evas_Filter_Fill_Mode fillmode) @@ -1135,10 +1052,9 @@ evas_filter_command_mask_add(Evas_Filter_Context *ctx, void *draw_context, Evas_Filter_Command *cmd; Evas_Filter_Buffer *in, *out, *mask; Efl_Gfx_Render_Op render_op; - int cmdid = -1; int R, G, B, A; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); render_op = _evas_to_gfx_render_op(ENFN->context_render_op_get(ENDT, draw_context)); ENFN->context_color_get(ENDT, draw_context, &R, &G, &B, &A); @@ -1146,29 +1062,22 @@ evas_filter_command_mask_add(Evas_Filter_Context *ctx, void *draw_context, in = _filter_buffer_get(ctx, inbuf); out = _filter_buffer_get(ctx, outbuf); mask = _filter_buffer_get(ctx, maskbuf); - if (!in || !out || !mask) - { - ERR("Invalid buffer id: input %d [%p], output %d [%p], mask %d [%p]", - inbuf, in, outbuf, out, maskbuf, mask); - return -1; - } + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(mask, NULL); cmd = _command_new(ctx, EVAS_FILTER_MODE_MASK, in, mask, out); - if (!cmd) goto end; + if (!cmd) return NULL; cmd->draw.rop = render_op; DRAW_COLOR_SET(R, G, B, A); DRAW_FILL_SET(fillmode); - - cmdid = cmd->id; out->dirty = EINA_TRUE; -end: - _filter_buffer_unlock_all(ctx); - return cmdid; + return cmd; } -int +Evas_Filter_Command * evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, void *draw_context EINA_UNUSED, int inbuf, int bumpbuf, int outbuf, @@ -1179,22 +1088,18 @@ evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, Evas_Filter_Fill_Mode fillmode) { Evas_Filter_Command *cmd; - Evas_Filter_Buffer *in, *out, *bumpmap; - int cmdid = -1; + Evas_Filter_Buffer *in, *out, *map; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); in = _filter_buffer_get(ctx, inbuf); out = _filter_buffer_get(ctx, outbuf); - bumpmap = _filter_buffer_get(ctx, bumpbuf); - if (!in || !out || !bumpmap) - { - ERR("Invalid buffer id: input %d [%p], output %d [%p], bumpmap %d [%p]", - inbuf, in, outbuf, out, bumpbuf, bumpmap); - return -1; - } + map = _filter_buffer_get(ctx, bumpbuf); + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(map, NULL); - if (!bumpmap->alpha_only) + if (!map->alpha_only) DBG("Bump map is not an Alpha buffer, implicit conversion may be slow"); // FIXME: Boo! @@ -1202,11 +1107,11 @@ evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, WRN("RGBA bump map support is not implemented! This will trigger conversion."); // FIXME: Must ensure in != out - if (in == out) CRI("Not acceptable"); - if (bumpmap == out) CRI("Not acceptable"); + EINA_SAFETY_ON_FALSE_RETURN_VAL(in != out, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(map != out, NULL); - cmd = _command_new(ctx, EVAS_FILTER_MODE_BUMP, in, bumpmap, out); - if (!cmd) goto end; + cmd = _command_new(ctx, EVAS_FILTER_MODE_BUMP, in, map, out); + if (!cmd) return NULL; DRAW_FILL_SET(fillmode); cmd->bump.xyangle = xyangle; @@ -1217,16 +1122,12 @@ evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, cmd->bump.white = white; cmd->bump.elevation = elevation; cmd->bump.compensate = !!(flags & EVAS_FILTER_BUMP_COMPENSATE); - cmdid = cmd->id; - out->dirty = EINA_TRUE; -end: - _filter_buffer_unlock_all(ctx); - return cmdid; + return cmd; } -int +Evas_Filter_Command * evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context EINA_UNUSED, int inbuf, int outbuf, @@ -1236,19 +1137,15 @@ evas_filter_command_transform_add(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd; Evas_Filter_Buffer *in, *out; - EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL); in = _filter_buffer_get(ctx, inbuf); out = _filter_buffer_get(ctx, outbuf); - if (!in || !out) - { - ERR("Invalid buffer id: input %d [%p], output %d [%p]", - inbuf, in, outbuf, out); - return -1; - } + EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL); cmd = _command_new(ctx, EVAS_FILTER_MODE_TRANSFORM, in, NULL, out); - if (!cmd) return -1; + if (!cmd) return NULL; DRAW_COLOR_SET(255, 255, 255, 255); cmd->transform.flags = flags; @@ -1265,7 +1162,7 @@ evas_filter_command_transform_add(Evas_Filter_Context *ctx, out->dirty = EINA_TRUE; - return cmd->id; + return cmd; } /* Final target */ @@ -1277,7 +1174,7 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); - ctx->target.bufid = _filter_buffer_new_from_evas_surface(ctx, surface); + ctx->target.surface = ENFN->image_ref(ENDT, surface); ctx->target.x = x; ctx->target.y = y; ctx->target.clip_use = ENFN->context_clip_get @@ -1303,21 +1200,19 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, static Eina_Bool _filter_target_render(Evas_Filter_Context *ctx) { - Evas_Filter_Buffer *src, *dst; - void *drawctx, *image = NULL, *surface = NULL; + Evas_Filter_Buffer *src; + void *drawctx, *image = NULL, *surface; - EINA_SAFETY_ON_FALSE_RETURN_VAL(ctx->target.bufid, EINA_FALSE); - - src = _filter_buffer_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID); - dst = _filter_buffer_get(ctx, ctx->target.bufid); - EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx->target.surface, EINA_FALSE); drawctx = ENFN->context_new(ENDT); - image = _evas_image_get(src->buffer); - surface = _evas_image_get(dst->buffer); - EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); + surface = ctx->target.surface; + + src = _filter_buffer_get(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID); + EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); + + image = evas_ector_buffer_drawable_image_get(src->buffer, EINA_FALSE); + EINA_SAFETY_ON_NULL_GOTO(image, fail); // FIXME: Use ector buffer RENDERER here @@ -1348,7 +1243,19 @@ _filter_target_render(Evas_Filter_Context *ctx) EINA_TRUE, EINA_FALSE); ENFN->context_free(ENDT, drawctx); + evas_ector_buffer_engine_image_release(src->buffer, image); + + ENFN->image_free(ENDT, surface); + ctx->target.surface = NULL; + return EINA_TRUE; + +fail: + ENFN->image_free(ENDT, surface); + ctx->target.surface = NULL; + + ERR("Failed to render filter to target canvas!"); + return EINA_FALSE; } @@ -1365,8 +1272,8 @@ evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, fb = _filter_buffer_get(ctx, bufid); EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); - surface = _evas_image_get(fb->buffer); - if (!surface) return EINA_FALSE; + surface = evas_ector_buffer_render_image_get(fb->buffer, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); // Copied from evas_font_draw_async_check async_unref = ENFN->font_draw(ENDT, draw_context, surface, @@ -1378,6 +1285,7 @@ evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, evas_unref_queue_glyph_put(ctx->evas, text_props->glyphs); } + evas_ector_buffer_engine_image_release(fb->buffer, surface); return EINA_TRUE; } @@ -1389,13 +1297,17 @@ evas_filter_image_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, { int dw = 0, dh = 0, w = 0, h = 0; Eina_Bool async_unref; + Evas_Filter_Buffer *fb; void *surface; ENFN->image_size_get(ENDT, image, &w, &h); if (!w || !h) return EINA_FALSE; - surface = evas_filter_buffer_backing_get(ctx, bufid); - if (!surface) return EINA_FALSE; + fb = _filter_buffer_get(ctx, bufid); + if (!fb) return EINA_FALSE; + + surface = evas_ector_buffer_render_image_get(fb->buffer, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); ENFN->image_size_get(ENDT, image, &dw, &dh); if (!dw || !dh) return EINA_FALSE; @@ -1410,6 +1322,7 @@ evas_filter_image_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, evas_unref_queue_image_put(ctx->evas, image); } + evas_ector_buffer_engine_image_release(fb->buffer, surface); return EINA_TRUE; } @@ -1571,7 +1484,6 @@ _filter_thread_run_cb(void *data) Eina_Bool evas_filter_run(Evas_Filter_Context *ctx) { - static int warned = 0; Eina_Bool ret; EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); @@ -1579,12 +1491,6 @@ evas_filter_run(Evas_Filter_Context *ctx) if (!ctx->commands) return EINA_TRUE; - if (ENFN->gl_surface_read_pixels && !warned) - { - WRN("OpenGL support through SW functions, expect low performance!"); - warned = 1; - } - if (ctx->async) { evas_thread_queue_flush(_filter_thread_run_cb, ctx); diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c index 8fce7c57a9..e3346e09bb 100644 --- a/src/lib/evas/filters/evas_filter_parser.c +++ b/src/lib/evas/filters/evas_filter_parser.c @@ -20,7 +20,7 @@ #define EVAS_FILTER_MODE_BUFFER (EVAS_FILTER_MODE_LAST+2) #define INSTR_PARAM_CHECK(a) do { if (!(a)) { \ - ERR("Argument %s can not be nil in %s!", #a, instr->name); return -1; } \ + ERR("Argument %s can not be nil in %s!", #a, instr->name); return NULL; } \ } while (0) /* Note on the documentation: @@ -913,8 +913,8 @@ _blend_padding_update(Evas_Filter_Program *pgm EINA_UNUSED, src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); - INSTR_PARAM_CHECK(src); - INSTR_PARAM_CHECK(dst); + EINA_SAFETY_ON_NULL_RETURN_VAL(src, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, 0); fillmode = _fill_mode_get(instr); if (fillmode & (EVAS_FILTER_FILL_MODE_STRETCH_X | EVAS_FILTER_FILL_MODE_REPEAT_X)) ox = 0; @@ -1022,8 +1022,8 @@ _blur_padding_update(Evas_Filter_Program *pgm EINA_UNUSED, src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); - INSTR_PARAM_CHECK(src); - INSTR_PARAM_CHECK(dst); + EINA_SAFETY_ON_NULL_RETURN_VAL(src, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, 0); if (typestr && !strcasecmp(typestr, "box")) type = EVAS_FILTER_BLUR_BOX; @@ -1405,8 +1405,8 @@ _displace_padding_update(Evas_Filter_Program *pgm EINA_UNUSED, intensity = _instruction_param_geti(instr, "intensity", NULL); src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); - INSTR_PARAM_CHECK(src); - INSTR_PARAM_CHECK(dst); + EINA_SAFETY_ON_NULL_RETURN_VAL(src, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, 0); l = intensity + src->pad.l; r = intensity + src->pad.r; @@ -1552,8 +1552,8 @@ _grow_padding_update(Evas_Filter_Program *pgm EINA_UNUSED, radius = _instruction_param_geti(instr, "radius", NULL); src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); - INSTR_PARAM_CHECK(src); - INSTR_PARAM_CHECK(dst); + EINA_SAFETY_ON_NULL_RETURN_VAL(src, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, 0); if (radius < 0) radius = 0; @@ -1684,7 +1684,7 @@ _transform_padding_update(Evas_Filter_Program *pgm EINA_UNUSED, ox = 0; oy = _instruction_param_geti(instr, "oy", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); - INSTR_PARAM_CHECK(dst); + EINA_SAFETY_ON_NULL_RETURN_VAL(dst, 0); if (ox < 0) l = (-ox) * 2; else r = ox * 2; @@ -3018,15 +3018,16 @@ _fill_mode_get(Evas_Filter_Instruction *instr) return EVAS_FILTER_FILL_MODE_NONE; } -static int +static Evas_Filter_Command * _instr2cmd_blend(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { Eina_Bool isset = EINA_FALSE; + Evas_Filter_Command *cmd; DATA32 color; Buffer *src, *dst; Evas_Filter_Fill_Mode fillmode; - int cmdid, ox, oy, A, R, G, B; + int ox, oy, A, R, G, B; ox = _instruction_param_geti(instr, "ox", NULL); oy = _instruction_param_geti(instr, "oy", NULL); @@ -3038,24 +3039,23 @@ _instr2cmd_blend(Evas_Filter_Context *ctx, INSTR_PARAM_CHECK(dst); if (isset) SETCOLOR(color); - cmdid = evas_filter_command_blend_add(ctx, dc, src->cid, dst->cid, ox, oy, - fillmode); + cmd = evas_filter_command_blend_add(ctx, dc, src->cid, dst->cid, ox, oy, fillmode); if (isset) RESETCOLOR(); - if (cmdid < 0) return cmdid; - return cmdid; + return cmd; } -static int +static Evas_Filter_Command * _instr2cmd_blur(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { Eina_Bool colorset = EINA_FALSE, yset = EINA_FALSE, cntset = EINA_FALSE; Evas_Filter_Blur_Type type = EVAS_FILTER_BLUR_DEFAULT; + Evas_Filter_Command *cmd; const char *typestr; DATA32 color; Buffer *src, *dst; - int cmdid, ox, oy, rx, ry, A, R, G, B, count; + int ox, oy, rx, ry, A, R, G, B, count; ox = _instruction_param_geti(instr, "ox", NULL); oy = _instruction_param_geti(instr, "oy", NULL); @@ -3098,14 +3098,14 @@ _instr2cmd_blur(Evas_Filter_Context *ctx, if (!yset) ry = rx; if (colorset) SETCOLOR(color); - cmdid = evas_filter_command_blur_add(ctx, dc, src->cid, dst->cid, type, - rx, ry, ox, oy, count); + cmd = evas_filter_command_blur_add(ctx, dc, src->cid, dst->cid, type, + rx, ry, ox, oy, count); if (colorset) RESETCOLOR(); - return cmdid; + return cmd; } -static int +static Evas_Filter_Command * _instr2cmd_bump(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { @@ -3114,7 +3114,7 @@ _instr2cmd_bump(Evas_Filter_Context *ctx, DATA32 color, black, white; Buffer *src, *dst, *map; double azimuth, elevation, depth, specular; - int cmdid, compensate; + int compensate; color = _instruction_param_getc(instr, "color", NULL); white = _instruction_param_getc(instr, "white", NULL); @@ -3134,15 +3134,13 @@ _instr2cmd_bump(Evas_Filter_Context *ctx, INSTR_PARAM_CHECK(dst); INSTR_PARAM_CHECK(map); - cmdid = evas_filter_command_bump_map_add(ctx, dc, src->cid, map->cid, dst->cid, - azimuth, elevation, depth, specular, - black, color, white, flags, - fillmode); - - return cmdid; + return evas_filter_command_bump_map_add(ctx, dc, src->cid, map->cid, dst->cid, + azimuth, elevation, depth, specular, + black, color, white, flags, + fillmode); } -static int +static Evas_Filter_Command * _instr2cmd_displace(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { @@ -3151,7 +3149,7 @@ _instr2cmd_displace(Evas_Filter_Context *ctx, EVAS_FILTER_DISPLACE_STRETCH | EVAS_FILTER_DISPLACE_LINEAR; const char *flagsstr; Buffer *src, *dst, *map; - int cmdid, intensity; + int intensity; Eina_Bool isset = EINA_FALSE; src = _instruction_param_getbuf(instr, "src", NULL); @@ -3176,23 +3174,19 @@ _instr2cmd_displace(Evas_Filter_Context *ctx, else if (isset) WRN("Invalid flags '%s' in displace operation. Using default instead", flagsstr); - cmdid = evas_filter_command_displacement_map_add(ctx, dc, src->cid, dst->cid, - map->cid, flags, intensity, - fillmode); - - return cmdid; + return evas_filter_command_displacement_map_add(ctx, dc, src->cid, dst->cid, + map->cid, flags, intensity, + fillmode); } -static int +static Evas_Filter_Command * _instr2cmd_fill(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { Buffer *dst; int R, G, B, A, l, r, t, b; Evas_Filter_Command *cmd; - Eina_Inlist *il; DATA32 color; - int cmdid; dst = _instruction_param_getbuf(instr, "dst", NULL); color = _instruction_param_getc(instr, "color", NULL); @@ -3203,31 +3197,27 @@ _instr2cmd_fill(Evas_Filter_Context *ctx, INSTR_PARAM_CHECK(dst); SETCOLOR(color); - cmdid = evas_filter_command_fill_add(ctx, dc, dst->cid); + cmd = evas_filter_command_fill_add(ctx, dc, dst->cid); RESETCOLOR(); + if (!cmd) return NULL; - if (cmdid < 0) return -1; - il = eina_inlist_last(ctx->commands); - if (!il) return -1; - - cmd = EINA_INLIST_CONTAINER_GET(il, Evas_Filter_Command); cmd->draw.clip.l = l; cmd->draw.clip.r = r; cmd->draw.clip.t = t; cmd->draw.clip.b = b; cmd->draw.clip_mode_lrtb = EINA_TRUE; - return cmdid; + return cmd; } -static int +static Evas_Filter_Command * _instr2cmd_grow(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { Evas_Filter_Command *cmd; Buffer *src, *dst; Eina_Bool smooth; - int cmdid, radius; + int radius; src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); @@ -3236,23 +3226,21 @@ _instr2cmd_grow(Evas_Filter_Context *ctx, INSTR_PARAM_CHECK(src); INSTR_PARAM_CHECK(dst); - cmdid = evas_filter_command_grow_add(ctx, dc, src->cid, dst->cid, - radius, smooth); - - cmd = _evas_filter_command_get(ctx, cmdid); + cmd = evas_filter_command_grow_add(ctx, dc, src->cid, dst->cid, radius, smooth); if (cmd) cmd->draw.need_temp_buffer = EINA_TRUE; - return cmdid; + return cmd; } -static int +static Evas_Filter_Command * _instr2cmd_mask(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { Evas_Filter_Fill_Mode fillmode; + Evas_Filter_Command *cmd; Buffer *src, *dst, *mask; DATA32 color; - int R, G, B, A, cmdid; + int R, G, B, A; src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); @@ -3264,22 +3252,17 @@ _instr2cmd_mask(Evas_Filter_Context *ctx, INSTR_PARAM_CHECK(mask); SETCOLOR(color); - cmdid = evas_filter_command_mask_add(ctx, dc, src->cid, mask->cid, dst->cid, fillmode); + cmd = evas_filter_command_mask_add(ctx, dc, src->cid, mask->cid, dst->cid, fillmode); RESETCOLOR(); - if (cmdid < 0) return cmdid; + if (!cmd) return NULL; - if (!src->alpha && !mask->alpha && !dst->alpha) - { - Evas_Filter_Command *cmd; + if (!src->alpha && !mask->alpha && !dst->alpha && !ctx->gl) + cmd->draw.need_temp_buffer = EINA_TRUE; - cmd = _evas_filter_command_get(ctx, cmdid); - cmd->draw.need_temp_buffer = EINA_TRUE; - } - - return cmdid; + return cmd; } -static int +static Evas_Filter_Command * _instr2cmd_curve(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { @@ -3289,7 +3272,6 @@ _instr2cmd_curve(Evas_Filter_Context *ctx, Buffer *src, *dst; DATA8 values[256]; int *points; - int cmdid; src = _instruction_param_getbuf(instr, "src", NULL); dst = _instruction_param_getbuf(instr, "dst", NULL); @@ -3328,12 +3310,10 @@ _instr2cmd_curve(Evas_Filter_Context *ctx, values[x] = x; } - cmdid = evas_filter_command_curve_add(ctx, dc, src->cid, dst->cid, values, channel); - - return cmdid; + return evas_filter_command_curve_add(ctx, dc, src->cid, dst->cid, values, channel); } -static int +static Evas_Filter_Command * _instr2cmd_transform(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { @@ -3355,17 +3335,18 @@ _instr2cmd_transform(Evas_Filter_Context *ctx, else { ERR("Invalid transform '%s'", op); - return -1; + return NULL; } return evas_filter_command_transform_add(ctx, dc, src->cid, dst->cid, flags, ox, oy); } -static int +static Eina_Bool _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr, void *dc) { - int (* instr2cmd) (Evas_Filter_Context *, Evas_Filter_Instruction *, void *); + Evas_Filter_Command * (* instr2cmd) (Evas_Filter_Context *, Evas_Filter_Instruction *, void *); + Evas_Filter_Command *cmd; switch (instr->type) { @@ -3401,10 +3382,19 @@ _command_from_instruction(Evas_Filter_Context *ctx, return EINA_TRUE; default: CRI("Invalid instruction type: %d", instr->type); - return -1; + return EINA_FALSE; } - return instr2cmd(ctx, instr, dc); + cmd = instr2cmd(ctx, instr, dc); + if (!cmd) return EINA_FALSE; + + if (cmd->output && ctx->gl) + { + if (ENFN->gfx_filter_supports(ENDT, cmd) == EVAS_FILTER_SUPPORT_GL) + cmd->output->is_render = EINA_TRUE; + } + + return EINA_TRUE; } #ifdef FILTERS_DEBUG @@ -3477,7 +3467,6 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Instruction *instr; Eina_Bool success = EINA_FALSE; void *dc = NULL; - int cmdid; EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE); @@ -3518,8 +3507,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx, EINA_INLIST_FOREACH(pgm->instructions, instr) { _instruction_dump(instr); - cmdid = _command_from_instruction(ctx, instr, dc); - if (cmdid <= 0) + if (!_command_from_instruction(ctx, instr, dc)) goto end; } diff --git a/src/lib/evas/filters/evas_filter_private.h b/src/lib/evas/filters/evas_filter_private.h index 6ba1a89e67..d982e6b389 100644 --- a/src/lib/evas/filters/evas_filter_private.h +++ b/src/lib/evas/filters/evas_filter_private.h @@ -8,9 +8,9 @@ extern int _evas_filter_log_dom; #define EVAS_FILTER_LOG_COLOR EINA_COLOR_LIGHTBLUE -#ifdef DEBUG +//#ifdef DEBUG # define FILTERS_DEBUG -#endif +//#endif #ifdef ERR # undef ERR @@ -136,7 +136,7 @@ struct _Evas_Filter_Context struct { - int bufid; + void *surface; int x, y; int cx, cy, cw, ch; // clip int r, g, b, a; // clip color @@ -150,6 +150,7 @@ struct _Evas_Filter_Context Eina_Bool async : 1; Eina_Bool running : 1; Eina_Bool has_proxies : 1; + Eina_Bool gl : 1; }; struct _Evas_Filter_Command @@ -242,6 +243,7 @@ struct _Evas_Filter_Buffer Eina_Bool locked : 1; // internal flag Eina_Bool delete_me : 1; // request delete asap (after released by client) Eina_Bool dirty : 1; // Marked as dirty as soon as a command writes to it + Eina_Bool is_render : 1; // Is render target of a filter using engine functions (ie. needs FBO in GL) }; enum _Evas_Filter_Interpolation_Mode @@ -264,13 +266,9 @@ void evas_filter_context_source_set(Evas_Filter_Context *ctx void _clip_to_target(int *sx, int *sy, int sw, int sh, int ox, int oy, int dw, int dh, int *dx, int *dy, int *rows, int *cols); Eina_Bool evas_filter_buffer_alloc(Evas_Filter_Buffer *fb, int w, int h); Evas_Filter_Buffer *_filter_buffer_get(Evas_Filter_Context *ctx, int bufid); -Eina_Bool _filter_buffer_data_set(Evas_Filter_Context *ctx, int bufid, void *data, int w, int h, Eina_Bool alpha_only); -Evas_Filter_Buffer *_filter_buffer_data_new(Evas_Filter_Context *ctx, void *data, int w, int h, Eina_Bool alpha_only); -#define evas_filter_buffer_alloc_new(ctx, w, h, a) _filter_buffer_data_new(ctx, NULL, w, h, a) Evas_Filter_Buffer *evas_filter_temporary_buffer_get(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only); Evas_Filter_Buffer *evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx, Evas_Filter_Buffer *src, unsigned w, unsigned h); Eina_Bool evas_filter_interpolate(DATA8* output /* 256 values */, int *points /* 256 values */, Evas_Filter_Interpolation_Mode mode); -Evas_Filter_Command *_evas_filter_command_get(Evas_Filter_Context *ctx, int cmdid); int evas_filter_smallest_pow2_larger_than(int val); void evas_filter_parser_shutdown(void); diff --git a/src/lib/evas/include/evas_ector_buffer.eo b/src/lib/evas/include/evas_ector_buffer.eo index 9275e75c02..d70d9710bd 100644 --- a/src/lib/evas/include/evas_ector_buffer.eo +++ b/src/lib/evas/include/evas_ector_buffer.eo @@ -1,19 +1,42 @@ -/* Note: only for internal C API */ - import evas_canvas; interface Evas.Ector.Buffer { - [[Evas ector buffer interface]] + [[Binding layer between ector buffers and evas images. + + Subclasses implement support for RGBA_Image for SW & GL, + and Evas_GL_Image for GL. + + Note: Internal class, not API stable. + ]] methods { - @property engine_image { - [[Engine image property]] - get {} - set { [[This Buffer will hold a reference to the evas image struct.]] } - values { - evas: Evas.Canvas; [[The current Evas.]] - image: void_ptr; [[The engine-specific image struct.]] + engine_image_set { + [[Attach this ector buffer to an existing engine image.]] + params { + @in evas: Evas.Canvas; [[The current Evas.]] + @in image: void_ptr; [[The RGBA_Image or Evas_GL_Image.]] } } + drawable_image_get { + [[Fetch an engine image from this ector buffer as a drawable.]] + params { + @in update: bool; [[$true to update the data to the remote image.]] + } + return: void_ptr; [[The engine image (RGBA_Image or Evas_GL_Image).]] + } + render_image_get { + [[Fetch an engine image from this ector buffer as a render target.]] + params { + @in update: bool; [[$true to update the data to the remote image.]] + } + return: void_ptr; [[The engine image (RGBA_Image or Evas_GL_Image).]] + } + engine_image_release { + [[Release an image from @.drawable_image_get or @.render_image_get.]] + params { + @in image: void_ptr; [[Return value of @.drawable_image_get or @.render_image_get.]] + } + return: bool; [[$false in case of error.]] + } } } diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h index cfea9bd197..0736b5b542 100644 --- a/src/lib/evas/include/evas_filter.h +++ b/src/lib/evas/include/evas_filter.h @@ -146,7 +146,6 @@ void evas_filter_context_post_run_callback_set(Evas_Filter_C Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx); int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only); -void *evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid); void *evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid); Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context *ctx, void *stolen_buffer); @@ -171,7 +170,7 @@ void _evas_filter_source_hash_free_cb(void *data); * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int ox, int oy, Evas_Filter_Fill_Mode fillmode); +Evas_Filter_Command *evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int ox, int oy, Evas_Filter_Fill_Mode fillmode); /** * @brief Apply a blur effect on a buffer @@ -188,7 +187,7 @@ int evas_filter_command_blend_add(Evas_Filter_Context *ctx, * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Blur_Type type, int dx, int dy, int ox, int oy, int count); +Evas_Filter_Command *evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Blur_Type type, int dx, int dy, int ox, int oy, int count); /** * @brief Fill a buffer with the current color @@ -199,7 +198,7 @@ int evas_filter_command_blur_add(Evas_Filter_Context *ctx, * @note The current draw context's render operation is ignored (always uses COPY mode). * @internal */ -int evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, int buf); +Evas_Filter_Command *evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, int buf); /** * @brief evas_filter_command_curve_add @@ -212,7 +211,7 @@ int evas_filter_command_fill_add(Evas_Filter_Context *ctx, * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_curve_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, DATA8 *curve /* 256 elements */, Evas_Filter_Channel channel); +Evas_Filter_Command *evas_filter_command_curve_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, DATA8 *curve /* 256 elements */, Evas_Filter_Channel channel); /** * @brief Grow/Shrink an image, as defined in image processing (this is not a scale algorithm!) @@ -225,7 +224,7 @@ int evas_filter_command_curve_add(Evas_Filter_Context *ctx, * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int radius, Eina_Bool smooth); +Evas_Filter_Command *evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int radius, Eina_Bool smooth); /** * @brief Apply a displacement map to a buffer. This will move pixels from the source to the destination based on pixel per pixel offset, as defined in the displacement map @@ -240,7 +239,7 @@ int evas_filter_command_grow_add(Evas_Filter_Context *ctx, * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int dispbuf, Evas_Filter_Displacement_Flags flags, int intensity, Evas_Filter_Fill_Mode fillmode); +Evas_Filter_Command *evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int dispbuf, Evas_Filter_Displacement_Flags flags, int intensity, Evas_Filter_Fill_Mode fillmode); /** * @brief Apply a texture to a buffer @@ -254,7 +253,7 @@ int evas_filter_command_displacement_map_add(Evas_Filter_Co * @note For the moment, inbuf can only be ALPHA, and output must be RGBA if mask is RGBA as well * @internal */ -int evas_filter_command_mask_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int maskbuf, int outbuf, Evas_Filter_Fill_Mode fillmode); +Evas_Filter_Command *evas_filter_command_mask_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int maskbuf, int outbuf, Evas_Filter_Fill_Mode fillmode); /** * @brief Apply a relief effect based on a bump map (Z map) @@ -275,7 +274,7 @@ int evas_filter_command_mask_add(Evas_Filter_Context *ctx, * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int bumpbuf, int outbuf, float azimuth, float elevation, float depth, float specular_factor, DATA32 black, DATA32 color, DATA32 white, Evas_Filter_Bump_Flags flags, Evas_Filter_Fill_Mode fillmode); +Evas_Filter_Command *evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int bumpbuf, int outbuf, float azimuth, float elevation, float depth, float specular_factor, DATA32 black, DATA32 color, DATA32 white, Evas_Filter_Bump_Flags flags, Evas_Filter_Fill_Mode fillmode); /** * @brief Apply a geometrical transformation to the buffer @@ -289,7 +288,7 @@ int evas_filter_command_bump_map_add(Evas_Filter_Context *c * @return Filter command ID or -1 in case of error * @internal */ -int evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Transform_Flags flags, int ox, int oy); +Evas_Filter_Command *evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Transform_Flags flags, int ox, int oy); /* Simple binding between a filter object and its sources */ struct _Evas_Filter_Proxy_Binding diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 4d6f608ac8..98c68a0b62 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1572,8 +1572,8 @@ 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, 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); + Ector_Buffer *(*ector_buffer_wrap) (void *data, Evas *e, void *engine_image); + Ector_Buffer *(*ector_buffer_new) (void *data, Evas *e, int width, int height, Efl_Gfx_Colorspace cspace, 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); void (*ector_end) (void *data, void *context, Ector_Surface *ector, void *surface, void *engine_data, Eina_Bool do_async); diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index ef91f7b9d6..38474bbe35 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -688,6 +688,7 @@ void evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, void evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im); void evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int npoints, RGBA_Map_Point *p, int smooth, int level); void evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth); +Evas_GL_Image *evas_gl_common_image_surface_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im); void *evas_gl_font_texture_new(void *gc, RGBA_Font_Glyph *fg); void evas_gl_font_texture_free(void *); diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c index 3b02db1406..de907be540 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -248,6 +248,8 @@ evas_gl_common_image_new_from_rgbaimage(Evas_Engine_GL_Context *gc, RGBA_Image * } */ + if (error) *error = EVAS_LOAD_ERROR_NONE; + // FIXME: keep unreffed shared images around EINA_LIST_FOREACH(gc->shared->images, l, im) { @@ -1039,6 +1041,65 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im) } } +Evas_GL_Image * +evas_gl_common_image_surface_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im) +{ + Evas_GL_Image *glim = NULL; + Eina_Bool alpha; + int w, h; + + if (!gc || !im || !im->im || !im->im->image.data) + goto fail; + + if (im->im->cache_entry.space == EFL_GFX_COLORSPACE_ARGB8888) + alpha = EINA_FALSE; + else if (im->im->cache_entry.space == EFL_GFX_COLORSPACE_GRY8) + alpha = EINA_TRUE; + else goto fail; + + w = im->im->cache_entry.w; + h = im->im->cache_entry.h; + glim = evas_gl_common_image_surface_new(gc, w, h, EINA_TRUE, EINA_FALSE); + if (!glim) goto fail; + + if (alpha) + { + RGBA_Image *image; + uint32_t *rgba; + uint8_t *gry8; + int k; + + image = evas_common_image_new(w, h, EINA_TRUE); + if (!image) goto fail; + + rgba = image->image.data; + gry8 = im->im->image.data8; + for (k = 0; k < (w * h); k++) + { + const int c = *gry8++; + *rgba++ = ARGB_JOIN(c, c, c, c); + } + + glim->im = image; + } + else + { + evas_cache_image_ref(&im->im->cache_entry); + glim->im = im->im; + } + + glim->dirty = EINA_TRUE; + evas_gl_common_image_update(gc, glim); + evas_gl_common_image_free(im); + + return glim; + +fail: + ERR("Failed to update surface pixels!"); + if (glim) evas_gl_common_image_free(glim); + return NULL; +} + void evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int npoints, RGBA_Map_Point *p, int smooth, int level EINA_UNUSED) diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c b/src/modules/evas/engines/gl_common/evas_gl_texture.c index f4d747e331..77c55f593b 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_texture.c +++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c @@ -82,6 +82,7 @@ static const struct { { MATCH_FALSE, MATCH_FALSE, EVAS_COLORSPACE_ARGB8888, &rgb_ifmt, &rgb_fmt }, #endif { MATCH_FALSE, MATCH_ANY, EVAS_COLORSPACE_GRY8, &lum_fmt, &lum_ifmt }, + { MATCH_TRUE, MATCH_ANY, EVAS_COLORSPACE_GRY8, &alpha_fmt, &alpha_ifmt }, { MATCH_TRUE, MATCH_ANY, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt }, // ETC1/2 support { MATCH_FALSE, MATCH_ANY, EVAS_COLORSPACE_ETC1, &etc1_fmt, &etc1_fmt }, diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c index 4736e6592c..ef8999e160 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c @@ -2,13 +2,357 @@ # include "config.h" #endif +#define ECTOR_GL_BUFFER_BASE_PROTECTED + +#include "evas_common_private.h" +#include "evas_gl_private.h" + #include #include "gl/ector_gl_private.h" #include "evas_common_private.h" +#include "../gl_common/evas_gl_common.h" +#include "evas_private.h" #include "ector_buffer.h" +#include "Evas_Engine_GL_Generic.h" + #include "evas_ector_buffer.eo.h" #include "evas_ector_gl_buffer.eo.h" #define MY_CLASS EVAS_ECTOR_GL_BUFFER_CLASS +typedef struct _Ector_GL_Buffer_Map Ector_GL_Buffer_Map; +typedef struct _Evas_Ector_GL_Buffer_Data Evas_Ector_GL_Buffer_Data; + +struct _Ector_GL_Buffer_Map +{ + EINA_INLIST; + void *ptr; + unsigned int base_size; // in bytes + unsigned int x, y, w, h; + void *image_data, *base_data; + size_t length; + Efl_Gfx_Colorspace cspace; + Evas_GL_Image *im; + Eina_Bool allocated; + Ector_Buffer_Access_Flag mode; +}; + +struct _Evas_Ector_GL_Buffer_Data +{ + Evas_Public_Data *evas; + Evas_GL_Image *glim; + Eina_Bool alpha_only; + Ector_GL_Buffer_Map *maps; +}; + +#define ENFN pd->evas->engine.func +#define ENDT pd->evas->engine.data.output + +// testing out some macros to maybe add to eina +#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) +#define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) +#define EINA_INLIST_PREPEND(l,i) do { l = (__typeof__(l)) eina_inlist_prepend(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) + +#define fail(fmt, ...) do { ERR(fmt, ##__VA_ARGS__); goto on_fail; } while (0) + +/* FIXME: Conversion routines don't belong here */ +static inline void +_pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len) +{ + int k; + for (k = 0; k < len; k++) + { + const uint32_t *s = src++; + *dst++ = A_VAL(s); + } +} + +static inline void +_pixels_gry8_to_argb_convert(uint32_t *dst, const uint8_t *src, int len) +{ + int k; + for (k = 0; k < len; k++) + { + const uint8_t s = *src++; + *dst++ = ARGB_JOIN(s, s, s, s); + } +} + +static inline Eina_Bool +_evas_gl_image_is_fbo(Evas_GL_Image *glim) +{ + return glim && glim->tex && glim->tex->pt && glim->tex->pt->fb; +} + +EOLIAN static void +_evas_ector_gl_buffer_gl_buffer_prepare(Eo *obj, Evas_Ector_GL_Buffer_Data *pd, + Evas_Canvas *eo_evas, + int w, int h, Efl_Gfx_Colorspace cspace, + Ector_Buffer_Flag flags EINA_UNUSED) +{ + Render_Engine_GL_Generic *re; + Evas_Engine_GL_Context *gc; + Evas_GL_Image *im; + + // this is meant to be called only once + EINA_SAFETY_ON_FALSE_GOTO(!pd->evas, on_fail); + EINA_SAFETY_ON_FALSE_GOTO(!efl_finalized_get(obj), on_fail); + + if (cspace == EFL_GFX_COLORSPACE_ARGB8888) + pd->alpha_only = EINA_FALSE; + else if (cspace == EFL_GFX_COLORSPACE_GRY8) + pd->alpha_only = EINA_TRUE; + else + fail("Unsupported colorspace: %u", cspace); + + pd->evas = efl_data_xref(eo_evas, EVAS_CANVAS_CLASS, obj); + re = pd->evas->engine.data.output; + gc = re->window_gl_context_get(re->software.ob); + + im = evas_gl_common_image_surface_new(gc, w, h, EINA_TRUE, EINA_FALSE); + if (!im) fail("Failed to create GL surface!"); + + pd->glim = im; + return; + +on_fail: + if (pd->glim) evas_gl_common_image_free(pd->glim); + pd->glim = NULL; +} + +EOLIAN static void * +_evas_ector_gl_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Buffer_Data *pd, + Eina_Bool update) +{ + Render_Engine_GL_Generic *re = pd->evas->engine.data.output; + Evas_Engine_GL_Context *gc; + + if (pd->maps != NULL) + fail("Image is currently mapped!"); + + evas_gl_common_image_ref(pd->glim); + if (!update) return pd->glim; + + gc = re->window_gl_context_get(re->software.ob); + evas_gl_common_image_update(gc, pd->glim); + + return pd->glim; + +on_fail: + return NULL; +} + +EOLIAN static void * +_evas_ector_gl_buffer_evas_ector_buffer_render_image_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Buffer_Data *pd, + Eina_Bool update) +{ + Render_Engine_GL_Generic *re = pd->evas->engine.data.output; + Evas_Engine_GL_Context *gc; + + if (pd->maps != NULL) + fail("Image is currently mapped!"); + + evas_gl_common_image_ref(pd->glim); + if (!update) return pd->glim; + + gc = re->window_gl_context_get(re->software.ob); + evas_gl_common_image_update(gc, pd->glim); + + return pd->glim; + +on_fail: + return NULL; +} + +EOLIAN static Eina_Bool +_evas_ector_gl_buffer_evas_ector_buffer_engine_image_release(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Buffer_Data *pd, + void *image) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(pd->glim == image, EINA_FALSE); + + evas_gl_common_image_free(pd->glim); + + return EINA_TRUE; +} + +EOLIAN static void +_evas_ector_gl_buffer_ector_buffer_size_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Buffer_Data *pd, + int *w, int *h) +{ + if (w) *w = pd->glim->w; + if (h) *h = pd->glim->h; +} + +EOLIAN static Efl_Gfx_Colorspace +_evas_ector_gl_buffer_ector_buffer_cspace_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Buffer_Data *pd) +{ + if (pd->alpha_only) + return EFL_GFX_COLORSPACE_GRY8; + else + return EFL_GFX_COLORSPACE_ARGB8888; +} + +EOLIAN static Ector_Buffer_Flag +_evas_ector_gl_buffer_ector_buffer_flags_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Buffer_Data *pd EINA_UNUSED) +{ + return ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_DRAWABLE | + ECTOR_BUFFER_FLAG_CPU_WRITABLE | ECTOR_BUFFER_FLAG_RENDERABLE; +} + +EOLIAN static void * +_evas_ector_gl_buffer_ector_buffer_map(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buffer_Data *pd, + unsigned int *length, + Ector_Buffer_Access_Flag mode, + unsigned int x, unsigned int y, unsigned int w, unsigned int h, + Efl_Gfx_Colorspace cspace, unsigned int *stride) +{ + Eina_Bool write = !!(mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE); + Ector_GL_Buffer_Map *map = NULL; + Eina_Bool tofree = EINA_FALSE; + Evas_GL_Image *im = NULL; + unsigned int W, H; + int len, err; + uint32_t *data; + int pxs; + + W = pd->glim->w; + H = pd->glim->h; + if (!w) w = W - x; + if (!h) h = H - y; + if ((x + w > W) || (y + h > H)) return NULL; + + if (write && _evas_gl_image_is_fbo(pd->glim)) + { + // Can not open FBO data to write! + im = ENFN->image_data_get(ENDT, pd->glim, EINA_FALSE, &data, &err, &tofree); + if (!im) return NULL; + } + else + { + im = ENFN->image_data_get(ENDT, pd->glim, write, &data, &err, &tofree); + if (!im) return NULL; + } + + map = calloc(1, sizeof(*map)); + map->mode = mode; + map->cspace = cspace; + map->x = x; + map->y = y; + map->w = w; + map->h = h; + map->image_data = data; + map->im = tofree ? im : NULL; + + len = W * H; + if (cspace == EFL_GFX_COLORSPACE_GRY8) + { + uint8_t *data8 = malloc(len); + + if (!data8) goto on_fail; + _pixels_argb_to_gry8_convert(data8, data, len); + map->allocated = EINA_TRUE; + map->base_data = data8; + map->ptr = data8 + x + (y * W); + pxs = 1; + } + else + { + map->allocated = EINA_FALSE; + map->base_data = data; + map->ptr = data + x + (y * W); + pxs = 4; + } + + map->base_size = len * pxs; + map->length = (W * h + w - W) * pxs; + if (stride) *stride = W * pxs; + if (length) *length = map->length; + + EINA_INLIST_PREPEND(pd->maps, map);; + return map->ptr; + +on_fail: + free(map); + return NULL; +} + +EOLIAN static void +_evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buffer_Data *pd, + void *data, unsigned int length) +{ + Ector_GL_Buffer_Map *map; + if (!data) return; + + EINA_INLIST_FOREACH(pd->maps, map) + { + if ((map->ptr == data) && (map->length == length)) + { + EINA_INLIST_REMOVE(pd->maps, map); + if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) + { + Render_Engine_GL_Generic *re = pd->evas->engine.data.output; + Evas_GL_Image *old_glim = pd->glim; + Evas_Engine_GL_Context *gc; + int W, H; + + W = pd->glim->w; + H = pd->glim->h; + gc = re->window_gl_context_get(re->software.ob); + + if (map->cspace == EFL_GFX_COLORSPACE_GRY8) + _pixels_gry8_to_argb_convert(map->image_data, map->base_data, W * H); + + if (map->im) + { + pd->glim = evas_gl_common_image_surface_update(gc, map->im); + evas_gl_common_image_free(old_glim); + } + else + { + pd->glim = evas_gl_common_image_surface_update(gc, old_glim); + } + } + else + { + if (map->im) + ENFN->image_free(ENDT, map->im); + else + ENFN->image_data_put(ENDT, pd->glim, map->image_data); + } + if (map->allocated) + free(map->base_data); + free(map); + return; + } + } + + ERR("Tried to unmap a non-mapped region!"); +} + +EOLIAN static Efl_Object * +_evas_ector_gl_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_Buffer_Data *pd) +{ + if (!pd->glim) + { + ERR("Buffer was not initialized properly!"); + return NULL; + } + return efl_finalize(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_evas_ector_gl_buffer_efl_object_destructor(Eo *obj, Evas_Ector_GL_Buffer_Data *pd) +{ + evas_gl_common_image_free(pd->glim); + efl_data_xunref(pd->evas->evas, pd->evas, obj); + efl_destructor(efl_super(obj, MY_CLASS)); +} + #include "evas_ector_gl_buffer.eo.c" diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.eo b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.eo index 417ee53136..6c6bdc03b9 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.eo +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.eo @@ -1,5 +1,35 @@ -class Evas.Ector.GL.Buffer (Efl.Object, Evas.Ector.Buffer, Ector.GL.Buffer.Base) +class Evas.Ector.GL.Buffer (Efl.Object, Evas.Ector.Buffer, Ector.GL.Buffer) { - [[Evas ector GL buffer class]] - data: null; + [[An Ector GL buffer capable of being mapped, drawn and rendered to. + + Potentially very inefficient (may rely on glReadPixels). + ]] + methods { + gl_buffer_prepare { + [[Set the main properties to create a gl buffer.]] + params { + evas: Evas.Canvas; [[The current canvas]] + w: int; [[Width]] + h: int; [[Height]] + cspace: Efl.Gfx.Colorspace; [[Alpha or RGBA]] + flags: Ector.Buffer.Flag; [[Required buffer capabilities + (map/draw/render, etc...)]] + } + } + } + constructors { + .gl_buffer_prepare; + } + implements { + Efl.Object.finalize; + Efl.Object.destructor; + Evas.Ector.Buffer.drawable_image_get; + Evas.Ector.Buffer.render_image_get; + Evas.Ector.Buffer.engine_image_release; + Ector.Buffer.size { get; } + Ector.Buffer.cspace { get; } + Ector.Buffer.flags { get; } + Ector.Buffer.map; + Ector.Buffer.unmap; + } } 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 4625071d8c..647f7cc7df 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 @@ -2,14 +2,20 @@ # include "config.h" #endif +/* this one is read-only buffer wrapping an existing evas_gl_image */ + #define ECTOR_GL_BUFFER_BASE_PROTECTED +#include "evas_common_private.h" +#include "evas_gl_private.h" + #include #include "gl/ector_gl_private.h" #include "evas_common_private.h" #include "../gl_common/evas_gl_common.h" #include "evas_private.h" #include "ector_buffer.h" +#include "Evas_Engine_GL_Generic.h" #include "evas_ector_buffer.eo.h" #include "evas_ector_gl_buffer.eo.h" @@ -17,30 +23,36 @@ #define MY_CLASS EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS -typedef struct _Ector_GL_Buffer_Map +typedef struct _Ector_GL_Buffer_Map Ector_GL_Buffer_Map; +typedef struct _Evas_Ector_GL_Image_Buffer_Data Evas_Ector_GL_Image_Buffer_Data; + +struct _Ector_GL_Buffer_Map { EINA_INLIST; void *ptr; - unsigned int size; // in bytes + unsigned int base_size; // in bytes unsigned int x, y, w, h; + void *image_data, *base_data; + size_t length; Efl_Gfx_Colorspace cspace; Evas_GL_Image *im; - Eina_Bool allocated; + Eina_Bool allocated, free_image; Ector_Buffer_Access_Flag mode; -} Ector_GL_Buffer_Map; +}; -typedef struct +struct _Evas_Ector_GL_Image_Buffer_Data { - Ector_GL_Buffer_Base_Data *base; - Evas *evas; - Evas_GL_Image *image; - struct { - Eina_Inlist *maps; // Ector_GL_Buffer_Map - } internal; -} Evas_Ector_GL_Image_Buffer_Data; + Evas_Public_Data *evas; + Evas_GL_Image *glim; + Ector_GL_Buffer_Map *maps; +}; -#define ENFN e->engine.func -#define ENDT e->engine.data.output +#define ENFN pd->evas->engine.func +#define ENDT pd->evas->engine.data.output + +// testing out some macros to maybe add to eina +#define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) +#define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) /* FIXME: Conversion routines don't belong here */ static inline void @@ -58,92 +70,99 @@ EOLIAN static void _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, Evas *evas, void *image) { - Evas_Public_Data *e = efl_data_scope_get(evas, EVAS_CANVAS_CLASS); Evas_GL_Image *im = image; - int l = 0, r = 0, t = 0, b = 0; - if (pd->base->generic->immutable) - { - CRI("Can't set image after finalize"); - return; - } - - pd->evas = efl_xref(evas, obj); + EINA_SAFETY_ON_FALSE_RETURN(!pd->glim); EINA_SAFETY_ON_NULL_RETURN(im); - if (im->tex && im->tex->pt) - { - if (im->im) - { - l = im->im->cache_entry.borders.l; - r = im->im->cache_entry.borders.r; - t = im->im->cache_entry.borders.t; - b = im->im->cache_entry.borders.b; - } - else - { - // always 1 pixel border, except FBO - if (!im->tex->pt->fb) - l = r = t = b = 1; - } - - pd->image = ENFN->image_ref(ENDT, im); - ector_gl_buffer_base_attach(obj, im->tex->pt->texture, im->tex->pt->fb, (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, l, r, t, b); - } - else - { - // FIXME: This might be required to support texture upload here - ERR("Image has no attached texture! Unsupported!"); - pd->image = NULL; - } + pd->evas = efl_data_xref(evas, EVAS_CANVAS_CLASS, obj); + evas_gl_common_image_ref(im); + pd->glim = im; } -EOLIAN static void -_evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_get(Eo *obj EINA_UNUSED, - Evas_Ector_GL_Image_Buffer_Data *pd, - Evas **evas, void **image) +EOLIAN static void * +_evas_ector_gl_image_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Image_Buffer_Data *pd, + Eina_Bool update EINA_UNUSED) { - if (evas) *evas = pd->evas; - if (image) *image = pd->image; + evas_gl_common_image_ref(pd->glim); + return pd->glim; +} + +EOLIAN static Eina_Bool +_evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_release(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Image_Buffer_Data *pd, + void *image) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(pd->glim == image, EINA_FALSE); + + evas_gl_common_image_free(pd->glim); + return EINA_TRUE; } EOLIAN static Ector_Buffer_Flag _evas_ector_gl_image_buffer_ector_buffer_flags_get(Eo *obj EINA_UNUSED, - Evas_Ector_GL_Image_Buffer_Data *pd) + Evas_Ector_GL_Image_Buffer_Data *pd EINA_UNUSED) { - Ector_Buffer_Flag flags; + return ECTOR_BUFFER_FLAG_CPU_READABLE | ECTOR_BUFFER_FLAG_DRAWABLE; +} - if (!pd->image) return 0; +EOLIAN static void +_evas_ector_gl_image_buffer_ector_buffer_size_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Image_Buffer_Data *pd, + int *w, int *h) +{ + if (w) *w = pd->glim->w; + if (h) *h = pd->glim->h; +} - flags = ECTOR_BUFFER_FLAG_CPU_READABLE; - if (pd->image->tex) - { - flags |= ECTOR_BUFFER_FLAG_DRAWABLE; - if (pd->image->tex->pt->fb) - flags |= ECTOR_BUFFER_FLAG_RENDERABLE; - } - if (pd->image->im) - flags |= ECTOR_BUFFER_FLAG_CPU_WRITABLE; - - return flags; +EOLIAN static Efl_Gfx_Colorspace +_evas_ector_gl_image_buffer_ector_buffer_cspace_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Image_Buffer_Data *pd EINA_UNUSED) +{ + return EFL_GFX_COLORSPACE_ARGB8888; } EOLIAN static void * _evas_ector_gl_image_buffer_ector_buffer_map(Eo *obj EINA_UNUSED, Evas_Ector_GL_Image_Buffer_Data *pd, unsigned int *length, - Ector_Buffer_Access_Flag mode, - unsigned int x, unsigned int y, unsigned int w, unsigned int h, - Efl_Gfx_Colorspace cspace, unsigned int *stride) + Ector_Buffer_Access_Flag mode, + unsigned int x, unsigned int y, unsigned int w, unsigned int h, + Efl_Gfx_Colorspace cspace, unsigned int *stride) { - Evas_Public_Data *e = efl_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); Ector_GL_Buffer_Map *map = NULL; Eina_Bool tofree = EINA_FALSE; - Evas_GL_Image *im; - uint32_t *data; + Evas_GL_Image *im = NULL; + unsigned int W, H; int len, err; + uint32_t *data; + int pxs; - im = ENFN->image_data_get(ENDT, pd->image, - mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE, - &data, &err, &tofree); + if ((cspace != EFL_GFX_COLORSPACE_GRY8) && (cspace != EFL_GFX_COLORSPACE_ARGB8888)) + { + ERR("Unsupported colorspace for map: %d", (int) cspace); + return NULL; + } + + if (mode == EFL_GFX_BUFFER_ACCESS_MODE_NONE) + { + ERR("Invalid access mode for map (none)"); + return NULL; + } + + if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE) + { + ERR("%s does not support write access for map", efl_class_name_get(MY_CLASS)); + return NULL; + } + + W = pd->glim->w; + H = pd->glim->h; + if (!w) w = W - x; + if (!h) h = H - y; + if ((x + w > W) || (y + h > H)) return NULL; + + im = ENFN->image_data_get(ENDT, pd->glim, EINA_FALSE, &data, &err, &tofree); if (!im) return NULL; map = calloc(1, sizeof(*map)); @@ -153,111 +172,89 @@ _evas_ector_gl_image_buffer_ector_buffer_map(Eo *obj EINA_UNUSED, Evas_Ector_GL_ map->y = y; map->w = w; map->h = h; - map->ptr = data; + map->image_data = data; + map->im = im; + map->free_image = tofree; - if (tofree) - map->im = im; - else - map->im = NULL; - - len = w * h; + len = W * H; if (cspace == EFL_GFX_COLORSPACE_GRY8) { uint8_t *data8 = malloc(len); + + if (!data8) goto fail; _pixels_argb_to_gry8_convert(data8, data, len); map->allocated = EINA_TRUE; - map->ptr = data8; - map->size = len; - if (stride) *stride = w; + map->base_data = data8; + map->ptr = data8 + x + (y * W); + pxs = 1; } else { map->allocated = EINA_FALSE; - map->ptr = data; - map->size = len * 4; - if (stride) *stride = w * 4; + map->base_data = data; + map->ptr = data + x + (y * W); + pxs = 4; } - if (length) *length = map->size; + map->base_size = len * pxs; + map->length = (W * h + w - W) * pxs; + if (stride) *stride = W * pxs; + if (length) *length = map->length; - pd->internal.maps = eina_inlist_prepend(pd->internal.maps, EINA_INLIST_GET(map)); + if (!tofree) + pd->glim = im; + + EINA_INLIST_APPEND(pd->maps, map); return map->ptr; + +fail: + free(map); + return NULL; } EOLIAN static void -_evas_ector_gl_image_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Image_Buffer_Data *pd, - void *data, unsigned int length) +_evas_ector_gl_image_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Image_Buffer_Data *pd, + void *data, unsigned int length) { - Evas_Public_Data *e = efl_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); Ector_GL_Buffer_Map *map; if (!data) return; - EINA_INLIST_FOREACH(pd->internal.maps, map) + EINA_INLIST_FOREACH(pd->maps, map) { - if ((map->ptr == data) && ((map->size == length) || (length == (unsigned int) -1))) + if ((map->base_data == data) && (map->length == length)) { - pd->internal.maps = eina_inlist_remove(pd->internal.maps, EINA_INLIST_GET(map)); - if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) - { - CRI("Not implemented yet. Dropping pixel changes."); - } - if (map->im) + EINA_INLIST_REMOVE(pd->maps, map); + if (map->free_image) ENFN->image_free(ENDT, map->im); + else + ENFN->image_data_put(ENDT, map->im, map->image_data); if (map->allocated) - free(map->ptr); + free(map->base_data); + free(map); return; } } - CRI("Tried to unmap a non-mapped region!"); -} - -EOLIAN static uint8_t * -_evas_ector_gl_image_buffer_ector_buffer_span_get(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, int x, int y, unsigned int w, - Efl_Gfx_Colorspace cspace, unsigned int *length) -{ - // ector_buffer_map - return _evas_ector_gl_image_buffer_ector_buffer_map - (obj, pd, length, ECTOR_BUFFER_ACCESS_FLAG_READ, x, y, w, 1, cspace, NULL); -} - -EOLIAN static void -_evas_ector_gl_image_buffer_ector_buffer_span_free(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, uint8_t *data) -{ - // ector_buffer_unmap - return _evas_ector_gl_image_buffer_ector_buffer_unmap - (obj, pd, data, (unsigned int) -1); -} - - -EOLIAN static Efl_Object * -_evas_ector_gl_image_buffer_efl_object_constructor(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd) -{ - obj = efl_constructor(efl_super(obj, MY_CLASS)); - pd->base = efl_data_ref(obj, ECTOR_GL_BUFFER_BASE_MIXIN); - pd->base->generic = efl_data_ref(obj, ECTOR_BUFFER_MIXIN); - pd->base->generic->eo = obj; - return obj; + ERR("Tried to unmap a non-mapped region: %p +%u", data, length); } EOLIAN static Efl_Object * _evas_ector_gl_image_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd) { - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->base, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->image, NULL); - pd->base->generic->immutable = EINA_TRUE; + if (!pd->glim) + { + ERR("Buffer was not initialized properly!"); + return NULL; + } return efl_finalize(efl_super(obj, MY_CLASS)); } EOLIAN static void _evas_ector_gl_image_buffer_efl_object_destructor(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd) { - Evas_Public_Data *e = efl_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); - - efl_data_unref(obj, pd->base->generic); - efl_data_unref(obj, pd->base); - ENFN->image_free(ENDT, pd->image); - efl_xunref(pd->evas, obj); + evas_gl_common_image_free(pd->glim); + efl_data_xunref(pd->evas->evas, pd->evas, obj); efl_destructor(efl_super(obj, MY_CLASS)); } 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 eff9d82984..ccf1534549 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,14 +1,15 @@ -class Evas.Ector.GL.Image.Buffer (Evas.Ector.GL.Buffer, Evas.Ector.Buffer) +class Evas.Ector.GL.Image.Buffer (Efl.Object, Evas.Ector.Buffer, Ector.GL.Buffer) { [[An Ector GL buffer wrapping an existing Evas_GL_Image.]] implements { - Efl.Object.constructor; Efl.Object.finalize; Efl.Object.destructor; - Evas.Ector.Buffer.engine_image { get; set; } + Evas.Ector.Buffer.engine_image_set; + Evas.Ector.Buffer.drawable_image_get; + Evas.Ector.Buffer.engine_image_release; + Ector.Buffer.size { get; } + Ector.Buffer.cspace { get; } Ector.Buffer.flags { get; } - Ector.Buffer.span_get; - Ector.Buffer.span_free; Ector.Buffer.map; Ector.Buffer.unmap; } diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.c deleted file mode 100644 index 91bb22220d..0000000000 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.c +++ /dev/null @@ -1,117 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "evas_common_private.h" -#include "evas_gl_private.h" - -#include -#include -#include "Evas_Engine_GL_Generic.h" - -#include "evas_ector_buffer.eo.h" -#include "evas_ector_gl_rgbaimage_buffer.eo.h" -#include "../software_generic/evas_ector_software_buffer.eo.h" - -#define MY_CLASS EVAS_ECTOR_GL_RGBAIMAGE_BUFFER_CLASS - -typedef struct { - Ector_Software_Buffer_Base_Data *base; - Evas *evas; - RGBA_Image *image; - Evas_GL_Image *glim; -} Evas_Ector_GL_RGBAImage_Buffer_Data; - -// GL engine stuff, do not use with RGBA_Image / Image_Entry -#define ENFN e->engine.func -#define ENDT e->engine.data.output - -EOLIAN static void -_evas_ector_gl_rgbaimage_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_GL_RGBAImage_Buffer_Data *pd, - Evas *evas, void *image) -{ - RGBA_Image *im = image; - - EINA_SAFETY_ON_NULL_RETURN(image); - if (efl_finalized_get(obj)) - { - CRI("engine_image must be set at construction time only"); - return; - } - - if (!im->image.data) - { - CRI("image has no pixels yet"); - return; - } - - pd->evas = efl_xref(evas, obj); - evas_cache_image_ref(&im->cache_entry); - pd->image = im; - - ector_buffer_pixels_set(obj, im->image.data, im->cache_entry.w, im->cache_entry.h, 0, (Efl_Gfx_Colorspace) im->cache_entry.space, EINA_TRUE, 0, 0, 0, 0); -} - -EOLIAN static void -_evas_ector_gl_rgbaimage_buffer_evas_ector_buffer_engine_image_get(Eo *obj EINA_UNUSED, - Evas_Ector_GL_RGBAImage_Buffer_Data *pd, - Evas **evas, void **image) -{ - Evas_Public_Data *e = efl_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); - Render_Engine_GL_Generic *re = e->engine.data.output; - int err = EVAS_LOAD_ERROR_NONE; - Evas_Engine_GL_Context *gc; - - if (evas) *evas = pd->evas; - if (image) *image = NULL; - if (pd->glim) - goto end; - - gc = re->window_gl_context_get(re->software.ob); -#ifdef EVAS_CSERVE2 - if (evas_cache2_image_cached(&pd->image->cache_entry)) - evas_cache2_image_ref(&pd->image->cache_entry); - else -#endif - evas_cache_image_ref(&pd->image->cache_entry); - pd->glim = evas_gl_common_image_new_from_rgbaimage(gc, pd->image, NULL, &err); - if ((err != EVAS_LOAD_ERROR_NONE) || !pd->glim) - { - ERR("Failed to create GL image! error %d", err); - return; - } - -end: - if (image) *image = pd->glim; -} - -EOLIAN static Eo * -_evas_ector_gl_rgbaimage_buffer_efl_object_constructor(Eo *obj, Evas_Ector_GL_RGBAImage_Buffer_Data *pd) -{ - obj = efl_constructor(efl_super(obj, MY_CLASS)); - pd->base = efl_data_xref(obj, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN, obj); - return obj; -} - -EOLIAN static Eo * -_evas_ector_gl_rgbaimage_buffer_efl_object_finalize(Eo *obj, Evas_Ector_GL_RGBAImage_Buffer_Data *pd) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->base, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->image, NULL); - pd->base->generic->immutable = EINA_TRUE; - return efl_finalize(efl_super(obj, MY_CLASS)); -} - -EOLIAN static void -_evas_ector_gl_rgbaimage_buffer_efl_object_destructor(Eo *obj, Evas_Ector_GL_RGBAImage_Buffer_Data *pd) -{ - Evas_Public_Data *e = efl_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); - - efl_data_xunref(obj, pd->base, obj); - ENFN->image_free(ENDT, pd->glim); - evas_cache_image_drop(&pd->image->cache_entry); - efl_xunref(pd->evas, obj); - efl_destructor(efl_super(obj, MY_CLASS)); -} - -#include "evas_ector_gl_rgbaimage_buffer.eo.c" diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.eo b/src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.eo deleted file mode 100644 index 1bb15e8a5b..0000000000 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_rgbaimage_buffer.eo +++ /dev/null @@ -1,10 +0,0 @@ -class Evas.Ector.GL.RGBAImage.Buffer (Ector.Software.Buffer, Evas.Ector.Buffer) -{ - [[A buffer object wrapping an existing Evas RGBA_Image for the GL Engine.]] - implements { - Efl.Object.constructor; - Efl.Object.finalize; - Efl.Object.destructor; - Evas.Ector.Buffer.engine_image { get; set; } - } -} diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 00fcc1d555..fe127d4936 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -7,7 +7,6 @@ #include "evas_ector_buffer.eo.h" #include "evas_ector_gl_buffer.eo.h" #include "evas_ector_gl_image_buffer.eo.h" -#include "evas_ector_gl_rgbaimage_buffer.eo.h" #include "filters/gl_engine_filter.h" #if defined HAVE_DLSYM && ! defined _WIN32 @@ -844,11 +843,11 @@ 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."); + ERR("ReadPixels failed."); return NULL; } *image_data = im_new->im->image.data; - if (tofree) *tofree = EINA_TRUE; + *tofree = EINA_TRUE; return im_new; } @@ -2539,85 +2538,22 @@ eng_ector_destroy(void *data EINA_UNUSED, Ector_Surface *ector) } static Ector_Buffer * -eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *evas, void *engine_image, Eina_Bool is_rgba_image) +eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *evas, void *engine_image) { - Ector_Buffer *buf = NULL; + Evas_GL_Image *im = engine_image; + EINA_SAFETY_ON_NULL_RETURN_VAL(engine_image, NULL); - if (is_rgba_image) - { - RGBA_Image *im = engine_image; - buf = efl_add(EVAS_ECTOR_GL_RGBAIMAGE_BUFFER_CLASS, evas, evas_ector_buffer_engine_image_set(efl_added, evas, im)); - } - else - { - Evas_GL_Image *im = engine_image; - - buf = efl_add(EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS, evas, evas_ector_buffer_engine_image_set(efl_added, evas, im)); - } - return buf; + return efl_add(EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS, evas, + evas_ector_buffer_engine_image_set(efl_added, evas, im)); } static Ector_Buffer * -eng_ector_buffer_new(void *data, Evas *evas, void *pixels, - int width, int height, int stride, - Efl_Gfx_Colorspace cspace, Eina_Bool writeable EINA_UNUSED, - int l, int r, int t, int b, Ector_Buffer_Flag flags) +eng_ector_buffer_new(void *data EINA_UNUSED, Evas *evas, int w, int h, + Efl_Gfx_Colorspace cspace, Ector_Buffer_Flag flags) { - Evas_Public_Data *e = efl_data_scope_get(evas, EVAS_CANVAS_CLASS); - Render_Engine_GL_Generic *re = e->engine.data.output; - Evas_Engine_GL_Context *gc = NULL; - Ector_Buffer *buf = NULL; - int iw = width + l + r; - int ih = height + t + b; - int pxs = (cspace == EFL_GFX_COLORSPACE_ARGB8888) ? 4 : 1; - - if (stride && (stride != iw * pxs)) - WRN("stride support is not implemented for ector gl buffers at this point!"); - - if ((flags & ECTOR_BUFFER_FLAG_RENDERABLE) == 0) - { - // Create an RGBA Image as backing - Image_Entry *ie; - - if (pixels) - { - // no copy - ie = evas_cache_image_data(evas_common_image_cache_get(), iw, ih, - pixels, EINA_TRUE, (Evas_Colorspace) cspace); - if (!ie) return NULL; - } - else - { - // alloc buffer - ie = evas_cache_image_copied_data(evas_common_image_cache_get(), iw, ih, - NULL, EINA_TRUE, (Evas_Colorspace) cspace); - if (!ie) return NULL; - pixels = ((RGBA_Image *) ie)->image.data; - memset(pixels, 0, iw * ih * pxs); - } - ie->borders.l = l; - ie->borders.r = r; - ie->borders.t = t; - ie->borders.b = b; - - buf = eng_ector_buffer_wrap(data, evas, ie, EINA_TRUE); - evas_cache_image_drop(ie); - } - else - { - // Create only an Evas_GL_Image as backing - Evas_GL_Image *im; - - if (l || r || t || b) - WRN("Borders are not supported by Evas surfaces!"); - - gc = re->window_gl_context_get(re->software.ob); - im = evas_gl_common_image_surface_new(gc, iw, ih, EINA_TRUE, EINA_FALSE); - buf = efl_add(EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS, evas, evas_ector_buffer_engine_image_set(efl_added, evas, im)); - im->references--; - } - return buf; + return efl_add(EVAS_ECTOR_GL_BUFFER_CLASS, evas, + evas_ector_gl_buffer_prepare(efl_added, evas, w, h, cspace, flags)); } static Efl_Gfx_Render_Op @@ -2768,7 +2704,7 @@ eng_ector_begin(void *data, void *context EINA_UNUSED, Ector_Surface *ector, } } memset(buffer->software, 0, sizeof (unsigned int) * w * h); - ector_buffer_pixels_set(ector, buffer->software, w, h, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE, 0, 0, 0, 0); + ector_buffer_pixels_set(ector, buffer->software, w, h, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); ector_surface_reference_point_set(ector, x, y); } else @@ -2796,7 +2732,7 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector, w = gl_context->w; h = gl_context->h; mul_use = gl_context->dc->mul.use; - ector_buffer_pixels_set(ector, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0); + ector_buffer_pixels_set(ector, NULL, 0, 0, 0, 0); buffer->gl = eng_image_data_put(data, buffer->gl, buffer->software); if (!mul_use) diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c b/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c index 9ed93897cf..5e48883ba3 100644 --- a/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c +++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c @@ -4,17 +4,40 @@ static Eina_Bool _gl_filter_blend(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) { Evas_Engine_GL_Context *gc; - Evas_GL_Image *image; - Evas_Canvas *eo_evas; - void *im = NULL; + Evas_GL_Image *image, *surface; + RGBA_Draw_Context *dc_save; re->window_use(re->software.ob); gc = re->window_gl_context_get(re->software.ob); - evas_ector_buffer_engine_image_get(cmd->input->buffer, &eo_evas, &im); - image = im; + image = evas_ector_buffer_drawable_image_get(cmd->input->buffer, EINA_TRUE); - evas_gl_common_image_draw(gc, image, 0, 0, image->w, image->h, 0, 0, image->w, image->h, EINA_TRUE); + EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(image->tex, EINA_FALSE); + + surface = evas_ector_buffer_render_image_get(cmd->output->buffer, EINA_FALSE); + + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface->tex, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface->tex->pt, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(surface->tex->pt->fb != 0, EINA_FALSE); + evas_gl_common_context_target_surface_set(gc, surface); + + // TODO: mapped render iteration + + dc_save = gc->dc; + gc->dc = evas_common_draw_context_new(); + evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A); + + evas_gl_common_image_draw(gc, image, 0, 0, image->w, image->h, + cmd->draw.ox, cmd->draw.oy, image->w, image->h, + EINA_TRUE); + + evas_common_draw_context_free(gc->dc); + gc->dc = dc_save; + + evas_ector_buffer_engine_image_release(cmd->input->buffer, image); + evas_ector_buffer_engine_image_release(cmd->output->buffer, surface); return EINA_TRUE; } @@ -26,5 +49,5 @@ gl_filter_blend_func_get(Evas_Filter_Command *cmd) EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL); - return NULL; // _gl_filter_blend; + return _gl_filter_blend; } 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 061d5fbd89..d3129744cd 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 @@ -27,46 +27,44 @@ _evas_ector_software_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ect RGBA_Image *im = image; EINA_SAFETY_ON_NULL_RETURN(image); - if (efl_finalized_get(obj)) - { - CRI("engine_image must be set at construction time only"); - return; - } - - if (!im->image.data) - { - CRI("image has no pixels yet"); - return; - } + EINA_SAFETY_ON_FALSE_RETURN(!efl_finalized_get(obj)); + EINA_SAFETY_ON_NULL_RETURN(im->image.data); pd->evas = efl_data_xref(evas, EVAS_CANVAS_CLASS, obj); evas_cache_image_ref(&im->cache_entry); pd->image = im; - ector_buffer_pixels_set(obj, im->image.data, im->cache_entry.w, im->cache_entry.h, 0, (Efl_Gfx_Colorspace) im->cache_entry.space, EINA_TRUE, 0, 0, 0, 0); + ector_buffer_pixels_set(obj, im->image.data, im->cache_entry.w, im->cache_entry.h, im->cache_entry.space, EINA_TRUE); } -EOLIAN static void -_evas_ector_software_buffer_evas_ector_buffer_engine_image_get(Eo *obj EINA_UNUSED, - Evas_Ector_Software_Buffer_Data *pd, - Evas **evas, void **image) +EOLIAN static void * +_evas_ector_software_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED, + Evas_Ector_Software_Buffer_Data *pd, + Eina_Bool update EINA_UNUSED) { - if (!pd->evas) - { - INF("evas_ector_buffer_engine_image_set was not called on this image"); - if (evas) *evas = NULL; - if (image) *image = NULL; - return; - } - if (evas) *evas = pd->evas->evas; - if (pd->evas->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; - } + evas_cache_image_ref(&pd->image->cache_entry); + return pd->image; +} - if (image) *image = pd->image; +EOLIAN static void * +_evas_ector_software_buffer_evas_ector_buffer_render_image_get(Eo *obj EINA_UNUSED, + Evas_Ector_Software_Buffer_Data *pd, + Eina_Bool update EINA_UNUSED) +{ + evas_cache_image_ref(&pd->image->cache_entry); + return pd->image; +} + +EOLIAN static Eina_Bool +_evas_ector_software_buffer_evas_ector_buffer_engine_image_release(Eo *obj EINA_UNUSED, + Evas_Ector_Software_Buffer_Data *pd, + void *image) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(pd->image == image, EINA_FALSE); + + evas_cache_image_drop(&pd->image->cache_entry); + return EINA_TRUE; } EOLIAN static Eo * diff --git a/src/modules/evas/engines/software_generic/evas_ector_software_buffer.eo b/src/modules/evas/engines/software_generic/evas_ector_software_buffer.eo index f2c98bb17a..938cd3a4e8 100644 --- a/src/modules/evas/engines/software_generic/evas_ector_software_buffer.eo +++ b/src/modules/evas/engines/software_generic/evas_ector_software_buffer.eo @@ -5,6 +5,9 @@ class Evas.Ector.Software.Buffer (Ector.Software.Buffer, Evas.Ector.Buffer) Efl.Object.constructor; Efl.Object.finalize; Efl.Object.destructor; - Evas.Ector.Buffer.engine_image { get; set; } + Evas.Ector.Buffer.engine_image_set; + Evas.Ector.Buffer.drawable_image_get; + Evas.Ector.Buffer.render_image_get; + Evas.Ector.Buffer.engine_image_release; } } diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 4ccec9bc8f..3947af63ad 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -4333,7 +4333,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, Eina_Bool is_rgba_image EINA_UNUSED) +eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image) { Image_Entry *ie = engine_image; Ector_Buffer *buf = NULL; @@ -4342,61 +4342,42 @@ eng_ector_buffer_wrap(void *data EINA_UNUSED, Evas *e, void *engine_image, Eina_ if (!efl_domain_current_push(EFL_ID_DOMAIN_SHARED)) return NULL; - buf = efl_add(EVAS_ECTOR_SOFTWARE_BUFFER_CLASS, NULL, evas_ector_buffer_engine_image_set(efl_added, e, ie)); + buf = efl_add(EVAS_ECTOR_SOFTWARE_BUFFER_CLASS, NULL, + evas_ector_buffer_engine_image_set(efl_added, e, ie)); efl_domain_current_pop(); return buf; } static Ector_Buffer * -eng_ector_buffer_new(void *data EINA_UNUSED, Evas *evas, 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 EINA_UNUSED) +eng_ector_buffer_new(void *data EINA_UNUSED, Evas *evas, int width, int height, + Efl_Gfx_Colorspace cspace, Ector_Buffer_Flag flags EINA_UNUSED) { - Ector_Buffer *buf = NULL; - int pxs = (cspace == EFL_GFX_COLORSPACE_ARGB8888) ? 4 : 1; - int iw = width + l + r; - int ih = height + t + b; + Ector_Buffer *buf; + Image_Entry *ie; + void *pixels; + int pxs; - if ((flags & (ECTOR_BUFFER_FLAG_RENDERABLE | ECTOR_BUFFER_FLAG_DRAWABLE)) == 0) - { - if (!efl_domain_current_push(EFL_ID_DOMAIN_SHARED)) - return NULL; - buf = efl_add(ECTOR_SOFTWARE_BUFFER_CLASS, NULL, ector_buffer_pixels_set(efl_added, pixels, width, height, stride, cspace, writeable, l, r, t, b)); - efl_domain_current_pop(); - } + if (cspace == EFL_GFX_COLORSPACE_ARGB8888) + pxs = 4; + else if (cspace == EFL_GFX_COLORSPACE_GRY8) + pxs = 1; else { - // Create an RGBA Image as backing - Image_Entry *ie; - - if (pixels) - { - // no copy - ie = evas_cache_image_data(evas_common_image_cache_get(), iw, ih, - pixels, EINA_TRUE, (Evas_Colorspace) cspace); - if (!ie) return NULL; - } - else - { - // alloc buffer - ie = evas_cache_image_copied_data(evas_common_image_cache_get(), iw, ih, - NULL, EINA_TRUE, (Evas_Colorspace) cspace); - if (!ie) return NULL; - pixels = ((RGBA_Image *) ie)->image.data; - memset(pixels, 0, iw * ih * pxs); - } - ie->borders.l = l; - ie->borders.r = r; - ie->borders.t = t; - ie->borders.b = b; - - buf = eng_ector_buffer_wrap(data, evas, ie, EINA_TRUE); - evas_cache_image_drop(ie); + ERR("Unsupported colorspace: %d", (int) cspace); + return NULL; } + // alloc buffer + ie = evas_cache_image_copied_data(evas_common_image_cache_get(), width, height, + NULL, EINA_TRUE, cspace); + if (!ie) return NULL; + pixels = ((RGBA_Image *) ie)->image.data; + memset(pixels, 0, width * height * pxs); + + buf = eng_ector_buffer_wrap(data, evas, ie); + evas_cache_image_drop(ie); + return buf; } @@ -4546,7 +4527,7 @@ _draw_thread_ector_surface_set(void *data) y = ector_surface->y; } - ector_buffer_pixels_set(ector_surface->ector, pixels, w, h, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE, 0, 0, 0, 0); + ector_buffer_pixels_set(ector_surface->ector, pixels, w, h, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); ector_surface_reference_point_set(ector_surface->ector, x, y); eina_mempool_free(_mp_command_ector_surface, ector_surface); @@ -4591,7 +4572,7 @@ eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface w = sf->cache_entry.w; h = sf->cache_entry.h; - ector_buffer_pixels_set(ector, pixels, w, h, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE, 0, 0, 0, 0); + ector_buffer_pixels_set(ector, pixels, w, h, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); ector_surface_reference_point_set(ector, x, y); } } @@ -4613,7 +4594,7 @@ eng_ector_end(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface * } else { - ector_buffer_pixels_set(ector, NULL, 0, 0, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE, 0, 0, 0, 0); + ector_buffer_pixels_set(ector, NULL, 0, 0, EFL_GFX_COLORSPACE_ARGB8888, EINA_TRUE); evas_common_cpu_end_opt(); } } diff --git a/src/modules/evas/engines/software_generic/filters/evas_filter_displace.c b/src/modules/evas/engines/software_generic/filters/evas_filter_displace.c index aeea412c79..cc459a0592 100644 --- a/src/modules/evas/engines/software_generic/filters/evas_filter_displace.c +++ b/src/modules/evas/engines/software_generic/filters/evas_filter_displace.c @@ -269,7 +269,7 @@ _filter_displace_cpu_rgba(Evas_Filter_Command *cmd) EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE); src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ARGB, &src_stride); - dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_READ, E_ARGB, &dst_stride); + dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_READ | E_WRITE, E_ARGB, &dst_stride); stretch = cmd->displacement.flags & EVAS_FILTER_DISPLACE_STRETCH; smooth = cmd->displacement.flags & EVAS_FILTER_DISPLACE_LINEAR; map_w = cmd->mask->w; @@ -294,7 +294,7 @@ _filter_displace_cpu_rgba(Evas_Filter_Command *cmd) } else map_fb = cmd->mask; - map_start = (uint32_t *) _buffer_map_all(map_fb->buffer, &map_len, E_READ, E_ARGB, &map_stride); + map_start = _buffer_map_all(map_fb->buffer, &map_len, E_READ, E_ARGB, &map_stride); EINA_SAFETY_ON_FALSE_GOTO(src && dst && map_start, end); _filter_displace_cpu_rgba_do(w, h, map_w, map_h, intensity, diff --git a/src/modules/evas/engines/software_generic/filters/evas_filter_fill.c b/src/modules/evas/engines/software_generic/filters/evas_filter_fill.c index 87a0075c35..6460b861e1 100644 --- a/src/modules/evas/engines/software_generic/filters/evas_filter_fill.c +++ b/src/modules/evas/engines/software_generic/filters/evas_filter_fill.c @@ -10,7 +10,7 @@ _fill_cpu(Evas_Filter_Command *cmd) uint32_t color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B); unsigned int stride, len; int w, h, k; - uint8_t *ptr; + uint8_t *map, *ptr; if (!cmd->draw.clip_mode_lrtb) { @@ -31,10 +31,10 @@ _fill_cpu(Evas_Filter_Command *cmd) h = CLAMP(0, fb->h - y - cmd->draw.clip.b, fb->h - y); } - ptr = _buffer_map_all(fb->buffer, &len, E_WRITE, fb->alpha_only ? E_ALPHA : E_ARGB, &stride); - if (!ptr) return EINA_FALSE; + map = _buffer_map_all(fb->buffer, &len, E_WRITE, fb->alpha_only ? E_ALPHA : E_ARGB, &stride); + if (!map) return EINA_FALSE; - ptr += y * stride; + ptr = map + y * stride; if (fb->alpha_only) { for (k = 0; k < h; k++) @@ -52,7 +52,7 @@ _fill_cpu(Evas_Filter_Command *cmd) } } - ector_buffer_unmap(fb->buffer, ptr, len); + ector_buffer_unmap(fb->buffer, map, len); return EINA_TRUE; } diff --git a/src/modules/evas/engines/software_generic/filters/evas_filter_mask.c b/src/modules/evas/engines/software_generic/filters/evas_filter_mask.c index 9243811a52..a138b43af1 100644 --- a/src/modules/evas/engines/software_generic/filters/evas_filter_mask.c +++ b/src/modules/evas/engines/software_generic/filters/evas_filter_mask.c @@ -16,9 +16,9 @@ eng_filter_mask_func_get(Evas_Filter_Command *cmd) EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->buffer, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->buffer, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->buffer, NULL); + //EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->buffer, NULL); + //EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->buffer, NULL); + //EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask->buffer, NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->input->w > 0) && (cmd->input->h > 0), NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->mask->w > 0) && (cmd->mask->h > 0), NULL); EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->w == cmd->output->w, NULL);