From 26ee52dd61de15deaf4ee315df43eebe6def9193 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Mon, 29 Aug 2011 20:56:48 +0000 Subject: [PATCH] evas: add NV12 and MT12 colorspace. MT12 is has documented in Linux videodev documentation a 64 * 32 macro block tiled colorspace format used on Samsung hardware. SVN revision: 62967 --- legacy/evas/ChangeLog | 5 + legacy/evas/src/lib/Evas.h | 4 +- .../evas/src/lib/canvas/evas_object_image.c | 12 + .../engines/common/evas_convert_colorspace.c | 42 ++ .../engines/common/evas_convert_colorspace.h | 10 +- .../src/lib/engines/common/evas_convert_yuv.c | 221 ++++++++++ .../src/lib/engines/common/evas_convert_yuv.h | 8 +- .../src/lib/engines/common/evas_image_main.c | 14 + .../engines/gl_common/evas_gl_common.h | 15 +- .../engines/gl_common/evas_gl_context.c | 381 ++++++------------ .../modules/engines/gl_common/evas_gl_image.c | 42 +- .../engines/gl_common/evas_gl_shader.c | 41 ++ .../engines/gl_common/evas_gl_texture.c | 117 ++++-- .../gl_common/shader/nv12_nomul_vert.h | 14 + .../gl_common/shader/nv12_nomul_vert.shd | 14 + .../engines/gl_common/shader/nv12_vert.h | 16 + .../engines/gl_common/shader/nv12_vert.shd | 16 + .../engines/gl_common/shader/yuy2_frag.shd | 26 ++ .../gl_common/shader/yuy2_nomul_frag.shd | 26 ++ .../gl_common/shader/yuy2_nomul_vert.shd | 13 + .../engines/gl_common/shader/yuy2_vert.shd | 16 + .../src/modules/engines/gl_sdl/evas_engine.c | 22 +- .../src/modules/engines/gl_x11/evas_engine.c | 22 +- .../engines/software_generic/evas_engine.c | 4 + 24 files changed, 793 insertions(+), 308 deletions(-) create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.h create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.shd create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.h create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.shd create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/yuy2_frag.shd create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_frag.shd create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_vert.shd create mode 100644 legacy/evas/src/modules/engines/gl_common/shader/yuy2_vert.shd diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index 494fbba9d3..30d7a935b0 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -470,3 +470,8 @@ * Fix evas_object_image_data_convert. * Add YUV 601 input format to evas_object_image_data_convert. + +2011-08-29 Cedric Bail + + * Add colorspaces NV12 and MT12 (64 * 32 macro block tiled + format, see Linux videodev documentation for more information). diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index 1db88d5de0..4cc8584cdd 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -510,7 +510,9 @@ typedef enum _Evas_Colorspace EVAS_COLORSPACE_YCBCR422P709_PL,/**< YCbCr 4:2:2 Planar, ITU.BT-709 specifications. The data pointed to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */ EVAS_COLORSPACE_RGB565_A5P, /**< 16bit rgb565 + Alpha plane at end - 5 bits of the 8 being used per alpha byte */ EVAS_COLORSPACE_GRY8, /**< 8bit grayscale */ - EVAS_COLORSPACE_YCBCR422601_PL /**< YCbCr 4:2:2, ITU.BT-601 specifications. The data poitned to is just an array of row pointer, pointing to line of Y,Cb,Y,Cr bytes */ + EVAS_COLORSPACE_YCBCR422601_PL, /**< YCbCr 4:2:2, ITU.BT-601 specifications. The data poitned to is just an array of row pointer, pointing to line of Y,Cb,Y,Cr bytes */ + EVAS_COLORSPACE_YCBCR420NV12601_PL, /**< YCbCr 4:2:0, ITU.BT-601 specification. The data pointed to is just an array of row pointer, pointing to the Y rows, then the Cb,Cr rows. */ + EVAS_COLORSPACE_YCBCR420TM12601_PL, /**< YCbCr 4:2:0, ITU.BT-601 specification. The data pointed to is just an array of tiled row pointer, pointing to the Y rows, then the Cb,Cr rows. */ } Evas_Colorspace; /**< Colorspaces for pixel data supported by Evas */ /** diff --git a/legacy/evas/src/lib/canvas/evas_object_image.c b/legacy/evas/src/lib/canvas/evas_object_image.c index 937a0c4778..4b68e0c6cc 100644 --- a/legacy/evas/src/lib/canvas/evas_object_image.c +++ b/legacy/evas/src/lib/canvas/evas_object_image.c @@ -3644,6 +3644,18 @@ evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_C o->cur.image.h, to_cspace); break; + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + out = evas_common_convert_yuv_420_601_to(data, + o->cur.image.w, + o->cur.image.h, + to_cspace); + break; + case EVAS_COLORSPACE_YCBCR420TM12601_PL: + out = evas_common_convert_yuv_420T_601_to(data, + o->cur.image.w, + o->cur.image.h, + to_cspace); + break; default: fprintf(stderr, "unknow colorspace: %i\n", o->cur.cspace); break; diff --git a/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c b/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c index 6ee1560087..013c2e7896 100644 --- a/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c +++ b/legacy/evas/src/lib/engines/common/evas_convert_colorspace.c @@ -140,5 +140,47 @@ evas_common_convert_yuv_422P_601_to(void *data, int w, int h, Evas_Colorspace cs return NULL; } +EAPI void * +evas_common_convert_yuv_420_601_to(void *data, int w, int h, Evas_Colorspace cspace) +{ + switch (cspace) + { + case EVAS_COLORSPACE_ARGB8888: + { + void *dst; + + dst = malloc(sizeof (unsigned int) * w * h); + if (!dst) return NULL; + + evas_common_convert_yuv_420_601_rgba(data, dst, w, h); + break; + } + default: + break; + } + return NULL; +} + +EAPI void * +evas_common_convert_yuv_420T_601_to(void *data, int w, int h, Evas_Colorspace cspace) +{ + switch (cspace) + { + case EVAS_COLORSPACE_ARGB8888: + { + void *dst; + + dst = malloc(sizeof (unsigned int) * w * h); + if (!dst) return NULL; + + evas_common_convert_yuv_420_601_rgba(data, dst, w, h); + break; + } + default: + break; + } + return NULL; +} + /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/legacy/evas/src/lib/engines/common/evas_convert_colorspace.h b/legacy/evas/src/lib/engines/common/evas_convert_colorspace.h index 16ec4e5666..f3bec7862e 100644 --- a/legacy/evas/src/lib/engines/common/evas_convert_colorspace.h +++ b/legacy/evas/src/lib/engines/common/evas_convert_colorspace.h @@ -2,9 +2,11 @@ #define _EVAS_CONVERT_COLORSPACE_H -EAPI void *evas_common_convert_argb8888_to (void *data, int w, int h, int stride, Eina_Bool has_alpha, Evas_Colorspace cspace); -EAPI void *evas_common_convert_rgb565_a5p_to (void *data, int w, int h, int stride, Eina_Bool has_alpha, Evas_Colorspace cspace); -EAPI void *evas_common_convert_yuv_422P_601_to (void *data, int w, int h, Evas_Colorspace cspace); -EAPI void *evas_common_convert_yuv_422_601_to (void *data, int w, int h, Evas_Colorspace cspace); +EAPI void *evas_common_convert_argb8888_to (void *data, int w, int h, int stride, Eina_Bool has_alpha, Evas_Colorspace cspace); +EAPI void *evas_common_convert_rgb565_a5p_to (void *data, int w, int h, int stride, Eina_Bool has_alpha, Evas_Colorspace cspace); +EAPI void *evas_common_convert_yuv_422P_601_to(void *data, int w, int h, Evas_Colorspace cspace); +EAPI void *evas_common_convert_yuv_422_601_to (void *data, int w, int h, Evas_Colorspace cspace); +EAPI void *evas_common_convert_yuv_420_601_to (void *data, int w, int h, Evas_Colorspace cspace); +EAPI void *evas_common_convert_yuv_420T_601_to(void *data, int w, int h, Evas_Colorspace cspace); #endif /* _EVAS_CONVERT_COLORSPACE_H */ diff --git a/legacy/evas/src/lib/engines/common/evas_convert_yuv.c b/legacy/evas/src/lib/engines/common/evas_convert_yuv.c index b832149157..94b00ba943 100644 --- a/legacy/evas/src/lib/engines/common/evas_convert_yuv.c +++ b/legacy/evas/src/lib/engines/common/evas_convert_yuv.c @@ -26,6 +26,8 @@ static void _evas_yv12torgb_diz (unsigned char **yuv, unsigned char *rgb, int #endif static void _evas_yv12torgb_raster (unsigned char **yuv, unsigned char *rgb, int w, int h); static void _evas_yuy2torgb_raster (unsigned char **yuv, unsigned char *rgb, int w, int h); +static void _evas_nv12torgb_raster (unsigned char **yuv, unsigned char *rgb, int w, int h); +static void _evas_nv12tiledtorgb_raster(unsigned char **yuv, unsigned char *rgb, int w, int h); #define CRV 104595 #define CBU 132251 @@ -898,6 +900,26 @@ evas_common_convert_yuv_422_601_rgba(DATA8 **src, DATA8 *dst, int w, int h) #endif } +void +evas_common_convert_yuv_420_601_rgba(DATA8 **src, DATA8 *dst, int w, int h) +{ +#ifdef BUILD_C + if (!initted) _evas_yuv_init(); + initted = 1; + _evas_nv12torgb_raster(src, dst, w, h); +#endif +} + +void +evas_common_convert_yuv_420T_601_rgba(DATA8 **src, DATA8 *dst, int w, int h) +{ +#ifdef BUILD_C + if (initted) _evas_yuv_init(); + initted = 1; + _evas_nv12tiledtorgb_raster(src, dst, w, h); +#endif +} + static void _evas_yuy2torgb_raster(unsigned char **yuv, unsigned char *rgb, int w, int h) { @@ -953,5 +975,204 @@ _evas_yuy2torgb_raster(unsigned char **yuv, unsigned char *rgb, int w, int h) #endif } +#ifdef BUILD_C +static inline void +_evas_yuv2rgb_420_raster(unsigned char *yp1, unsigned char *yp2, unsigned char *up, unsigned char *vp, + unsigned char *dp1, unsigned char *dp2) +{ + int y, u, v; + int vmu; + + /* collect u & v for 4 pixels block */ + u = *up; + v = *vp; + + /* save lookups */ + vmu = _v813[v] + _v391[u]; + u = _v2018[u]; + v = _v1596[v]; + + /* do the top 2 pixels of the 2x2 block which shared u & v */ + /* yuv to rgb */ + y = _v1164[*yp1]; + *((DATA32 *) dp1) = 0xff000000 + RGB_JOIN(LUT_CLIP(y + v), LUT_CLIP(y - vmu), LUT_CLIP(y + u)); + + dp1 += 4; yp1++; + + /* yuv to rgb */ + y = _v1164[*yp1]; + *((DATA32 *) dp1) = 0xff000000 + RGB_JOIN(LUT_CLIP(y + v), LUT_CLIP(y - vmu), LUT_CLIP(y + u)); + + /* do the bottom 2 pixels of the 2x2 block which shared u & v */ + /* yuv to rgb */ + y = _v1164[*yp2]; + *((DATA32 *) dp2) = 0xff000000 + RGB_JOIN(LUT_CLIP(y + v), LUT_CLIP(y - vmu), LUT_CLIP(y + u)); + + dp2 += 4; yp2++; + + /* yuv to rgb */ + y = _v1164[*yp2]; + *((DATA32 *) dp2) = 0xff000000 + RGB_JOIN(LUT_CLIP(y + v), LUT_CLIP(y - vmu), LUT_CLIP(y + u)); +} +#endif + +static void +_evas_nv12tiledtorgb_raster(unsigned char **yuv, unsigned char *rgb, int w, int h) +{ +#ifdef BUILD_C + +#define HANDLE_MACROBLOCK(YP1, YP2, UP, VP, DP1, DP2) \ + { \ + int i; \ + int j; \ + \ + for (i = 0; i < 32; i += 2) \ + { \ + for (j = 0; j < 64; j += 2) \ + { \ + _evas_yuv2rgb_420_raster(YP1, YP2, UP, VP, DP1, DP2); \ + \ + /* the previous call just rendered 2 pixels per lines */ \ + DP1 += 8; DP2 += 8; \ + \ + /* and took for that 2 lines with 2 Y, 1 U and 1 V. Don't forget U & V are in the same plane */ \ + YP1 += 2; YP2 += 2; UP += 2; VP += 2; \ + } \ + \ + DP1 += sizeof (int) * w; \ + DP2 += sizeof (int) * w; \ + YP1 += 64; \ + YP2 += 64; \ + } \ + } + + /* One macro block is 32 lines of Y and 16 lines of UV */ + int mb_x, mb_y, mb_w, mb_h; + + /* Idea iterate over each macroblock and convert each of them using _evas_nv12torgb_raster */ + + /* The layout of the macroblock order in RGB non tiled space : */ + /* --------------------------------------------------- */ + /* | 0 | 1 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | */ + /* --------------------------------------------------- */ + /* | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 18 | 19 | */ + /* --------------------------------------------------- */ + /* | 20 | 21 | 26 | 27 | 28 | 29 | 34 | 35 | 36 | 37 | */ + /* --------------------------------------------------- */ + /* | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 38 | 39 | */ + /* --------------------------------------------------- */ + /* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | */ + /* --------------------------------------------------- */ + + /* the number of macroblock should be a multiple of 64x32 */ + mb_w = w / 64; + mb_h = h / 32; + + /* In this format we linearize macroblock on two line to form a Z and it's invert */ + for (mb_y = 0; mb_y < (mb_h / 2); ++mb_y) + { + int step = 1; + int offset = 0; + int x = 0; + + for (mb_x = 0; mb_x < (mb_w * 2); ++mb_x) + { + unsigned char *yp1, *yp2, *up, *vp; + unsigned char *dp1, *dp2; + + step++; + + if (step % 4 == 0) + { + x -= 2; + offset = 1 - offset; + } + else + { + x++; + } + + /* Y mb addr = yuv[mb_y] + mb_x */ + /* UV mb addr = yuv[mb_y + mb_h / 2] + mb_x / 2*/ + /* visual addr = rgb + x * 64 + (mb_y + offset) * 2 * 32 * w */ + + dp1 = rgb + x * 64 + (mb_y + offset) * 2 * 32 * w; + dp2 = dp1 + sizeof (int) * w; + + yp1 = yuv[mb_y] + mb_x * 64; + yp2 = yp1 + 64; + + up = yuv[mb_y + mb_h / 2] + mb_x * 64; /* UV plane is two time less bigger in pixel count, but it old two bytes each times */ + vp = up + 1; + + HANDLE_MACROBLOCK(yp1, yp2, up, vp, dp1, dp2); + } + } + + if (mb_h % 2) + { + mb_y++; + int x = 0; + + for (mb_x = 0; mb_x < mb_w; ++mb_x, ++x) + { + unsigned char *yp1, *yp2, *up, *vp; + unsigned char *dp1, *dp2; + + dp1 = rgb + x * 64 + mb_y * 2 * 32 *w; + dp2 = dp1 + sizeof (int) * w; + + yp1 = yuv[mb_y] + mb_x * 64; + yp2 = yp1 + 64; + + up = yuv[mb_y + mb_h / 2] + mb_x * 64; + vp = up + 1; + + HANDLE_MACROBLOCK(yp1, yp2, up, vp, dp1, dp2); + } + } +#endif +} + +static void +_evas_nv12torgb_raster(unsigned char **yuv, unsigned char *rgb, int w, int h) +{ +#ifdef BUILD_C + int xx, yy; + unsigned char *yp1, *yp2, *up, *vp; + unsigned char *dp1; + unsigned char *dp2; + + dp1 = rgb; + dp2 = dp1 + sizeof (int) * w; + + for (yy = 0; yy < h; yy++) + { + yp1 = yuv[yy++]; + yp2 = yuv[yy]; + + up = yuv[h + (yy >> 1)]; + vp = up + 1; + + for (xx = 0; xx < w; xx += 2) + { + _evas_yuv2rgb_420_raster(yp1, yp2, up, vp, dp1, dp2); + + /* the previous call just rendered 2 pixels per lines */ + dp1 += 8; dp2 += 8; + + /* and took for that 2 lines with 2 Y, 1 U and 1 V. Don't forget U & V are in the same plane */ + yp1 += 2; yp2 += 2; up += 2; vp += 2; + } + + /* jump one line */ + dp1 += sizeof (int) * w; + dp2 += sizeof (int) * w; + yp1 += w; + yp2 += w; + } +#endif +} + #endif diff --git a/legacy/evas/src/lib/engines/common/evas_convert_yuv.h b/legacy/evas/src/lib/engines/common/evas_convert_yuv.h index 12b4f78f3f..b598807176 100644 --- a/legacy/evas/src/lib/engines/common/evas_convert_yuv.h +++ b/legacy/evas/src/lib/engines/common/evas_convert_yuv.h @@ -1,9 +1,9 @@ #ifndef _EVAS_CONVERT_YUV_H #define _EVAS_CONVERT_YUV_H - -EAPI void evas_common_convert_yuv_420p_601_rgba (DATA8 **src, DATA8 *dst, int w, int h); -EAPI void evas_common_convert_yuv_422_601_rgba(DATA8 **src, DATA8 *dst, int w, int h); - +EAPI void evas_common_convert_yuv_420p_601_rgba (DATA8 **src, DATA8 *dst, int w, int h); +EAPI void evas_common_convert_yuv_422_601_rgba (DATA8 **src, DATA8 *dst, int w, int h); +EAPI void evas_common_convert_yuv_420_601_rgba (DATA8 **src, DATA8 *dst, int w, int h); +EAPI void evas_common_convert_yuv_420T_601_rgba (DATA8 **src, DATA8 *dst, int w, int h); #endif /* _EVAS_CONVERT_YUV_H */ diff --git a/legacy/evas/src/lib/engines/common/evas_image_main.c b/legacy/evas/src/lib/engines/common/evas_image_main.c index 122bd869f6..d4d847ccaa 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_main.c +++ b/legacy/evas/src/lib/engines/common/evas_image_main.c @@ -610,6 +610,20 @@ evas_common_image_colorspace_normalize(RGBA_Image *im) im->cache_entry.w, im->cache_entry.h); #endif break; + case EVAS_COLORSPACE_YCBCR420NV12601_PL: +#ifdef BUILD_CONVERT_YUV + if ((im->image.data) && (*((unsigned char **)im->cs.data))) + evas_common_convert_yuv_420_601_rgba(im->cs.data, (DATA8*) im->image.data, + im->cache_entry.w, im->cache_entry.h); +#endif + break; + case EVAS_COLORSPACE_YCBCR420TM12601_PL: +#ifdef BUILD_CONVERT_YUV + if ((im->image.data) && (*((unsigned char **)im->cs.data))) + evas_common_convert_yuv_420T_601_rgba(im->cs.data, (DATA8*) im->image.data, + im->cache_entry.w, im->cache_entry.h); +#endif + break; default: break; } diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h index 64adfa5e07..9c7d5b35e1 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h @@ -130,6 +130,8 @@ typedef enum { SHADER_YUV_NOMUL, SHADER_YUY2, SHADER_YUY2_NOMUL, + SHADER_NV12, + SHADER_NV12_NOMUL, SHADER_TEX, SHADER_TEX_NOMUL, SHADER_FILTER_INVERT, @@ -525,6 +527,12 @@ void evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc, int x, int y, int w, int h, 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, + int r, int g, int b, int a, + Eina_Bool smooth); void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, Evas_GL_Texture *tex, int npoints, @@ -533,8 +541,7 @@ void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g int r, int g, int b, int a, Eina_Bool smooth, Eina_Bool tex_only, - Eina_Bool yuv, - Eina_Bool yuy2); + Evas_Colorspace cspace); void evas_gl_common_context_flush(Evas_Engine_GL_Context *gc); int evas_gl_common_shader_program_init(Evas_GL_Shared *shared); @@ -556,6 +563,10 @@ Evas_GL_Texture *evas_gl_common_texture_yuv_new(Evas_Engine_GL_Context *gc, DAT void evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned int w, unsigned int h); Evas_GL_Texture *evas_gl_common_texture_yuy2_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h); void evas_gl_common_texture_yuy2_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned int w, unsigned int h); +Evas_GL_Texture *evas_gl_common_texture_nv12_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h); +void evas_gl_common_texture_nv12_update(Evas_GL_Texture *tex, DATA8 **row, unsigned int w, unsigned int h); +Evas_GL_Texture *evas_gl_common_texture_nv12tiled_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h); +void evas_gl_common_texture_nv12tiled_update(Evas_GL_Texture *tex, DATA8 **row, unsigned int w, unsigned int h); void evas_gl_common_image_all_unload(Evas_Engine_GL_Context *gc); diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c index 4bba403b36..31bcc97c22 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c @@ -687,6 +687,9 @@ evas_gl_common_context_new(void) SHADER_TEXTURE_ADD(shared, YUY2, tex); SHADER_TEXTURE_ADD(shared, YUY2, texuv); + SHADER_TEXTURE_ADD(shared, NV12, tex); + SHADER_TEXTURE_ADD(shared, NV12, texuv); + SHADER_TEXTURE_ADD(shared, YUV_NOMUL, tex); SHADER_TEXTURE_ADD(shared, YUV_NOMUL, texu); SHADER_TEXTURE_ADD(shared, YUV_NOMUL, texv); @@ -694,6 +697,9 @@ evas_gl_common_context_new(void) SHADER_TEXTURE_ADD(shared, YUY2_NOMUL, tex); SHADER_TEXTURE_ADD(shared, YUY2_NOMUL, texuv); + SHADER_TEXTURE_ADD(shared, NV12_NOMUL, tex); + SHADER_TEXTURE_ADD(shared, NV12_NOMUL, texuv); + SHADER_TEXTURE_ADD(shared, IMG_MASK, tex); SHADER_TEXTURE_ADD(shared, IMG_MASK, texm); @@ -1084,6 +1090,24 @@ vertex_array_size_check(Evas_Engine_GL_Context *gc, int pn, int n) return 1; } +static inline Evas_GL_Shader +evas_gl_common_shader_choice(int npoints, + RGBA_Map_Point *p, + int r, int g, int b, int a, + Evas_GL_Shader nomul, + Evas_GL_Shader mul) +{ + if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) + { + if (!p) return nomul; + + if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && + (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) + return nomul; + } + return mul; +} + static int _evas_gl_common_context_push(int rtype, Evas_Engine_GL_Context *gc, @@ -1408,34 +1432,26 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc, { if (tex->pt->dyn.img) { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - prog = gc->shared->shader[SHADER_IMG_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_IMG].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a, + SHADER_IMG_NOMUL, SHADER_IMG)].prog; } else { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - prog = gc->shared->shader[SHADER_TEX_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_TEX].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a, + SHADER_TEX_NOMUL, SHADER_TEX)].prog; } } else { if (tex->gc->shared->info.bgra) { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - prog = gc->shared->shader[SHADER_IMG_BGRA_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_IMG_BGRA].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a, + SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog; } else { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - prog = gc->shared->shader[SHADER_IMG_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_IMG].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a, + SHADER_IMG_NOMUL, SHADER_IMG)].prog; } } @@ -1542,153 +1558,34 @@ evas_gl_common_context_image_mask_push(Evas_Engine_GL_Context *gc, } #endif -again: - vertex_array_size_check(gc, gc->state.top_pipe, 6); - pn = gc->state.top_pipe; -#ifdef GLPIPES - if ((pn == 0) && (gc->pipe[pn].array.num == 0)) - { - gc->pipe[pn].region.type = RTYPE_IMASK; - gc->pipe[pn].shader.cur_tex = tex->pt->texture; - gc->pipe[pn].shader.cur_texm = texm->pt->texture; - gc->pipe[pn].shader.cur_prog = prog; - gc->pipe[pn].shader.smooth = smooth; - gc->pipe[pn].shader.blend = blend; - gc->pipe[pn].shader.render_op = gc->dc->render_op; - gc->pipe[pn].shader.clip = 0; - gc->pipe[pn].shader.cx = 0; - gc->pipe[pn].shader.cy = 0; - gc->pipe[pn].shader.cw = 0; - gc->pipe[pn].shader.ch = 0; - gc->pipe[pn].array.line = 0; - gc->pipe[pn].array.use_vertex = 1; - // if nomul... dont need this - gc->pipe[pn].array.use_color = 1; - gc->pipe[pn].array.use_texuv = 1; - gc->pipe[pn].array.use_texuv2 = 0; - gc->pipe[pn].array.use_texuv3 = 0; - gc->pipe[pn].array.use_texm = 1; - } - else - { - int found = 0; - - for (i = pn; i >= 0; i--) - { - if ((gc->pipe[i].region.type == RTYPE_IMASK) - && (gc->pipe[i].shader.cur_tex == tex->pt->texture) - && (gc->pipe[i].shader.cur_texm == texm->pt->texture) - && (gc->pipe[i].shader.cur_prog == prog) - && (gc->pipe[i].shader.smooth == smooth) - && (gc->pipe[i].shader.blend == blend) - && (gc->pipe[i].shader.render_op == gc->dc->render_op) - && (gc->pipe[i].shader.clip == 0) - ) - { - found = 1; - pn = i; - break; - } - if (pipe_region_intersects(gc, i, x, y, w, h)) break; - } - if (!found) - { - pn = gc->state.top_pipe + 1; - if (pn >= gc->shared->info.tune.pipes.max) - { - shader_array_flush(gc); - goto again; - } - gc->state.top_pipe = pn; - gc->pipe[pn].region.type = RTYPE_IMASK; - gc->pipe[pn].shader.cur_tex = tex->pt->texture; - gc->pipe[pn].shader.cur_texm = texm->pt->texture; - gc->pipe[pn].shader.cur_prog = prog; - gc->pipe[pn].shader.smooth = smooth; - gc->pipe[pn].shader.blend = blend; - gc->pipe[pn].shader.render_op = gc->dc->render_op; - gc->pipe[pn].shader.clip = 0; - gc->pipe[pn].shader.cx = 0; - gc->pipe[pn].shader.cy = 0; - gc->pipe[pn].shader.cw = 0; - gc->pipe[pn].shader.ch = 0; - gc->pipe[pn].array.line = 0; - gc->pipe[pn].array.use_vertex = 1; - gc->pipe[pn].array.use_color = 1; - gc->pipe[pn].array.use_texuv = 1; - gc->pipe[pn].array.use_texuv2 = 0; - gc->pipe[pn].array.use_texuv3 = 0; - gc->pipe[pn].array.use_texm = 1; - - } - } - if ((tex->im) && (tex->im->native.data)) - { - if (gc->pipe[pn].array.im != tex->im) - { - shader_array_flush(gc); - pn = gc->state.top_pipe; - gc->pipe[pn].array.im = tex->im; - goto again; - } - } - if (tex->pt->dyn.img) - { - if (gc->pipe[pn].array.im != tex->im) - { - shader_array_flush(gc); - pn = gc->state.top_pipe; - gc->pipe[pn].array.im = tex->im; - goto again; - } - } -#else - if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture) - || (gc->pipe[pn].shader.cur_prog != prog) - || (gc->pipe[pn].shader.smooth != smooth) - || (gc->pipe[pn].shader.blend != blend) - || (gc->pipe[pn].shader.render_op != gc->dc->render_op) - || (gc->pipe[pn].shader.clip != 0) - ) - { - shader_array_flush(gc); - gc->pipe[pn].shader.cur_tex = tex->pt->texture; - gc->pipe[pn].shader.cur_texm = texm->pt->texture; - gc->pipe[pn].shader.cur_prog = prog; - gc->pipe[pn].shader.smooth = smooth; - gc->pipe[pn].shader.blend = blend; - gc->pipe[pn].shader.render_op = gc->dc->render_op; - gc->pipe[pn].shader.clip = 0; - gc->pipe[pn].shader.cx = 0; - gc->pipe[pn].shader.cy = 0; - gc->pipe[pn].shader.cw = 0; - gc->pipe[pn].shader.ch = 0; - } - if ((tex->im) && (tex->im->native.data)) - { - if (gc->pipe[pn].array.im != tex->im) - { - shader_array_flush(gc); - gc->pipe[pn].array.im = tex->im; - } - } - if (tex->pt->dyn.img) - { - if (gc->pipe[pn].array.im != tex->im) - { - shader_array_flush(gc); - gc->pipe[pn].array.im = tex->im; - } - } + pn = _evas_gl_common_context_push(RTYPE_IMASK, + gc, tex, texm, + prog, + x, y, w, h, + blend, + smooth, + 0, 0, 0, 0, 0); + gc->pipe[pn].region.type = RTYPE_IMASK; + gc->pipe[pn].shader.cur_tex = tex->pt->texture; + gc->pipe[pn].shader.cur_texm = texm->pt->texture; + gc->pipe[pn].shader.cur_prog = prog; + gc->pipe[pn].shader.smooth = smooth; + gc->pipe[pn].shader.blend = blend; + gc->pipe[pn].shader.render_op = gc->dc->render_op; + gc->pipe[pn].shader.clip = 0; + gc->pipe[pn].shader.cx = 0; + gc->pipe[pn].shader.cy = 0; + gc->pipe[pn].shader.cw = 0; + gc->pipe[pn].shader.ch = 0; gc->pipe[pn].array.line = 0; gc->pipe[pn].array.use_vertex = 1; + // if nomul... dont need this gc->pipe[pn].array.use_color = 1; gc->pipe[pn].array.use_texuv = 1; gc->pipe[pn].array.use_texuv2 = 0; gc->pipe[pn].array.use_texuv3 = 0; gc->pipe[pn].array.use_texm = 1; -#endif pipe_region_expand(gc, pn, x, y, w, h); @@ -1852,15 +1749,13 @@ evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc, int pnum, nv, nc, nu, nu2, nu3, nt, i; GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2; Eina_Bool blend = 0; - GLuint prog = gc->shared->shader[SHADER_YUV].prog; + GLuint prog; int pn = 0; if (a < 255) blend = 1; - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - prog = gc->shared->shader[SHADER_YUV_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_YUV].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a, + SHADER_YUV_NOMUL, SHADER_YUV)].prog; pn = _evas_gl_common_context_push(RTYPE_YUV, gc, tex, NULL, @@ -1957,15 +1852,13 @@ evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc, int pnum, nv, nc, nu, nu2, nu3, nt, i; GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2; Eina_Bool blend = 0; - GLuint prog = gc->shared->shader[SHADER_YUY2].prog; + GLuint prog; int pn = 0; if (a < 255) blend = 1; - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - prog = gc->shared->shader[SHADER_YUY2_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_YUY2].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a, + SHADER_YUY2_NOMUL, SHADER_YUY2)].prog; pn = _evas_gl_common_context_push(RTYPE_YUY2, gc, tex, NULL, @@ -2049,9 +1942,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, RGBA_Map_Point *p, int clip, int cx, int cy, int cw, int ch, int r, int g, int b, int a, - Eina_Bool smooth, Eina_Bool tex_only, - Eina_Bool yuv, - Eina_Bool yuy2) + Eina_Bool smooth, Eina_Bool tex_only, + Evas_Colorspace cspace) { int pnum, nv, nc, nu, nu2, nu3, nt, i; const int points[6] = { 0, 1, 2, 0, 2, 3 }; @@ -2060,6 +1952,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, Eina_Bool blend = 1; DATA32 cmul; GLuint prog = gc->shared->shader[SHADER_IMG].prog; + Eina_Bool utexture = EINA_FALSE; + Eina_Bool uvtexture = EINA_FALSE; int pn = 0; int flat = 0; @@ -2084,94 +1978,56 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, { if (p[0].foc <= 0) flat = 1; } - if (yuv) + + switch (cspace) { - prog = gc->shared->shader[SHADER_YUV].prog; - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - { - if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && - (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) - prog = gc->shared->shader[SHADER_YUV_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_YUV].prog; - } - else - prog = gc->shared->shader[SHADER_YUV].prog; - } - else if (yuy2) - { - prog = gc->shared->shader[SHADER_YUY2].prog; - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - { - if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && - (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) - prog = gc->shared->shader[SHADER_YUY2_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_YUY2].prog; - } - else - prog = gc->shared->shader[SHADER_YUY2].prog; - } - else - { - if (tex_only) - { - if (tex->pt->dyn.img) - { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - { - if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && - (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) - prog = gc->shared->shader[SHADER_IMG_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_IMG].prog; - } - else - prog = gc->shared->shader[SHADER_IMG].prog; - } + case EVAS_COLORSPACE_YCBCR422P601_PL: + case EVAS_COLORSPACE_YCBCR422P709_PL: + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_YUV_NOMUL, SHADER_YUV)].prog; + utexture = EINA_TRUE; + break; + case EVAS_COLORSPACE_YCBCR422601_PL: + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_YUY2_NOMUL, SHADER_YUY2)].prog; + uvtexture = EINA_TRUE; + break; + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_NV12_NOMUL, SHADER_NV12)].prog; + uvtexture = EINA_TRUE; + break; + + default: + if (tex_only) + { + if (tex->pt->dyn.img) + { + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_IMG_NOMUL, SHADER_IMG)].prog; + } + else + { + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_TEX_NOMUL, SHADER_TEX)].prog; + } + } + else + { + if (tex->gc->shared->info.bgra) + { + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_IMG_BGRA_NOMUL, + SHADER_IMG_BGRA)].prog; + } else { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - { - if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && - (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) - prog = gc->shared->shader[SHADER_TEX_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_TEX].prog; - } - else - prog = gc->shared->shader[SHADER_TEX].prog; + prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a, + SHADER_IMG_NOMUL, + SHADER_IMG)].prog; } - } - else - { - if (tex->gc->shared->info.bgra) - { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - { - if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && - (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) - prog = gc->shared->shader[SHADER_IMG_BGRA_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_IMG_BGRA].prog; - } - else - prog = gc->shared->shader[SHADER_IMG_BGRA].prog; - } - else - { - if ((a == 255) && (r == 255) && (g == 255) && (b == 255)) - { - if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) && - (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff)) - prog = gc->shared->shader[SHADER_IMG_NOMUL].prog; - else - prog = gc->shared->shader[SHADER_IMG].prog; - } - else - prog = gc->shared->shader[SHADER_IMG].prog; - } - } + } } x = w = (p[points[0]].x >> FP); @@ -2188,11 +2044,16 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, py = (p[points[i]].y >> FP); if (py < y) y = py; else if (py > h) h = py; - if (yuv || yuy2) + if (utexture) { t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptu->w; t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptu->h; } + else if (uvtexture) + { + t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptuv->w; + t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptuv->h; + } } w = w - x; h = h - y; @@ -2230,12 +2091,12 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, gc->pipe[pn].region.type = RTYPE_MAP; gc->pipe[pn].shader.cur_tex = tex->pt->texture; - if (yuv) + if (utexture) { gc->pipe[pn].shader.cur_texu = tex->ptu->texture; gc->pipe[pn].shader.cur_texv = tex->ptv->texture; } - else if (yuy2) + else if (uvtexture) { gc->pipe[pn].shader.cur_texu = tex->ptuv->texture; } @@ -2252,8 +2113,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, gc->pipe[pn].array.use_vertex = 1; gc->pipe[pn].array.use_color = 1; gc->pipe[pn].array.use_texuv = 1; - gc->pipe[pn].array.use_texuv2 = (yuv || yuy2) ? 1 : 0; - gc->pipe[pn].array.use_texuv3 = (yuv) ? 1 : 0; + gc->pipe[pn].array.use_texuv2 = (utexture || uvtexture) ? 1 : 0; + gc->pipe[pn].array.use_texuv3 = (utexture) ? 1 : 0; pipe_region_expand(gc, pn, x, y, w, h); @@ -2268,7 +2129,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, for (i = 0; i < 4; i++) { ty[i] = 1.0 - ty[i]; - if (yuv || yuy2) + if (utexture || uvtexture) t2y[i] = 1.0 - t2y[i]; } } @@ -2295,7 +2156,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, PUSH_TEXUV(pn, tx[points[i]], ty[points[i]]); - if (yuv) + if (utexture) { PUSH_TEXUV2(pn, t2x[points[i]], @@ -2304,7 +2165,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, t2x[points[i]], t2y[points[i]]); } - else if (yuy2) + else if (uvtexture) { PUSH_TEXUV2(pn, t2x[points[i]], diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c index a7b5b6be15..1c3d64c4c6 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c @@ -578,6 +578,40 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im) } if (!im->tex) return; break; + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + if ((im->tex) && (im->dirty)) + { + evas_gl_common_texture_nv12_update(im->tex, im->cs.data, + im->im->cache_entry.w, + im->im->cache_entry.h); + im->dirty = 0; + } + if ((!im->tex) && (im->cs.data) && (*((unsigned char **)im->cs.data))) + { + im->tex = evas_gl_common_texture_nv12_new(gc, im->cs.data, + im->im->cache_entry.w, + im->im->cache_entry.h); + im->dirty = 0; + } + if (!im->tex) return; + break; + case EVAS_COLORSPACE_YCBCR420TM12601_PL: + if ((im->tex) && (im->dirty)) + { + evas_gl_common_texture_nv12tiled_update(im->tex, im->cs.data, + im->im->cache_entry.w, + im->im->cache_entry.h); + im->dirty = 0; + } + if ((!im->tex) && (im->cs.data) && (*((unsigned char **)im->cs.data))) + { + im->tex = evas_gl_common_texture_nv12tiled_new(gc, im->cs.data, + im->im->cache_entry.w, + im->im->cache_entry.h); + im->dirty = 0; + } + if (!im->tex) return; + break; default: ERR("unhandled img format colorspace=%d", im->cs.space); break; @@ -613,15 +647,11 @@ evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, cx = gc->dc->clip.x; cy = gc->dc->clip.y; cw = gc->dc->clip.w; ch = gc->dc->clip.h; im->tex->im = im; - if ((im->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || - (im->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) - yuv = 1; - if (im->cs.space == EVAS_COLORSPACE_YCBCR422601_PL) - yuy2 = 1; + evas_gl_common_context_image_map_push(gc, im->tex, npoints, p, c, cx, cy, cw, ch, r, g, b, a, smooth, im->tex_only, - yuv, yuy2); + im->cs.space); } void diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c index 239f209e10..5f05c009d2 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c @@ -200,6 +200,45 @@ Evas_GL_Program_Source shader_yuy2_nomul_vert_src = #endif }; +///////////////////////////////////////////// +#if defined (GLES_VARIETY_S3C6410) +const unsigned int nv12_nomul_vert_bin[] = +{ +# include "shader/nv12_nomul_vert_bin_s3c6410.h" +}; +#endif +const char nv12_nomul_vert_glsl[] = +#include "shader/nv12_nomul_vert.h" + ; +Evas_GL_Program_Source shader_nv12_nomul_vert_src = +{ + nv12_nomul_vert_glsl, +#if defined (GLES_VARIETY_S3C6410) + nv12_nomul_vert_bin, sizeof(nv12_nomul_vert_bin) +#else + NULL, 0 +#endif +}; + +#if defined (GLES_VARIETY_S3C6410) +const unsigned int nv12_vert_bin[] = +{ +# include "shader/nv12_vert_bin_s3c6410.h" +}; +#endif +const char nv12_vert_glsl[] = +#include "shader/nv12_vert.h" + ; +Evas_GL_Program_Source shader_nv12_vert_src = +{ + nv12_vert_glsl, +#if defined (GLES_VARIETY_S3C6410) + nv12_vert_bin, sizeof(nv12_vert_bin) +#else + NULL, 0 +#endif +}; + ///////////////////////////////////////////// #if defined (GLES_VARIETY_S3C6410) const unsigned int yuv_nomul_frag_bin[] = @@ -1029,6 +1068,8 @@ static const struct { SHADER_SOURCE_LINE(YUV_NOMUL, yuv_nomul), SHADER_SOURCE_LINE(YUY2, yuy2), SHADER_SOURCE_LINE(YUY2_NOMUL, yuy2_nomul), + { SHADER_NV12, &(shader_nv12_vert_src), &(shader_yuy2_frag_src), "nv12" }, + { SHADER_NV12_NOMUL, &(shader_nv12_nomul_vert_src), &(shader_yuy2_nomul_frag_src), "nv12_nomul" }, SHADER_SOURCE_LINE(TEX, tex), SHADER_SOURCE_LINE(TEX_NOMUL, tex_nomul), /* Most of the filters use the image fragment shader */ diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c index e92b141fd3..95c720e54c 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c @@ -1067,8 +1067,10 @@ evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned i } } -Evas_GL_Texture * -evas_gl_common_texture_yuy2_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h) +static Evas_GL_Texture * +_evas_gl_common_texture_y2uv_new(Evas_Engine_GL_Context *gc, + unsigned int yw, unsigned int yh, + unsigned int uvw, unsigned int uvh) { Evas_GL_Texture *tex; @@ -1077,7 +1079,7 @@ evas_gl_common_texture_yuy2_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsign tex->gc = gc; tex->references = 1; - tex->pt = _pool_tex_new(gc, w + 1, h + 1, lum_alpha_ifmt, lum_alpha_fmt); + tex->pt = _pool_tex_new(gc, yw + 1, yh + 1, lum_alpha_ifmt, lum_alpha_fmt); if (!tex->pt) { free(tex); @@ -1087,7 +1089,7 @@ evas_gl_common_texture_yuy2_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsign tex->pt->slot = -1; tex->pt->fslot = -1; tex->pt->whole = 1; - tex->ptuv = _pool_tex_new(gc, (w / 2) + 1, h + 1, rgba8_ifmt, rgba8_fmt); + tex->ptuv = _pool_tex_new(gc, uvw + 1, uvh + 1, rgba8_ifmt, rgba8_fmt); if (!tex->ptuv) { pt_unref(tex->pt); @@ -1100,38 +1102,50 @@ evas_gl_common_texture_yuy2_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsign tex->ptuv->whole = 1; tex->x = 0; tex->y = 0; - tex->w = w; - tex->h = h; + tex->w = yw; + tex->h = yh; tex->pt->allocations = eina_list_prepend(tex->pt->allocations, tex); tex->ptuv->allocations = eina_list_prepend(tex->ptuv->allocations, tex); tex->pt->references++; tex->ptuv->references++; + return tex; +} + +Evas_GL_Texture * +evas_gl_common_texture_yuy2_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h) +{ + Evas_GL_Texture *tex; + + tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h); evas_gl_common_texture_yuy2_update(tex, rows, w, h); return tex; } +Evas_GL_Texture * +evas_gl_common_texture_nv12_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h) +{ + Evas_GL_Texture *tex; + + tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h / 2); + evas_gl_common_texture_nv12_update(tex, rows, w, h); + return tex; +} + +Evas_GL_Texture * +evas_gl_common_texture_nv12tiled_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h) +{ + Evas_GL_Texture *tex; + + tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h / 2); + evas_gl_common_texture_nv12tiled_update(tex, rows, w, h); + return tex; +} + void evas_gl_common_texture_yuy2_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned int w, unsigned int h) { if (!tex->pt) return; // FIXME: works on lowest size 4 pixel high buffers. must also be multiple of 2 -#undef GL_UNPACK_ROW_LENGTH -#ifdef GL_UNPACK_ROW_LENGTH - glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[1] - rows[0]); - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - glBindTexture(GL_TEXTURE_2D, tex->pt->texture); - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - fprintf(stderr, "rows: %p\n", rows[0]); - fprintf(stderr, "rows end: %p\n", rows[h - 1] + (rows[1] - rows[0])); - _tex_sub_2d(0, 0, w, h, tex->pt->format, tex->pt->dataformat, rows[0]); - glBindTexture(GL_TEXTURE_2D, tex->ptuv->texture); - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[1] - rows[0]); - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - _tex_sub_2d(0, 0, w / 2, h, tex->ptuv->format, tex->ptuv->dataformat, rows[0]); -#else unsigned int y; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -1156,6 +1170,55 @@ evas_gl_common_texture_yuy2_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned _tex_sub_2d(0, y, w / 2, 1, tex->ptuv->format, tex->ptuv->dataformat, rows[y]); } + if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex) + { + glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + } +} + +void +evas_gl_common_texture_nv12_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned int w, unsigned int h) +{ + if (!tex->pt) return; + // FIXME: works on lowest size 4 pixel high buffers. must also be multiple of 2 +#ifdef GL_UNPACK_ROW_LENGTH + glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[1] - rows[0]); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glBindTexture(GL_TEXTURE_2D, tex->pt->texture); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + _tex_sub_2d(0, 0, w, h, tex->pt->format, tex->pt->dataformat, rows[0]); + glBindTexture(GL_TEXTURE_2D, tex->ptuv->texture); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[h + 1] - rows[h]); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + _tex_sub_2d(0, 0, w / 2, h / 2, tex->ptuv->format, tex->ptuv->dataformat, rows[h]); +#else + unsigned int y; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + glBindTexture(GL_TEXTURE_2D, tex->pt->texture); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + if ((rows[1] - rows[0]) == (int)w) + _tex_sub_2d(0, 0, w, h, tex->pt->format, tex->pt->dataformat, rows[0]); + else + { + for (y = 0; y < h; y++) + _tex_sub_2d(0, y, w, 1, tex->pt->format, tex->pt->dataformat, rows[y]); + } + + glBindTexture(GL_TEXTURE_2D, tex->ptuv->texture); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + if ((rows[h + 1] - rows[h]) == (int)(w / 2)) + _tex_sub_2d(0, 0, w / 2, h / 2, tex->ptuv->format, tex->ptuv->dataformat, rows[h]); + else + { + for (y = 0; y < (h / 2); y++) + _tex_sub_2d(0, y, w / 2, 1, tex->ptuv->format, tex->ptuv->dataformat, rows[h + y]); + } #endif if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex) { @@ -1163,3 +1226,11 @@ evas_gl_common_texture_yuy2_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned GLERR(__FUNCTION__, __FILE__, __LINE__, ""); } } + +void +evas_gl_common_texture_nv12tiled_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned int w, unsigned int h) +{ + if (!tex->pt) return; + // FIXME: not done yet + abort(); +} diff --git a/legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.h b/legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.h new file mode 100644 index 0000000000..3227065353 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.h @@ -0,0 +1,14 @@ +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"attribute vec4 vertex;\n" +"attribute vec4 color;\n" +"attribute vec2 tex_coord, tex_coord2;\n" +"uniform mat4 mvp;\n" +"varying vec2 tex_c, tex_cuv;\n" +"void main()\n" +"{\n" +" gl_Position = mvp * vertex;\n" +" tex_c = tex_coord;\n" +" tex_cuv = tex_coord2;\n" +"}\n" diff --git a/legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.shd b/legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.shd new file mode 100644 index 0000000000..e2412ade4c --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/nv12_nomul_vert.shd @@ -0,0 +1,14 @@ +#ifdef GL_ES +precision mediump float; +#endif +attribute vec4 vertex; +attribute vec4 color; +attribute vec2 tex_coord, tex_coord2; +uniform mat4 mvp; +varying vec2 tex_y, tex_cuv; +void main() +{ + gl_Position = mvp * vertex; + tex_y = tex_coord; + tex_cuv = tex_coord2; +} diff --git a/legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.h b/legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.h new file mode 100644 index 0000000000..0cb908edcd --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.h @@ -0,0 +1,16 @@ +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"attribute vec4 vertex;\n" +"attribute vec4 color;\n" +"attribute vec2 tex_coord, tex_coord2;\n" +"uniform mat4 mvp;\n" +"varying vec4 col;\n" +"varying vec2 tex_c, tex_cuv;\n" +"void main()\n" +"{\n" +" gl_Position = mvp * vertex;\n" +" col = color;\n" +" tex_c = tex_coord;\n" +" tex_cuv = tex_coord2;\n" +"}\n" diff --git a/legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.shd b/legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.shd new file mode 100644 index 0000000000..76eb533925 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/nv12_vert.shd @@ -0,0 +1,16 @@ +#ifdef GL_ES +precision mediump float; +#endif +attribute vec4 vertex; +attribute vec4 color; +attribute vec2 tex_coord, tex_coord2; +uniform mat4 mvp; +varying vec4 col; +varying vec2 tex_y, tex_cuv; +void main() +{ + gl_Position = mvp * vertex; + col = color; + tex_y = tex_coord; + tex_cuv = tex_coord2; +} diff --git a/legacy/evas/src/modules/engines/gl_common/shader/yuy2_frag.shd b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_frag.shd new file mode 100644 index 0000000000..64cd911af3 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_frag.shd @@ -0,0 +1,26 @@ +#ifdef GL_ES +precision mediump float; +#endif +uniform sampler2D tex, texuv; +varying vec4 col; +varying vec2 tex_c, tex_cuv; +void main() +{ + float y,u,v,vmu,r,g,b; + y=texture2D(tex,tex_c).r; + u=texture2D(texuv,tex_cuv).g; + v=texture2D(texuv,tex_cuv).a; + + u=u-0.5; + v=v-0.5; + vmu=v*0.813+u*0.391; + u=u*2.018; + v=v*1.596; + + r=y+v; + g=y-vmu; + b=y+u; + + gl_FragColor=vec4(r,g,b,1.0) * col; +} + diff --git a/legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_frag.shd b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_frag.shd new file mode 100644 index 0000000000..2a8d2ed973 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_frag.shd @@ -0,0 +1,26 @@ +#ifdef GL_ES +precision mediump float; +#endif +uniform sampler2D tex, texuv; +varying vec2 tex_c, tex_cuv; +void main() +{ + float y,u,v,vmu,r,g,b; + y=texture2D(tex,tex_c).r; + u=texture2D(texuv,tex_cuv).g; + v=texture2D(texuv,tex_cuv).a; + + u=u-0.5; + v=v-0.5; + vmu=v*0.813+u*0.391; + u=u*2.018; + v=v*1.596; + y=(y-0.062)*1.164; + + r=y+v; + g=y-vmu; + b=y+u; + + gl_FragColor=vec4(r,g,b,1.0); +} + diff --git a/legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_vert.shd b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_vert.shd new file mode 100644 index 0000000000..ee3fd89db8 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_nomul_vert.shd @@ -0,0 +1,13 @@ +#ifdef GL_ES +precision mediump float; +#endif +attribute vec4 vertex; +attribute vec2 tex_coord, tex_coord2; +uniform mat4 mvp; +varying vec2 tex_c, tex_cuv; +void main() +{ + gl_Position = mvp * vertex; + tex_c = tex_coord; + tex_cuv = vec2(tex_coord2.x * 0.5, tex_coord2.y); +} diff --git a/legacy/evas/src/modules/engines/gl_common/shader/yuy2_vert.shd b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_vert.shd new file mode 100644 index 0000000000..879e15ce22 --- /dev/null +++ b/legacy/evas/src/modules/engines/gl_common/shader/yuy2_vert.shd @@ -0,0 +1,16 @@ +#ifdef GL_ES +precision mediump float; +#endif +attribute vec4 vertex; +attribute vec4 color; +attribute vec2 tex_coord, tex_coord2; +uniform mat4 mvp; +varying vec4 col; +varying vec2 tex_c, tex_cuv; +void main() +{ + gl_Position = mvp * vertex; + col = color; + tex_c = tex_coord; + tex_cuv = vec2(tex_coord2.x * 0.5, tex_coord2.y); +} diff --git a/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c b/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c index 3134270fdd..332438a9c2 100644 --- a/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_sdl/evas_engine.c @@ -468,6 +468,8 @@ eng_image_colorspace_set(void *data, void *image, int cspace) case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: if (im->tex) evas_gl_common_texture_free(im->tex); im->tex = NULL; if (im->cs.data) @@ -599,10 +601,18 @@ eng_image_size_set(void *data, void *image, int w, int h) return image; } im_old = image; - if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) || - (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL) || - (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422601_PL)) - w &= ~0x1; + + switch (eng_image_colorspace_get(data, image)) + { + case EVAS_COLORSPACE_YCBCR422P601_PL: + case EVAS_COLORSPACE_YCBCR422P709_PL: + case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: + w &= ~0x1; + break; + } + if ((im_old) && (im_old->im->cache_entry.w == w) && (im_old->im->cache_entry.h == h)) return image; if (im_old) @@ -689,6 +699,8 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: *image_data = im->cs.data; break; default: @@ -729,6 +741,8 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data) case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: if (image_data != im->cs.data) { if (im->cs.data) diff --git a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c index d440c23ea2..16a7643f2b 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -1065,6 +1065,8 @@ eng_image_colorspace_set(void *data, void *image, int cspace) case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: if (im->tex) evas_gl_common_texture_free(im->tex); im->tex = NULL; if (im->cs.data) @@ -1708,10 +1710,18 @@ eng_image_size_set(void *data, void *image, int w, int h) return image; } im_old = image; - if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) || - (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL) || - (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422601_PL)) - w &= ~0x1; + + switch (eng_image_colorspace_get(data, image)) + { + case EVAS_COLORSPACE_YCBCR422P601_PL: + case EVAS_COLORSPACE_YCBCR422P709_PL: + case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: + w &= ~0x1; + break; + } + if ((im_old) && ((int)im_old->im->cache_entry.w == w) && ((int)im_old->im->cache_entry.h == h)) @@ -1842,6 +1852,8 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: *image_data = im->cs.data; break; default: @@ -1908,6 +1920,8 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data) case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: if (image_data != im->cs.data) { if (im->cs.data) diff --git a/legacy/evas/src/modules/engines/software_generic/evas_engine.c b/legacy/evas/src/modules/engines/software_generic/evas_engine.c index 966366569a..ceed58a280 100644 --- a/legacy/evas/src/modules/engines/software_generic/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_generic/evas_engine.c @@ -434,6 +434,8 @@ eng_image_data_get(void *data __UNUSED__, void *image, int to_write, DATA32 **im case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: *image_data = im->cs.data; break; default: @@ -470,6 +472,8 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data) case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: case EVAS_COLORSPACE_YCBCR422601_PL: + case EVAS_COLORSPACE_YCBCR420NV12601_PL: + case EVAS_COLORSPACE_YCBCR420TM12601_PL: if (image_data != im->cs.data) { if (im->cs.data)