forked from enlightenment/efl
evas: fix rotation and flipping of image in gl engine
Summary: fix rotation(90, 180, 270) and flipping(vertical, horizontal, transpose, transverse) of evas image in gl engine backend. @fix T2338 Signed-off-by: kabeer khan <kabeer.khan@samsung.com> Reviewers: cedric, jpeg Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D2400 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
parent
5e4b523d51
commit
ce45d443c1
|
@ -644,8 +644,9 @@ struct _Evas_GL_Image
|
|||
int scale_hint, content_hint;
|
||||
int csize;
|
||||
|
||||
Eina_List *filtered;
|
||||
Eina_List *targets;
|
||||
Eina_List *filtered;
|
||||
Eina_List *targets;
|
||||
Evas_Image_Orient orient;
|
||||
|
||||
unsigned char dirty : 1;
|
||||
unsigned char cached : 1;
|
||||
|
|
|
@ -1256,9 +1256,53 @@ evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc,
|
|||
PUSH_VERTEX(pn, x , y + h, 0); PUSH_VERTEX(pn, x + w, y , 0); \
|
||||
PUSH_VERTEX(pn, x + w, y + h, 0); PUSH_VERTEX(pn, x , y + h, 0); \
|
||||
} while (0)
|
||||
#define PUSH_6_TEXUV(pn, x1, y1, x2, y2) do { \
|
||||
PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y2); \
|
||||
PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y2); \
|
||||
#define PUSH_6_TEXUV(pn, Tex, x1, y1, x2, y2) do { \
|
||||
Evas_GL_Texture *_tex = Tex; \
|
||||
if (_tex && _tex->im) \
|
||||
{ \
|
||||
switch (_tex->im->orient) \
|
||||
{ \
|
||||
case EVAS_IMAGE_ORIENT_NONE: \
|
||||
PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y2); \
|
||||
PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y2); \
|
||||
break; \
|
||||
case EVAS_IMAGE_ORIENT_90: \
|
||||
PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y2); \
|
||||
PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x2, y2); \
|
||||
break; \
|
||||
case EVAS_IMAGE_ORIENT_180: \
|
||||
PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x2, y1); \
|
||||
PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y1); \
|
||||
break; \
|
||||
case EVAS_IMAGE_ORIENT_270: \
|
||||
PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y1); \
|
||||
PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x1, y1); \
|
||||
break; \
|
||||
case EVAS_IMAGE_FLIP_HORIZONTAL: \
|
||||
PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y2); \
|
||||
PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x2, y2); \
|
||||
break; \
|
||||
case EVAS_IMAGE_FLIP_VERTICAL: \
|
||||
PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y1); \
|
||||
PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y1); \
|
||||
break; \
|
||||
case EVAS_IMAGE_FLIP_TRANSVERSE: \
|
||||
PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y2); \
|
||||
PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x1, y2); \
|
||||
break; \
|
||||
case EVAS_IMAGE_FLIP_TRANSPOSE: \
|
||||
PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x2, y1); \
|
||||
PUSH_TEXUV(pn, x1, y2); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x2, y1); \
|
||||
break; \
|
||||
default: \
|
||||
ERR("Wrong orientation"); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x1, y2); \
|
||||
PUSH_TEXUV(pn, x2, y1); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x1, y2); \
|
||||
} \
|
||||
} while (0)
|
||||
#define PUSH_6_TEXUV2(pn, x1, y1, x2, y2) do { \
|
||||
PUSH_TEXUV2(pn, x1, y1); PUSH_TEXUV2(pn, x2, y1); PUSH_TEXUV2(pn, x1, y2); \
|
||||
|
@ -1918,6 +1962,7 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
|
|||
Evas_GL_Texture_Pool *pt;
|
||||
GLfloat tx1, tx2, ty1, ty2;
|
||||
GLfloat offsetx, offsety;
|
||||
double pw, ph;
|
||||
Eina_Bool blend = EINA_FALSE;
|
||||
Evas_GL_Shader shader = SHADER_IMG;
|
||||
GLuint prog = gc->shared->shader[shader].prog;
|
||||
|
@ -1992,23 +2037,36 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
|
|||
pipe_region_expand(gc, pn, x, y, w, h);
|
||||
PIPE_GROW(gc, pn, 6);
|
||||
|
||||
pw = pt->w;
|
||||
ph = pt->h;
|
||||
if (tex->im &&
|
||||
(tex->im->orient == EVAS_IMAGE_ORIENT_90 ||
|
||||
tex->im->orient == EVAS_IMAGE_ORIENT_270 ||
|
||||
tex->im->orient == EVAS_IMAGE_FLIP_TRANSPOSE ||
|
||||
tex->im->orient == EVAS_IMAGE_FLIP_TRANSVERSE))
|
||||
{
|
||||
// Adjust size for taking rotation into account as im->w and h are already modified.
|
||||
pw = pt->h;
|
||||
ph = pt->w;
|
||||
}
|
||||
|
||||
if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
|
||||
{
|
||||
tx1 = ((double)(offsetx) + sx) / (double)pt->w;
|
||||
ty1 = 1.0 - ((double)(offsety) + sy) / (double)pt->h;
|
||||
tx2 = ((double)(offsetx) + sx + sw) / (double)pt->w;
|
||||
ty2 = 1.0 - ((double)(offsety) + sy + sh) / (double)pt->h;
|
||||
tx1 = ((double)(offsetx) + sx) / pw;
|
||||
ty1 = 1.0 - ((double)(offsety) + sy) / ph;
|
||||
tx2 = ((double)(offsetx) + sx + sw) / pw;
|
||||
ty2 = 1.0 - ((double)(offsety) + sy + sh) / ph;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx1 = ((double)(offsetx) + sx) / (double)pt->w;
|
||||
ty1 = ((double)(offsety) + sy) / (double)pt->h;
|
||||
tx2 = ((double)(offsetx) + sx + sw) / (double)pt->w;
|
||||
ty2 = ((double)(offsety) + sy + sh) / (double)pt->h;
|
||||
tx1 = ((double)(offsetx) + sx) / pw;
|
||||
ty1 = ((double)(offsety) + sy) / ph;
|
||||
tx2 = ((double)(offsetx) + sx + sw) / pw;
|
||||
ty2 = ((double)(offsety) + sy + sh) / ph;
|
||||
}
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV(pn, tex, tx1, ty1, tx2, ty2);
|
||||
|
||||
if (sam)
|
||||
{
|
||||
|
@ -2098,7 +2156,7 @@ evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
|
|||
}
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV(pn, NULL, tx1, ty1, tx2, ty2);
|
||||
PUSH_MASK(pn, mtex, mx, my, mw, mh);
|
||||
PUSH_6_COLORS(pn, r, g, b, a);
|
||||
}
|
||||
|
@ -2174,7 +2232,7 @@ evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
|
|||
t2y2 = ((sy + sh) / 2) / (double)tex->ptu->h;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV(pn, NULL, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
|
||||
PUSH_6_TEXUV3(pn, t2x1, t2y1, t2x2, t2y2);
|
||||
PUSH_MASK(pn, mtex, mx, my, mw, mh);
|
||||
|
@ -2252,7 +2310,7 @@ evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc,
|
|||
t2y2 = (sy + sh) / (double)tex->ptuv->h;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV(pn, NULL, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
|
||||
PUSH_MASK(pn, mtex, mx, my, mw, mh);
|
||||
if (!nomul)
|
||||
|
@ -2332,7 +2390,7 @@ evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
|
|||
t2y2 = (sy + sh) / (double)tex->ptuv->h;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV(pn, NULL, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
|
||||
PUSH_MASK(pn, mtex, mx, my, mw, mh);
|
||||
if (!nomul)
|
||||
|
@ -2416,7 +2474,7 @@ evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc,
|
|||
t2y2 = (tex->y + sy + sh) / (double)tex->pta->h;
|
||||
|
||||
PUSH_6_VERTICES(pn, x, y, w, h);
|
||||
PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXUV(pn, NULL, tx1, ty1, tx2, ty2);
|
||||
PUSH_6_TEXA(pn, t2x1, t2y1, t2x2, t2y2);
|
||||
PUSH_MASK(pn, mtex, mx, my, mw, mh);
|
||||
if (!nomul)
|
||||
|
|
|
@ -228,6 +228,7 @@ found_cspace:
|
|||
im->gc = gc;
|
||||
im->cached = 1;
|
||||
im->cs.space = cspace;
|
||||
im->orient = EVAS_IMAGE_ORIENT_NONE;
|
||||
im->alpha = im->im->cache_entry.flags.alpha;
|
||||
im->w = im->im->cache_entry.w;
|
||||
im->h = im->im->cache_entry.h;
|
||||
|
|
|
@ -43,7 +43,18 @@ static int _evas_engine_GL_log_dom = -1;
|
|||
#define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_GL_log_dom, __VA_ARGS__)
|
||||
#define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_GL_log_dom, __VA_ARGS__)
|
||||
|
||||
#ifdef GL_GLES
|
||||
# ifndef GL_FRAMEBUFFER
|
||||
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||
# endif
|
||||
#else
|
||||
# ifndef GL_FRAMEBUFFER
|
||||
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static int eng_gl_image_direct_get(void *data EINA_UNUSED, void *image);
|
||||
static int eng_gl_surface_destroy(void *data, void *surface);
|
||||
|
||||
static void
|
||||
eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h, Eina_Bool do_async EINA_UNUSED)
|
||||
|
@ -473,14 +484,27 @@ eng_image_free(void *data, void *image)
|
|||
static void
|
||||
eng_image_size_get(void *data EINA_UNUSED, void *image, int *w, int *h)
|
||||
{
|
||||
Evas_GL_Image *im;
|
||||
if (!image)
|
||||
{
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
return;
|
||||
}
|
||||
if (w) *w = ((Evas_GL_Image *)image)->w;
|
||||
if (h) *h = ((Evas_GL_Image *)image)->h;
|
||||
im = image;
|
||||
if (im->orient == EVAS_IMAGE_ORIENT_90 ||
|
||||
im->orient == EVAS_IMAGE_ORIENT_270 ||
|
||||
im->orient == EVAS_IMAGE_FLIP_TRANSPOSE ||
|
||||
im->orient == EVAS_IMAGE_FLIP_TRANSVERSE)
|
||||
{
|
||||
if (w) *w = ((Evas_GL_Image *)image)->h;
|
||||
if (h) *h = ((Evas_GL_Image *)image)->w;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w) *w = ((Evas_GL_Image *)image)->w;
|
||||
if (h) *h = ((Evas_GL_Image *)image)->h;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
|
@ -548,6 +572,91 @@ eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h)
|
|||
return image;
|
||||
}
|
||||
|
||||
static Evas_GL_Image *
|
||||
_rotate_image_data(void *data, void *img)
|
||||
{
|
||||
int alpha;
|
||||
Evas_GL_Image *im1, *im2;
|
||||
Evas_Engine_GL_Context *gl_context;
|
||||
Render_Engine_GL_Generic *re = data;
|
||||
RGBA_Draw_Context *dc;
|
||||
DATA32 *pixels;
|
||||
int w, h;
|
||||
|
||||
re->window_use(re->software.ob);
|
||||
gl_context = re->window_gl_context_get(re->software.ob);
|
||||
im1 = img;
|
||||
|
||||
w = im1->w;
|
||||
h = im1->h;
|
||||
alpha = eng_image_alpha_get(data, img);
|
||||
|
||||
if (im1->orient == EVAS_IMAGE_ORIENT_90 ||
|
||||
im1->orient == EVAS_IMAGE_ORIENT_270 ||
|
||||
im1->orient == EVAS_IMAGE_FLIP_TRANSPOSE ||
|
||||
im1->orient == EVAS_IMAGE_FLIP_TRANSVERSE)
|
||||
{
|
||||
w = im1->h;
|
||||
h = im1->w;
|
||||
}
|
||||
|
||||
im2 = evas_gl_common_image_surface_new(gl_context, w, h, alpha);
|
||||
|
||||
evas_gl_common_context_target_surface_set(gl_context, im2);
|
||||
|
||||
// Create a new and temporary context
|
||||
dc = evas_common_draw_context_new();
|
||||
evas_common_draw_context_set_clip(dc, 0, 0, im2->w, im2->h);
|
||||
gl_context->dc = dc;
|
||||
|
||||
// Image draw handle the rotation magically for us
|
||||
evas_gl_common_image_draw(gl_context, im1,
|
||||
0, 0, w, h,
|
||||
0, 0, im2->w, im2->h,
|
||||
0);
|
||||
// Do not forget to flush everything or you will have nothing in your buffer
|
||||
evas_gl_common_context_flush(gl_context);
|
||||
|
||||
gl_context->dc = NULL;
|
||||
evas_common_draw_context_free(dc);
|
||||
|
||||
glsym_glBindFramebuffer(GL_FRAMEBUFFER, im2->tex->pt->fb);
|
||||
GLERRV("glsym_glBindFramebuffer");
|
||||
|
||||
// Rely on Evas_GL_Image infrastructure to allocate pixels
|
||||
im2->im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
|
||||
if (!im2->im) return NULL;
|
||||
im2->im->cache_entry.flags.alpha = !!alpha;
|
||||
evas_gl_common_image_alloc_ensure(im2);
|
||||
pixels = im2->im->image.data;
|
||||
|
||||
if (im2->tex->pt->format == GL_BGRA)
|
||||
{
|
||||
glReadPixels(0, 0, im2->w, im2->h, GL_BGRA,
|
||||
GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
DATA32 *ptr = pixels;
|
||||
unsigned int k;
|
||||
|
||||
glReadPixels(0, 0, im2->w, im2->h, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, pixels);
|
||||
for (k = im2->w * im2->h; k; --k)
|
||||
{
|
||||
const DATA32 v = *ptr;
|
||||
*ptr++ = (v & 0xFF00FF00)
|
||||
| ((v & 0x00FF0000) >> 16)
|
||||
| ((v & 0x000000FF) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
GLERRV("glsym_glBindFramebuffer");
|
||||
|
||||
return im2;
|
||||
}
|
||||
|
||||
static void *
|
||||
eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, int *err)
|
||||
{
|
||||
|
@ -555,20 +664,34 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
|
|||
Evas_GL_Image *im;
|
||||
int error;
|
||||
|
||||
*image_data = NULL;
|
||||
|
||||
if (!image)
|
||||
{
|
||||
*image_data = NULL;
|
||||
if (err) *err = EVAS_LOAD_ERROR_GENERIC;
|
||||
return NULL;
|
||||
}
|
||||
im = image;
|
||||
if (im->native.data)
|
||||
{
|
||||
*image_data = NULL;
|
||||
if (err) *err = EVAS_LOAD_ERROR_NONE;
|
||||
return im;
|
||||
}
|
||||
|
||||
if (im->orient != EVAS_IMAGE_ORIENT_NONE)
|
||||
{
|
||||
Evas_GL_Image *im_new = _rotate_image_data(data, image);
|
||||
if (!im_new)
|
||||
{
|
||||
if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
return im;
|
||||
}
|
||||
evas_gl_common_image_free(im);
|
||||
|
||||
*image_data = im_new->im->image.data;
|
||||
return im_new;
|
||||
}
|
||||
|
||||
#ifdef GL_GLES
|
||||
re->window_use(re->software.ob);
|
||||
|
||||
|
@ -771,6 +894,32 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
|
|||
return im;
|
||||
}
|
||||
|
||||
static void *
|
||||
eng_image_orient_set(void *data, void *image, Evas_Image_Orient orient)
|
||||
{
|
||||
Render_Engine_GL_Generic *re = data;
|
||||
Evas_GL_Image *im;
|
||||
|
||||
if (!image) return NULL;
|
||||
im = image;
|
||||
if (im->orient == orient) return image;
|
||||
|
||||
re->window_use(re->software.ob);
|
||||
|
||||
im->orient = orient;
|
||||
return im;
|
||||
}
|
||||
|
||||
static Evas_Image_Orient
|
||||
eng_image_orient_get(void *data EINA_UNUSED, void *image)
|
||||
{
|
||||
Evas_GL_Image *im;
|
||||
|
||||
if (!image) return EVAS_IMAGE_ORIENT_NONE;
|
||||
im = image;
|
||||
return im->orient;
|
||||
}
|
||||
|
||||
static void
|
||||
eng_image_data_preload_request(void *data, void *image, const Eo *target)
|
||||
{
|
||||
|
@ -1474,16 +1623,6 @@ eng_gl_surface_read_pixels(void *data, void *surface,
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
#ifdef GL_GLES
|
||||
# ifndef GL_FRAMEBUFFER
|
||||
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||
# endif
|
||||
#else
|
||||
# ifndef GL_FRAMEBUFFER
|
||||
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Since this is an FBO, the pixels are already in the right Y order.
|
||||
* But some devices don't support GL_BGRA, so we still need to convert.
|
||||
*/
|
||||
|
@ -2351,6 +2490,8 @@ module_open(Evas_Module *em)
|
|||
ORD(image_data_preload_cancel);
|
||||
ORD(image_alpha_set);
|
||||
ORD(image_alpha_get);
|
||||
ORD(image_orient_set);
|
||||
ORD(image_orient_get);
|
||||
ORD(image_border_set);
|
||||
ORD(image_border_get);
|
||||
ORD(image_draw);
|
||||
|
|
Loading…
Reference in New Issue