This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch span-gl-clean
in repository efl.
View the commit online.
commit c7cb51335dae9668f256099f1a265443bac0712d
Author: [email protected] <[email protected]>
AuthorDate: Mon Apr 6 09:59:18 2026 -0600
feat(ector_gl): composite mask support and VG canvas integration
Add composite/mask rendering support to the GL span-buffer pipeline
and integrate with the Evas VG canvas layer.
Composite mask rendering:
- Mask container shapes render through the span-buffer pipeline into
a dedicated non-atlas FBO (prevents GL texture feedback loop)
- ector_mask_surface_create engine function forces standalone GL texture
via evas_gl_common_image_surface_noscale_noatlas_new
- Mask FBO texture sampled by source shapes' fragment shader on unit 4
- All 6 Efl_Gfx_Vg_Composite_Method values GPU-accelerated:
MATTE_ALPHA, MATTE_ALPHA_INVERSE (branchless mix),
MASK_INTERSECT, MASK_SUBSTRACT (same math, different init),
MASK_ADD (additive alpha), MASK_DIFFERENCE (abs difference)
VG container integration (_prepare_comp):
- GL path creates/reuses mask FBO, renders mask shapes via nested
eng_ector_begin/end during render_pre (before main VG begin)
- gl_comp_surface propagated via ector_software_surface_gl_comp_set
accessor (bridges canvas code and ector private header)
- Per-frame propagation in _evas_vg_render (draw phase, always runs)
rather than render_pre (only runs on changes)
VG object rendering fixes:
- Composite target containers (comp.src) skipped in _evas_vg_render
to prevent unmasked duplicate draws
- Gradient fill objects skipped in composite containers (they are
shape properties, not standalone renderable nodes)
Software engine compatibility:
- NULL slot for ector_mask_surface_create in software_generic
- GL path guarded by ENFN->gl_surface_read_pixels (NULL on SW engine)
- ECTOR_BACKEND=software fallback preserved
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
src/lib/ector/software/ector_software_surface.c | 34 +++++
src/lib/evas/canvas/efl_canvas_vg_container.c | 161 ++++++++++++++++++++-
src/lib/evas/canvas/efl_canvas_vg_object.c | 45 +++++-
src/lib/evas/canvas/evas_vg_private.h | 9 ++
src/lib/evas/include/evas_private.h | 1 +
src/modules/evas/engines/gl_common/evas_gl_image.c | 23 ++-
.../evas/engines/gl_common/evas_gl_texture.c | 30 ++++
src/modules/evas/engines/gl_generic/meson.build | 10 +-
.../evas/engines/software_generic/evas_engine.c | 1 +
9 files changed, 308 insertions(+), 6 deletions(-)
diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c
index ba64445ba3..152758f745 100644
--- a/src/lib/ector/software/ector_software_surface.c
+++ b/src/lib/ector/software/ector_software_surface.c
@@ -284,5 +284,39 @@ _ector_software_surface_ector_surface_draw_image(Eo *obj EINA_UNUSED,
}
return EINA_TRUE;
}
+
+/* GL composite mask accessors.
+ *
+ * Called by efl_canvas_vg_container.c during render_pre to store the mask FBO
+ * surface and composite method so that eng_ector_end() (in the GL engine) can
+ * look them up via _gl_comp_get and populate Span_Pipe_Params.mask_tex.
+ *
+ * These are the only way for canvas code (which cannot include
+ * ector_software_private.h) to reach Ector_Software_Surface_Data fields. */
+ECTOR_API void
+ector_software_surface_gl_comp_set(Ector_Surface *obj,
+ void *gl_surface, int comp_method)
+{
+ Ector_Software_Surface_Data *pd = efl_data_scope_get(obj, ECTOR_SOFTWARE_SURFACE_CLASS);
+ if (!pd) return;
+ pd->gl_comp_surface = gl_surface;
+ pd->gl_comp_method = comp_method;
+}
+
+ECTOR_API void
+ector_software_surface_gl_comp_get(Ector_Surface *obj,
+ void **gl_surface_out, int *comp_method_out)
+{
+ Ector_Software_Surface_Data *pd = efl_data_scope_get(obj, ECTOR_SOFTWARE_SURFACE_CLASS);
+ if (!pd)
+ {
+ if (gl_surface_out) *gl_surface_out = NULL;
+ if (comp_method_out) *comp_method_out = 0;
+ return;
+ }
+ if (gl_surface_out) *gl_surface_out = pd->gl_comp_surface;
+ if (comp_method_out) *comp_method_out = pd->gl_comp_method;
+}
+
#include "ector_software_surface.eo.c"
#include "ector_renderer_software.eo.c"
diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.c b/src/lib/evas/canvas/efl_canvas_vg_container.c
index 76a67f4eee..d1450ac901 100644
--- a/src/lib/evas/canvas/efl_canvas_vg_container.c
+++ b/src/lib/evas/canvas/efl_canvas_vg_container.c
@@ -75,6 +75,99 @@ _prepare_comp(Evas_Object_Protected_Data *obj, //vector object
pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MASK_INTERSECT)
init_buffer = 0xFFFFFFFF;
+ /* GL span-buffer path: render the mask shapes into a dedicated FBO surface
+ * through the same span-buffer pipeline. This runs during render_pre,
+ * which is BEFORE the main VG object's eng_ector_begin(), so the shared
+ * ector surface is free and the nested begin/end does not conflict with
+ * any outer begin/end for the main VG render.
+ *
+ * The mask FBO surface is kept alive on pd->comp.gl_surface across frames
+ * and reused when the size matches. eng_ector_end() of the main VG object
+ * reads espd->gl_comp_surface (set by render_pre after we return) to fill
+ * the mask texture params on each shape's Span_Pipe_Params. */
+ if (ENFN->gl_surface_read_pixels) /* GL engine only — SW engine sets this to NULL */
+ {
+ int err = 0;
+ void *mask_surface = pd->comp.gl_surface;
+
+ /* Create or resize mask FBO. */
+ if (mask_surface)
+ {
+ int mw = 0, mh = 0;
+ ENFN->image_size_get(ENC, mask_surface, &mw, &mh);
+ if (mw != size.w || mh != size.h)
+ {
+ ENFN->ector_surface_destroy(ENC, mask_surface);
+ mask_surface = NULL;
+ }
+ }
+ if (!mask_surface)
+ {
+ /* Use ector_mask_surface_create when available so the mask FBO
+ * gets a dedicated GL texture that cannot be atlas-shared with the
+ * main VG FBO, preventing a read/write feedback loop in the shader. */
+ if (ENFN->ector_mask_surface_create)
+ mask_surface = ENFN->ector_mask_surface_create(ENC, size.w, size.h, &err);
+ else
+ mask_surface = ENFN->ector_surface_create(ENC, size.w, size.h, &err);
+ if (err || !mask_surface) goto gl_mask_fallback;
+ }
+ pd->comp.gl_surface = mask_surface;
+ pd->comp.size.w = size.w;
+ pd->comp.size.h = size.h;
+ pd->comp.vg_pd = obj;
+
+ /* Prepare mask shapes via render_pre.
+ * The nested composite chain (MASK_ADD) is handled first, exactly as
+ * in the CPU path below, but using NULL as the comp buffer since the
+ * GL path does not create a CPU comp buffer here. */
+ if (pd->comp.method >= EFL_GFX_VG_COMPOSITE_METHOD_MASK_ADD)
+ {
+ Efl_Canvas_Vg_Container_Data *target_pd = pd;
+ for (Efl_VG *ct = pd->comp_target; ct; ct = target_pd->comp_target)
+ {
+ Efl_Canvas_Vg_Container_Data *src_pd = NULL;
+ target_pd = efl_data_scope_get(ct, MY_CLASS);
+ src_pd = efl_data_scope_get(eina_list_nth(target_pd->comp.src, 0), MY_CLASS);
+ _evas_vg_render_pre(obj, ct,
+ engine, output, context, surface,
+ ctransform, c_opacity, NULL, src_pd->comp.method);
+ }
+ }
+
+ _evas_vg_render_pre(obj, comp_target,
+ engine, output, context, surface,
+ ptransform, p_opacity, NULL, comp_method);
+
+ /* Render mask shapes into the FBO via span-buffer pipeline.
+ * eng_ector_begin installs span collectors on the shared ector surface;
+ * _draw_comp drives ector_renderer_draw to populate them;
+ * eng_ector_end uploads and draws them to mask_surface's FBO. */
+ {
+ RGBA_Draw_Context *dc = evas_common_draw_context_new();
+ evas_common_draw_context_set_render_op(dc, _EVAS_RENDER_COPY);
+ evas_common_draw_context_set_color(dc, 255, 255, 255, 255);
+
+ if (ENFN->ector_begin(ENC, mask_surface, dc, surface, 0, 0, EINA_FALSE))
+ {
+ _draw_comp(obj, comp_target, surface, engine, output, context);
+ ENFN->image_dirty_region(ENC, mask_surface, 0, 0, size.w, size.h);
+ ENFN->ector_end(ENC, mask_surface, dc, surface, EINA_FALSE);
+ }
+
+ evas_common_draw_context_free(dc);
+ }
+
+ /* Signal to the caller that there is no CPU comp buffer.
+ * The mask FBO reference lives on pd->comp.gl_surface; render_pre
+ * propagates it to the ector surface data for eng_ector_end to pick up. */
+ return NULL;
+ }
+
+gl_mask_fallback:
+ /* Fallback: original CPU pixel buffer path (software backend or GL surface
+ * creation failure). */
+
//2. Reusable ector buffer?
if (pd->comp.buffer &&
((pd->comp.size.w != size.w) ||
@@ -171,6 +264,23 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd,
Efl_VG *child;
Efl_Gfx_Change_Flag flag;
+ /* Even when the container's flags are NONE (nothing changed), we must
+ * still propagate the GL composite mask reference to the ector surface
+ * every frame — eng_ector_end clears it after use. */
+ if (pd->comp_target &&
+ (pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA ||
+ pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA_INVERSE ||
+ pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MASK_INTERSECT ||
+ pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MASK_SUBSTRACT))
+ {
+ Efl_Canvas_Vg_Container_Data *cpd =
+ efl_data_scope_get(pd->comp_target, MY_CLASS);
+ if (cpd && cpd->comp.gl_surface)
+ ector_software_surface_gl_comp_set(surface,
+ cpd->comp.gl_surface,
+ (int)pd->comp.method);
+ }
+
if (nd->flags == EFL_GFX_CHANGE_FLAG_NONE) return;
flag = nd->flags;
@@ -184,12 +294,27 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd,
// This condition is valid because the masking use same type as matte.
if (pd->comp_target &&
(pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA ||
- pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA_INVERSE))
+ pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA_INVERSE ||
+ pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MASK_INTERSECT ||
+ pd->comp.method == EFL_GFX_VG_COMPOSITE_METHOD_MASK_SUBSTRACT))
{
comp_method = pd->comp.method;
comp = _prepare_comp(vg_pd, pd->comp_target,
engine, output, context, surface,
ptransform, ctransform, p_opacity, c_a, comp, comp_method);
+
+ /* GL span-buffer path: _prepare_comp returns NULL but stores the
+ * mask FBO on pd->comp.gl_surface. Propagate it to the shared ector
+ * surface so eng_ector_end() can find it when building pipe params. */
+ if (!comp && pd->comp_target)
+ {
+ Efl_Canvas_Vg_Container_Data *cpd =
+ efl_data_scope_get(pd->comp_target, MY_CLASS);
+ if (cpd && cpd->comp.gl_surface)
+ ector_software_surface_gl_comp_set(surface,
+ cpd->comp.gl_surface,
+ (int)pd->comp.method);
+ }
}
//If the container has transparency, it internally alpha blends with ector buffer.
@@ -225,7 +350,20 @@ _efl_canvas_vg_container_render_pre(Evas_Object_Protected_Data *vg_pd,
// However, if there is a composition target, the child must refer to the parent's opacity.
// Because _evas_vg_render does not support opacity calculation for containers that need to be composited.
// These things need to be refactored in a better way later.
- c_a = !comp ? 255 : c_a;
+ /* If there is a composite (CPU buffer or GL FBO mask), children must
+ * inherit the container's opacity. In the GL span-buffer path,
+ * comp is NULL even when a mask FBO was prepared, so also check for
+ * gl_surface on the comp_target's pd. */
+ {
+ Eina_Bool has_comp = comp != NULL;
+ if (!has_comp && pd->comp_target)
+ {
+ Efl_Canvas_Vg_Container_Data *cpd =
+ efl_data_scope_get(pd->comp_target, MY_CLASS);
+ if (cpd && cpd->comp.gl_surface) has_comp = EINA_TRUE;
+ }
+ c_a = !has_comp ? 255 : c_a;
+ }
_evas_vg_render_pre(vg_pd, child,
engine, output, context, surface,
@@ -267,6 +405,25 @@ _efl_canvas_vg_container_efl_object_destructor(Eo *obj,
efl_unref(pd->comp.buffer);
}
+ /* Destroy GL FBO mask surface (GL span-buffer path).
+ * pd->comp.gl_surface is an Evas_GL_Image* allocated via
+ * ENFN->ector_surface_create. We need the engine handle to free it.
+ * Retrieve the engine and output from the VG object's Evas layer if
+ * available. If the engine context has already been torn down, skip
+ * the free to avoid use-after-free (minor leak on shutdown). */
+ if (pd->comp.gl_surface && pd->comp.vg_pd)
+ {
+ Evas_Object_Protected_Data *vg_pd = pd->comp.vg_pd;
+ if (vg_pd->layer && vg_pd->layer->evas)
+ {
+ Evas_Public_Data *evas = vg_pd->layer->evas;
+ if (evas->engine.func && evas->engine.func->ector_surface_destroy)
+ evas->engine.func->ector_surface_destroy(
+ _evas_engine_context(evas), pd->comp.gl_surface);
+ }
+ pd->comp.gl_surface = NULL;
+ }
+
efl_unref(pd->comp_target);
eina_list_free(pd->comp.src);
eina_hash_free(pd->names);
diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c
index fe25ead344..f4001fdcc8 100644
--- a/src/lib/evas/canvas/efl_canvas_vg_object.c
+++ b/src/lib/evas/canvas/efl_canvas_vg_object.c
@@ -430,6 +430,20 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
if (cd->comp.src) return; //Don't draw composite target itself.
+ /* GL composite mask: propagate the mask FBO to the shared ector
+ * surface every frame. render_pre only runs on changes, but the
+ * draw phase runs every frame. eng_ector_end clears gl_comp_surface
+ * after use, so it must be re-set here. */
+ if (cd->comp_target)
+ {
+ Efl_Canvas_Vg_Container_Data *cpd =
+ efl_data_scope_get(cd->comp_target, EFL_CANVAS_VG_CONTAINER_CLASS);
+ if (cpd && cpd->comp.gl_surface)
+ ector_software_surface_gl_comp_set(ector,
+ cpd->comp.gl_surface,
+ (int)cd->comp.method);
+ }
+
int alpha = 255;
efl_gfx_color_get(node, NULL, NULL, NULL, &alpha);
@@ -484,7 +498,17 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
// Draw child node to changed buffer
EINA_LIST_FOREACH(cd->children, l, child)
- _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async);
+ {
+ if (efl_isa(child, EFL_CANVAS_VG_CONTAINER_CLASS))
+ {
+ Efl_Canvas_Vg_Container_Data *child_cd =
+ efl_data_scope_get(child, EFL_CANVAS_VG_CONTAINER_CLASS);
+ if (child_cd && child_cd->comp.src) continue;
+ }
+ if (cd->comp_target && efl_isa(child, EFL_CANVAS_VG_GRADIENT_CLASS))
+ continue;
+ _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async);
+ }
// Recover original surface
ector_buffer_pixels_set(ector, ppixels, pw, ph, pstride, pcspace, EINA_TRUE);
@@ -499,7 +523,24 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
efl_canvas_vg_container_blend_buffer_clear(node, cd);
EINA_LIST_FOREACH(cd->children, l, child)
- _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async);
+ {
+ /* Skip composite target containers — their shapes were
+ * already rendered to the mask FBO during render_pre.
+ * Drawing them again would overwrite the masked result. */
+ if (efl_isa(child, EFL_CANVAS_VG_CONTAINER_CLASS))
+ {
+ Efl_Canvas_Vg_Container_Data *child_cd =
+ efl_data_scope_get(child, EFL_CANVAS_VG_CONTAINER_CLASS);
+ if (child_cd && child_cd->comp.src) continue;
+ }
+ /* Skip gradient objects in composite containers — they are
+ * fill properties of shapes, not standalone renderable
+ * nodes. Only skip when comp_target is set to avoid
+ * affecting non-composite containers. */
+ if (cd->comp_target && efl_isa(child, EFL_CANVAS_VG_GRADIENT_CLASS))
+ continue;
+ _evas_vg_render(obj, pd, engine, output, context, child, clips, w, h, ector, do_async);
+ }
}
}
else
diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h
index beb5854253..e68f82b155 100644
--- a/src/lib/evas/canvas/evas_vg_private.h
+++ b/src/lib/evas/canvas/evas_vg_private.h
@@ -89,6 +89,7 @@ typedef struct _Vg_Composite
void *pixels; //Composite pixel buffer (actual data)
unsigned int length; //pixel buffer data size
unsigned int stride; //pixel buffer stride
+ void *gl_surface; /* GL FBO surface for mask (Evas_GL_Image* in GL path, NULL for SW) */
Eina_Size2D size; //Composite boundary
Eina_List *src; //Composite Sources
Efl_Gfx_Vg_Composite_Method method; //Composite Method
@@ -147,6 +148,14 @@ Eina_Bool evas_cache_vg_anim_sector_get(const Vg_Cache_Entry*
unsigned int evas_cache_vg_anim_frame_count_get(const Vg_Cache_Entry *vg_entry);
Eina_Size2D evas_cache_vg_entry_default_size_get(const Vg_Cache_Entry *vg_entry);
void * evas_cache_vg_surface_key_get(Efl_Canvas_Vg_Node *root, int w, int h, int frame_idx);
+/* Forward declarations for ector software surface GL composite accessors.
+ * The implementations live in src/lib/ector/software/ector_software_surface.c.
+ * These allow canvas code (which cannot include ector_software_private.h) to
+ * store and retrieve the GL FBO mask surface reference on the shared ector
+ * surface during render_pre, so that eng_ector_end() can find it. */
+ECTOR_API void ector_software_surface_gl_comp_set(Ector_Surface *obj, void *gl_surface, int comp_method);
+ECTOR_API void ector_software_surface_gl_comp_get(Ector_Surface *obj, void **gl_surface_out, int *comp_method_out);
+
void efl_canvas_vg_node_vg_obj_set(Efl_VG *node, Efl_VG *vg_obj, Efl_Canvas_Vg_Object_Data *vd);
void efl_canvas_vg_node_change(Efl_VG *node);
void efl_canvas_vg_container_vg_obj_update(Efl_VG *obj, Efl_Canvas_Vg_Node_Data *nd);
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index 5a4b447ee9..dd643a0c89 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1073,6 +1073,7 @@ struct _Evas_Func
void (*ector_end) (void *engine, void *output, void *context, Ector_Surface *ector, Eina_Bool do_async);
void *(*ector_surface_create) (void *engine, int w, int h, int *error);
+ void *(*ector_mask_surface_create) (void *engine, int w, int h, int *error);
void (*ector_surface_destroy) (void *engine, void *surface);
void (*ector_surface_cache_set) (void *engine, void *key, void *surface);
void *(*ector_surface_cache_get) (void *engine, void *key);
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 f52691f6c5..da9a67ff24 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_image.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_image.c
@@ -775,6 +775,28 @@ evas_gl_common_image_surface_noscale_new(Evas_Engine_GL_Context *gc, unsigned in
return im;
}
+EMODAPI Evas_GL_Image *
+evas_gl_common_image_surface_noscale_noatlas_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha)
+{
+ Evas_GL_Image *im;
+
+ if (((int)w > gc->shared->info.max_texture_size) ||
+ ((int)h > gc->shared->info.max_texture_size))
+ return NULL;
+
+ im = calloc(1, sizeof(Evas_GL_Image));
+ if (!im) return NULL;
+ im->references = 1;
+ im->gc = gc;
+ im->cs.space = EVAS_COLORSPACE_ARGB8888;
+ im->alpha = alpha;
+ im->w = w;
+ im->h = h;
+ im->tex = evas_gl_common_texture_render_noscale_noatlas_new(gc, w, h, alpha);
+ im->tex_only = 1;
+ return im;
+}
+
void
evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
@@ -1331,7 +1353,6 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
evas_gl_common_rect_draw(gc, dx, dy, dw, dh);
return;
}
-
mask = gc->dc->clip.mask;
switch (im->cs.space)
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 317905e9a7..76ea5f8b2e 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_texture.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c
@@ -1151,6 +1151,36 @@ evas_gl_common_texture_render_noscale_new(Evas_Engine_GL_Context *gc, unsigned i
return tex;
}
+Evas_GL_Texture *
+evas_gl_common_texture_render_noscale_noatlas_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha)
+{
+ Evas_GL_Texture *tex;
+ int u = 0, v = 0;
+ int lformat;
+
+ lformat = _evas_gl_texture_search_format(alpha, gc->shared->info.bgra, EVAS_COLORSPACE_ARGB8888);
+ if (lformat < 0) return NULL;
+
+ tex = evas_gl_common_texture_alloc(gc, w, h, alpha);
+ if (!tex) return NULL;
+ tex->pt = _pool_tex_render_find(gc, w, h,
+ *matching_format[lformat].intformat,
+ *matching_format[lformat].format,
+ &u, &v, &tex->apt,
+ gc->shared->info.tune.atlas.max_alloc_size * 8,
+ EINA_TRUE);
+ if (!tex->pt)
+ {
+ evas_gl_common_texture_light_free(tex);
+ return NULL;
+ }
+ tex->x = u;
+ tex->y = v;
+
+ tex->pt->references++;
+ return tex;
+}
+
Evas_GL_Texture *
evas_gl_common_texture_dynamic_new(Evas_Engine_GL_Context *gc, Evas_GL_Image *im)
{
diff --git a/src/modules/evas/engines/gl_generic/meson.build b/src/modules/evas/engines/gl_generic/meson.build
index 0464ea43a8..40ae5d46b0 100644
--- a/src/modules/evas/engines/gl_generic/meson.build
+++ b/src/modules/evas/engines/gl_generic/meson.build
@@ -5,6 +5,8 @@ engine_src = files([
'evas_ector_gl.h',
'evas_ector_gl_buffer.c',
'evas_ector_gl_image_buffer.c',
+ 'evas_ector_gl_span.c',
+ 'evas_ector_gl_span_shader.c',
join_paths('filters','gl_engine_filter.h'),
join_paths('filters','gl_filter_blend.c'),
join_paths('filters','gl_filter_blur.c'),
@@ -65,7 +67,13 @@ endforeach
engine_deps += [gl_deps]
-engine_include_dir = include_directories(join_paths('..','software_generic'), join_paths('..', 'gl_common'))
+engine_include_dir = include_directories(
+ join_paths('..','software_generic'),
+ join_paths('..', 'gl_common'),
+ join_paths('..', '..', '..', '..', 'static_libs', 'freetype'),
+ join_paths('..', '..', '..', '..', 'static_libs', 'draw'),
+ join_paths('..', '..', '..', '..', 'lib', 'ector', 'software'),
+)
shared_module(mod_full_name, engine_src,
include_directories : config_dir + [engine_include_dir],
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c
index 83630e5818..77455962a2 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -4839,6 +4839,7 @@ static Evas_Func func =
eng_ector_renderer_draw,
eng_ector_end,
eng_ector_surface_create,
+ NULL, // ector_mask_surface_create — software engine has no atlas; regular path suffices
eng_ector_surface_destroy,
eng_ector_surface_cache_set,
eng_ector_surface_cache_get,
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.