}
}
+static inline void
+_image_mask_image_set(Evas_Object_Protected_Data *obj, Eina_Bool smooth, void *image)
+{
+ if ((obj->mask->image != image) || (obj->mask->smooth_scale != smooth))
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, Evas_Object_Mask_Data, mask)
+ mask->image = image;
+ mask->smooth_scale = smooth;
+ EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mask);
+ }
+}
+
static void
evas_object_image_render_pre(Evas_Object *eo_obj,
Evas_Object_Protected_Data *obj,
if ((o->cur->fill.w < 1) || (o->cur->fill.h < 1)) return;
+ /* plain mask images */
+ if (obj->mask->is_mask && !o->cur->scene && !o->cur->source)
+ {
+ DBG("Setting image pointer in mask data.");
+ _image_mask_image_set(obj, o->cur->smooth_scale, o->engine_data);
+ }
+ else
+ _image_mask_image_set(obj, EINA_FALSE, NULL);
+
/* if someone is clipping this obj - go calculate the clipper */
if (obj->cur->clipper)
{
{
/* is image clipper */
if (_evas_render_object_changed_get(obj))
- _evas_mask_redraw_set(e, obj);
+ {
+ obj->func->render_pre(obj->object, obj, obj->private_data);
+ _evas_mask_redraw_set(e, obj);
+ }
}
}
for (i = 0; i < render_objects->count; i++)
int level)
{
int x, y, w, h, r, g, b, a;
+ Eina_Bool is_image, done = EINA_FALSE;
void *ctx;
if (!mask) return;
RD(level, "evas_render_mask_subrender(%p, prev: %p)\n", mask, prev_mask);
+ is_image = eo_isa(mask->object, EVAS_IMAGE_CLASS);
+
x = mask->cur->geometry.x;
y = mask->cur->geometry.y;
w = mask->cur->geometry.w;
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, mask->mask, Evas_Object_Mask_Data, mdata)
mdata->redraw = EINA_FALSE;
- /* delete render surface if changed or if already alpha
- * (we don't know how to render objects to alpha) */
- if (mdata->surface && ((w != mdata->w) || (h != mdata->h) || mdata->is_alpha))
- {
- ENFN->image_map_surface_free(ENDT, mdata->surface);
- mdata->surface = NULL;
- }
-
- /* create new RGBA render surface if needed */
- if (!mdata->surface)
+ if (is_image && !prev_mask && mdata->image && ENFN->image_scaled_update)
{
- mdata->surface = ENFN->image_map_surface_new(ENDT, w, h, EINA_TRUE);
- if (!mdata->surface) goto end;
- mdata->is_alpha = EINA_FALSE;
- mdata->w = w;
- mdata->h = h;
+ /* Fast path (for GL) that avoids creating a map surface, render the
+ * scaled image in it, when the shaders can just scale on the fly. */
+ void *scaled = ENFN->image_scaled_update
+ (ENDT, mdata->surface, mdata->image, w, h,
+ mdata->smooth_scale, EINA_TRUE, EVAS_COLORSPACE_GRY8);
+ if (scaled)
+ {
+ done = EINA_TRUE;
+ if (mdata->surface && (mdata->surface != scaled))
+ ENFN->image_map_surface_free(ENDT, mdata->surface);
+ mdata->surface = scaled;
+ mdata->w = w;
+ mdata->h = h;
+ mdata->is_alpha = (ENFN->image_colorspace_get(ENDT, scaled) == EVAS_COLORSPACE_GRY8);
+ }
}
- /* Clear surface with transparency */
- ctx = ENFN->context_new(ENDT);
- ENFN->context_color_set(ENDT, ctx, 0, 0, 0, 0);
- ENFN->context_render_op_set(ENDT, ctx, EVAS_RENDER_COPY);
- ENFN->rectangle_draw(ENDT, ctx, mdata->surface, 0, 0, w, h, EINA_FALSE);
- ENFN->context_free(ENDT, ctx);
-
- /* Render mask to RGBA surface */
- ctx = ENFN->context_new(ENDT);
- if (prev_mask)
+ if (!done)
{
- ENFN->context_clip_image_set(ENDT, ctx,
- prev_mask->mask->surface,
- prev_mask->cur->geometry.x - x,
- prev_mask->cur->geometry.y - y);
- }
- evas_render_mapped(evas, mask->object, mask, ctx, mdata->surface,
- -x, -y, 1, 0, 0, evas->output.w, evas->output.h,
- NULL, level, EINA_TRUE, EINA_FALSE);
- ENFN->context_free(ENDT, ctx);
-
- /* BEGIN HACK */
-
- /* Now we want to convert this RGBA surface to Alpha.
- * NOTE: So, this is not going to work with the GL engine but only with
- * the SW engine. Here's the detection hack:
- * FIXME: If you know of a way to support rendering to GL_ALPHA in GL,
- * then we should render directly to an ALPHA surface. A priori,
- * GLES FBO does not support this.
- */
- if (!ENFN->gl_surface_read_pixels)
- {
- RGBA_Image *alpha_surface;
- DATA32 *rgba;
- DATA8* alpha;
-
- alpha_surface = ENFN->image_new_from_copied_data
- (ENDT, w, h, NULL, EINA_TRUE, EVAS_COLORSPACE_GRY8);
- if (!alpha_surface) goto end;
-
- /* Copy alpha channel */
- rgba = ((RGBA_Image *) mdata->surface)->image.data;
- alpha = alpha_surface->image.data8;
- for (y = h; y; --y)
- for (x = w; x; --x, alpha++, rgba++)
- *alpha = (DATA8) A_VAL(rgba);
-
- /* Now we can drop the original surface */
- ENFN->image_map_surface_free(ENDT, mdata->surface);
- mdata->surface = alpha_surface;
- mdata->is_alpha = EINA_TRUE;
+ /* delete render surface if changed or if already alpha
+ * (we don't know how to render objects to alpha) */
+ if (mdata->surface && ((w != mdata->w) || (h != mdata->h) || mdata->is_alpha))
+ {
+ ENFN->image_map_surface_free(ENDT, mdata->surface);
+ mdata->surface = NULL;
+ }
+
+ /* create new RGBA render surface if needed */
+ if (!mdata->surface)
+ {
+ mdata->surface = ENFN->image_map_surface_new(ENDT, w, h, EINA_TRUE);
+ if (!mdata->surface) goto end;
+ mdata->is_alpha = EINA_FALSE;
+ mdata->w = w;
+ mdata->h = h;
+ }
+
+ /* Clear surface with transparency */
+ ctx = ENFN->context_new(ENDT);
+ ENFN->context_color_set(ENDT, ctx, 0, 0, 0, 0);
+ ENFN->context_render_op_set(ENDT, ctx, EVAS_RENDER_COPY);
+ ENFN->rectangle_draw(ENDT, ctx, mdata->surface, 0, 0, w, h, EINA_FALSE);
+ ENFN->context_free(ENDT, ctx);
+
+ /* Render mask to RGBA surface */
+ ctx = ENFN->context_new(ENDT);
+ if (prev_mask)
+ {
+ ENFN->context_clip_image_set(ENDT, ctx,
+ prev_mask->mask->surface,
+ prev_mask->cur->geometry.x - x,
+ prev_mask->cur->geometry.y - y);
+ }
+ evas_render_mapped(evas, mask->object, mask, ctx, mdata->surface,
+ -x, -y, 1, 0, 0, evas->output.w, evas->output.h,
+ NULL, level, EINA_TRUE, EINA_FALSE);
+ ENFN->context_free(ENDT, ctx);
+
+ /* BEGIN HACK */
+
+ /* Now we want to convert this RGBA surface to Alpha.
+ * NOTE: So, this is not going to work with the GL engine but only with
+ * the SW engine. Here's the detection hack:
+ * FIXME: If you know of a way to support rendering to GL_ALPHA in GL,
+ * then we should render directly to an ALPHA surface. A priori,
+ * GLES FBO does not support this.
+ */
+ if (!ENFN->gl_surface_read_pixels)
+ {
+ RGBA_Image *alpha_surface;
+ DATA32 *rgba;
+ DATA8* alpha;
+
+ alpha_surface = ENFN->image_new_from_copied_data
+ (ENDT, w, h, NULL, EINA_TRUE, EVAS_COLORSPACE_GRY8);
+ if (!alpha_surface) goto end;
+
+ /* Copy alpha channel */
+ rgba = ((RGBA_Image *) mdata->surface)->image.data;
+ alpha = alpha_surface->image.data8;
+ for (y = h; y; --y)
+ for (x = w; x; --x, alpha++, rgba++)
+ *alpha = (DATA8) A_VAL(rgba);
+
+ /* Now we can drop the original surface */
+ ENFN->image_map_surface_free(ENDT, mdata->surface);
+ mdata->surface = alpha_surface;
+ mdata->is_alpha = EINA_TRUE;
+ }
+ /* END OF HACK */
}
mdata->surface = ENFN->image_dirty_region(ENDT, mdata->surface, 0, 0, w, h);
- /* END OF HACK */
-
end:
EINA_COW_WRITE_END(evas_object_mask_cow, mask->mask, mdata);
struct _Evas_Object_Mask_Data
{
void *surface;
+ void *image; // original image
int w, h;
Eina_Bool is_mask : 1;
Eina_Bool redraw : 1;
Eina_Bool is_alpha : 1;
+ Eina_Bool smooth_scale : 1;
};
struct _Evas_Object_Protected_State
void *(*image_map_surface_new) (void *data, int w, int h, int alpha);
void (*image_map_surface_free) (void *data, void *surface);
void (*image_map_clean) (void *data, RGBA_Map *m);
+ void *(*image_scaled_update) (void *data, void *scaled, void *image, int dst_w, int dst_h, Eina_Bool smooth, Eina_Bool alpha, Evas_Colorspace cspace);
void (*image_content_hint_set) (void *data, void *surface, int hint);
int (*image_content_hint_get) (void *data, void *surface);
Eina_Bool use_texsam : 1;
Eina_Bool use_texm : 1;
Eina_Bool anti_alias : 1;
+ Eina_Bool mask_smooth : 1;
Evas_GL_Image *im;
GLuint buffer;
int buffer_alloc;
unsigned char loose : 1;
} native;
+ struct {
+ Evas_GL_Image *origin;
+ int w, h;
+ Eina_Bool smooth : 1;
+ } scaled;
+
int scale_hint, content_hint;
int csize;
void evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc,
int x, int y, int w, int h,
int r, int g, int b, int a,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh);
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth);
void evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only);
void evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a);
void evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth);
void evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth);
void evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth);
void evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth);
void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
#define PUSH_MASK(pn, mtex, mx, my, mw, mh) if (mtex) do { \
GLfloat tmx1, tmx2, tmy1, tmy2; \
- tmx1 = (mtex->x + mx) / (double)mtex->pt->w; \
- tmy1 = (mtex->y + my) / (double)mtex->pt->h; \
- tmx2 = (mtex->x + mx + mw) / (double)mtex->pt->w; \
- tmy2 = (mtex->y + my + mh) / (double)mtex->pt->h; \
+ tmx1 = mx; \
+ tmy1 = my; \
+ tmx2 = mx + mw; \
+ tmy2 = my + mh; \
PUSH_TEXM(pn, tmx1, tmy1); \
PUSH_TEXM(pn, tmx2, tmy1); \
PUSH_TEXM(pn, tmx1, tmy2); \
PUSH_TEXM(pn, tmx2, tmy2); \
PUSH_TEXM(pn, tmx1, tmy2); \
} while(0)
+/* was:
+ tmx1 = (mtex->x + mx) / (double)mtex->pt->w; \
+ tmy1 = (mtex->y + my) / (double)mtex->pt->h; \
+ tmx2 = (mtex->x + mx + mw) / (double)mtex->pt->w; \
+ tmy2 = (mtex->y + my + mh) / (double)mtex->pt->h; \
+ */
#define PIPE_GROW(gc, pn, inc) \
int nv = gc->pipe[pn].array.num * 3; (void) nv; \
int x, int y, int w, int h,
int r, int g, int b, int a,
Evas_GL_Texture *mtex,
- int mx, int my, int mw, int mh)
+ double mx, double my, double mw, double mh, Eina_Bool mask_smooth)
{
Eina_Bool blend = EINA_FALSE;
Evas_GL_Shader shader = SHADER_RECT;
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only)
{
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texsam = sam;
+ gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a)
{
GLfloat tx1, tx2, ty1, ty2;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texsam = 0;
+ gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth)
{
gc->pipe[pn].array.use_texuv3 = 1;
gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texsam = 0;
+ gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth)
{
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texsam = 0;
+ gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth)
{
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texsam = 0;
+ gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
double sx, double sy,
double sw, double sh,
int x, int y, int w, int h,
- Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
+ Evas_GL_Texture *mtex, double mx, double my, double mw, double mh, Eina_Bool mask_smooth,
int r, int g, int b, int a,
Eina_Bool smooth)
gc->pipe[pn].array.use_texa = EINA_TRUE;
gc->pipe[pn].array.use_texsam = 0;
gc->pipe[pn].array.use_texm = !!mtex;
+ gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texa = !!mtex;
gc->pipe[pn].array.use_texsam = gc->pipe[pn].array.use_texm;
+ gc->pipe[pn].array.mask_smooth = EINA_FALSE;
pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6);
if (shared->info.anisotropic > 0.0)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
#endif
- if (gc->pipe[i].shader.smooth)
+ if (gc->pipe[i].array.mask_smooth) // (gc->pipe[i].shader.smooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gc->pipe[i].array.use_texa = 0;
gc->pipe[i].array.use_texsam = 0;
gc->pipe[i].array.use_texm = 0;
+ gc->pipe[i].array.mask_smooth = 0;
gc->pipe[i].array.vertex = NULL;
gc->pipe[i].array.color = NULL;
{
Evas_Engine_GL_Context *gc = context;
RGBA_Draw_Context *dc = draw_context;
- Evas_GL_Texture *tex, *mtex = NULL;
+ Evas_GL_Image *mask = gc->dc->clip.mask;
+ Evas_GL_Texture *tex, *mtex = mask ? mask->tex : NULL;
Cutout_Rect *rct;
int r, g, b, a;
double ssx, ssy, ssw, ssh;
int c, cx, cy, cw, ch;
int i;
int sx, sy, sw, sh;
- double mmx = 0.0, mmy = 0.0, mmw = 0.0, mmh = 0.0;
+ double mx = 0.0, my = 0.0, mw = 0.0, mh = 0.0;
+ Eina_Bool mask_smooth = EINA_FALSE;
if (dc != gc->dc) return;
tex = fg->ext_dat;
if (gc->dc->clip.mask && (sw > 0) && (sh > 0))
{
- // FIXME: This code path does not handle half the stuff the other path does...
- Evas_GL_Image *mask = gc->dc->clip.mask;
- int nx, ny, nw, nh, dx, dy, dw, dh;
- double mx, my, mw, mh;
-
- if (mask->tex)
+ double nx, ny, nw, nh, dx, dy, dw, dh;
+ const double mask_x = gc->dc->clip.mask_x;
+ const double mask_y = gc->dc->clip.mask_y;
+ const double tmw = mtex->pt->w;
+ const double tmh = mtex->pt->h;
+ double scalex = 1.0;
+ double scaley = 1.0;
+
+ // canvas coords
+ nx = x; ny = y; nw = tex->w; nh = tex->h;
+ RECTS_CLIP_TO_RECT(nx, ny, nw, nh,
+ gc->dc->clip.x, gc->dc->clip.y,
+ gc->dc->clip.w, gc->dc->clip.h);
+ if ((nw < 1) || (nh < 1)) return;
+ dx = x; dy = y; dw = sw; dh = sh;
+ mx = mask_x; my = mask_y;
+ if (mask->scaled.origin && mask->scaled.w && mask->scaled.h)
{
- nx = x; ny = y; nw = tex->w; nh = tex->h;
- RECTS_CLIP_TO_RECT(nx, ny, nw, nh,
- gc->dc->clip.x, gc->dc->clip.y,
- gc->dc->clip.w, gc->dc->clip.h);
- if ((nw < 1) || (nh < 1)) return;
-
- //ssx = (double)sx + ((double)(sw * (nx - x)) / (double)(tex->w));
- //ssy = (double)sy + ((double)(sh * (ny - y)) / (double)(tex->h));
- //ssw = ((double)sw * (double)(nw)) / (double)(tex->w);
- //ssh = ((double)sh * (double)(nh)) / (double)(tex->h);
-
- dx = x; dy = y; dw = sw; dh = sh;
- mx = gc->dc->clip.mask_x; my = gc->dc->clip.mask_y; mw = mask->w; mh = mask->h;
- //RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
- RECTS_CLIP_TO_RECT(mx, my, mw, mh, dx, dy, dw, dh);
-
- mmx = (double)(mx - gc->dc->clip.mask_x) + ((double)(mw * (nx - dx)) / (double)(dw));
- mmy = (double)(my - gc->dc->clip.mask_y) + ((double)(mh * (ny - dy)) / (double)(dh));
- mmw = ((double)mw * (double)(nw)) / (double)(dw);
- mmh = ((double)mh * (double)(nh)) / (double)(dh);
-
- mtex = mask->tex;
+ mw = mask->scaled.w;
+ mh = mask->scaled.h;
+ scalex = mask->w / (double)mask->scaled.w;
+ scaley = mask->h / (double)mask->scaled.h;
+ mask_smooth = mask->scaled.smooth;
+ }
+ else
+ {
+ mw = mask->w;
+ mh = mask->h;
}
+ //RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
+ RECTS_CLIP_TO_RECT(mx, my, mw, mh, dx, dy, dw, dh);
+
+ // convert to tex coords
+ mx = (mtex->x / tmw) + ((mx - mask_x + (mw * (nx - dx)) / dw) * scalex / tmw);
+ my = (mtex->y / tmh) + ((my - mask_y + (mh * (ny - dy)) / dy) * scaley / tmh);
+ mw = (mw * nw * scalex / dw) / tmw;
+ mh = (mh * nh * scaley / dh) / tmh;
}
if ((!gc->dc->cutout.rects) ||
0.0, 0.0, 0.0, 0.0,
// sx, sy, sw, sh,
x, y, tex->w, tex->h,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a);
return;
}
evas_gl_common_context_font_push(gc, tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a);
}
else
0.0, 0.0, 0.0, 0.0,
// sx, sy, sw, sh,
x, y, tex->w, tex->h,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a);
}
return;
0.0, 0.0, 0.0, 0.0,
// sx, sy, sw, sh,
x, y, tex->w, tex->h,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a);
continue;
}
evas_gl_common_context_font_push(gc, tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a);
}
evas_common_draw_context_cutouts_free(_evas_gl_common_cutout_rects);
im->references--;
if (im->references > 0) return;
+ if (im->scaled.origin)
+ evas_gl_common_image_free(im->scaled.origin);
+
if (im->native.func.free)
im->native.func.free(im->native.func.data, im);
mmw = mw;
mmh = mh;
mtex = mask->tex;
+ // TODO: implement support for scaled masks
+ //if (mask->scaled.origin)
+ //mask_smooth = mask->scaled.smooth;
}
evas_gl_common_context_image_map_push(gc, im->tex, npoints, p,
Eina_Bool yuv, Eina_Bool yuy2, Eina_Bool nv12,
Eina_Bool rgb_a_pair)
{
- double mmx = 0, mmy = 0, mmw = 0, mmh = 0;
+ double mx = 0, my = 0, mw = 0, mh = 0;
double ssx, ssy, ssw, ssh;
- Evas_GL_Texture *mtex = NULL;
+ Evas_GL_Texture *mtex = mask ? mask->tex : NULL;
+ Eina_Bool mask_smooth = EINA_FALSE;
int nx, ny, nw, nh;
nx = dx; ny = dy; nw = dw; nh = dh;
if ((nw < 1) || (nh < 1)) return;
if (!im->tex) return;
- if (mask && mask->tex)
+ if (mtex && mtex->pt && mtex->pt->w && mtex->pt->h)
{
- double mx, my, mw, mh;
-
- mx = mask_x; my = mask_y; mw = mask->w; mh = mask->h;
+ const double tmw = mtex->pt->w;
+ const double tmh = mtex->pt->h;
+ double scalex = 1.0;
+ double scaley = 1.0;
+
+ // canvas coords
+ mx = mask_x; my = mask_y;
+ if (mask->scaled.origin)
+ {
+ mw = mask->scaled.w;
+ mh = mask->scaled.h;
+ scalex = mask->w / (double)mask->scaled.w;
+ scaley = mask->h / (double)mask->scaled.h;
+ mask_smooth = mask->scaled.smooth;
+ }
+ else
+ {
+ mw = mask->w;
+ mh = mask->h;
+ }
RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
RECTS_CLIP_TO_RECT(mx, my, mw, mh, dx, dy, dw, dh);
- mmx = mx - mask_x;
- mmy = my - mask_y;
- mmw = mw;
- mmh = mh;
- mtex = mask->tex;
+
+ // convert to tex coords
+ mx = (mtex->x / tmw) + ((mx - mask_x) * scalex / tmw);
+ my = (mtex->y / tmh) + ((my - mask_y) * scaley / tmh);
+ mw = mw * scalex / tmw;
+ mh = mh * scaley / tmh;
}
if ((nx == dx) && (ny == dy) && (nw == dw) && (nh == dh))
im->tex,
sx, sy, sw, sh,
dx, dy, dw, dh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else if (yuy2)
im->tex,
sx, sy, sw, sh,
dx, dy, dw, dh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else if (nv12)
im->tex,
sx, sy, sw, sh,
dx, dy, dw, dh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else if (rgb_a_pair)
im->tex,
sx, sy, sw, sh,
dx, dy, dw, dh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else
im->tex,
sx, sy, sw, sh,
dx, dy, dw, dh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth, im->tex_only);
return;
im->tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else if (yuy2)
im->tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else if (nv12)
im->tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else if (rgb_a_pair)
im->tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth);
else
im->tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
- mtex, mmx, mmy, mmw, mmh,
+ mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a,
smooth, im->tex_only);
}
h = 1;
evas_gl_common_context_rectangle_push(gc, x, y, w, h,
cr, cg, cb, ca,
- NULL, 0, 0, 0, 0);
+ NULL, 0, 0, 0, 0, EINA_FALSE);
}
}
else
if ((w > 0) && (h > 0))
evas_gl_common_context_rectangle_push(gc, x, y, w, h,
cr, cg, cb, ca,
- NULL, 0, 0, 0, 0);
+ NULL, 0, 0, 0, 0, EINA_FALSE);
}
}
}
Cutout_Rect *r;
int c, cx, cy, cw, ch, cr, cg, cb, ca, i;
double mx = 0, my = 0, mw = 0, mh = 0;
- Evas_GL_Texture *mtex = NULL;
+ Eina_Bool mask_smooth = EINA_FALSE;
+ Evas_GL_Image *mask = gc->dc->clip.mask;
+ Evas_GL_Texture *mtex = mask ? mask->tex : NULL;
if ((w <= 0) || (h <= 0)) return;
if (!(RECTS_INTERSECT(x, y, w, h, 0, 0, gc->w, gc->h))) return;
gc->dc->clip.w, gc->dc->clip.h);
}
- if (gc->dc->clip.mask)
+ if (mtex)
{
- Evas_GL_Image *mask = gc->dc->clip.mask;
+ const double mask_x = gc->dc->clip.mask_x;
+ const double mask_y = gc->dc->clip.mask_y;
+ const double tmw = mtex->pt->w;
+ const double tmh = mtex->pt->h;
+ double scalex = 1.0;
+ double scaley = 1.0;
- mx = gc->dc->clip.mask_x; mw = mask->w;
- my = gc->dc->clip.mask_y; mh = mask->h;
+ // canvas coords
+ mx = mask_x; my = mask_y;
+ if (mask->scaled.origin && mask->scaled.w && mask->scaled.h)
+ {
+ mw = mask->scaled.w;
+ mh = mask->scaled.h;
+ scalex = mask->w / (double)mask->scaled.w;
+ scaley = mask->h / (double)mask->scaled.h;
+ mask_smooth = mask->scaled.smooth;
+ }
+ else
+ {
+ mw = mask->w;
+ mh = mask->h;
+ }
RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
mx -= gc->dc->clip.mask_x;
my -= gc->dc->clip.mask_y;
- mtex = mask->tex;
+
+ // convert to tex coords
+ mx = (mtex->x / tmw) + ((mx - mask_x) * scalex / tmw);
+ my = (mtex->y / tmh) + ((my - mask_y) * scaley / tmh);
+ mw = mw * scalex / tmw;
+ mh = mh * scaley / tmh;
}
if (!gc->dc->cutout.rects)
{
- evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca, mtex, mx, my, mw, mh);
+ evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca, mtex, mx, my, mw, mh, mask_smooth);
}
else
{
r = _evas_gl_common_cutout_rects->rects + i;
if ((r->w > 0) && (r->h > 0))
{
- evas_gl_common_context_rectangle_push(gc, r->x, r->y, r->w, r->h, cr, cg, cb, ca, mtex, mx, my, mw, mh);
+ evas_gl_common_context_rectangle_push(gc, r->x, r->y, r->w, r->h, cr, cg, cb, ca, mtex, mx, my, mw, mh, mask_smooth);
}
}
evas_common_draw_context_cutouts_free(_evas_gl_common_cutout_rects);
evas_gl_common_image_free(surface);
}
+static void *
+eng_image_scaled_update(void *data EINA_UNUSED, void *scaled, void *image,
+ int dst_w, int dst_h,
+ Eina_Bool smooth, Eina_Bool alpha,
+ Evas_Colorspace cspace EINA_UNUSED)
+{
+ Evas_GL_Image *dst = scaled;
+ Evas_GL_Image *src = image;
+ Evas_Engine_GL_Context *gc;
+
+ if (!src) return NULL;
+
+ gc = src->gc;
+ if ((dst_w > gc->shared->info.max_texture_size) ||
+ (dst_h > gc->shared->info.max_texture_size))
+ return NULL;
+
+ if (dst && (dst->scaled.origin == src) &&
+ (dst->scaled.w == dst_w) && (dst->scaled.h == dst_h))
+ return dst;
+
+ if (dst) evas_gl_common_image_free(dst);
+ evas_gl_common_image_update(gc, src);
+ if (!src->tex)
+ {
+ ERR("No source texture.");
+ return NULL;
+ }
+
+ dst = calloc(1, sizeof(Evas_GL_Image));
+ if (!dst) return NULL;
+
+ dst->references = 1;
+ dst->gc = gc;
+ dst->cs.space = src->cs.space;
+ dst->alpha = alpha;
+ dst->w = src->w;
+ dst->h = src->h;
+ dst->tex = src->tex;
+ dst->tex->references++;
+ dst->tex_only = 1;
+
+ src->references++;
+ dst->scaled.origin = src;
+ dst->scaled.w = dst_w;
+ dst->scaled.h = dst_h;
+ dst->scaled.smooth = smooth;
+
+ return dst;
+}
+
static void
eng_image_content_hint_set(void *data, void *image, int hint)
{
ORD(image_map_surface_new);
ORD(image_map_surface_free);
ORD(image_map_clean);
+ ORD(image_scaled_update);
ORD(image_content_hint_set);
ORD(image_content_hint_get);
eng_image_map_surface_new,
eng_image_map_surface_free,
eng_image_map_clean,
+ NULL, // eng_image_scaled_get - used for live scaling in GL only (fastpath)
NULL, // eng_image_content_hint_set - software doesn't use it
NULL, // eng_image_content_hint_get - software doesn't use it
eng_font_pen_coords_get,