#define RTYPE_MAP 5 /* need to merge with image */
#define RTYPE_IMASK 6
#define RTYPE_YUY2 7
-
+#define RTYPE_NV12 8
struct _Evas_Engine_GL_Context
{
}
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)
+{
+ int pnum, nv, nc, nu, nu2, nu3, nt, i;
+ GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
+ Eina_Bool blend = 0;
+ GLuint prog;
+ int pn = 0;
+
+ if (a < 255) blend = 1;
+
+ prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+ SHADER_NV12_NOMUL, SHADER_NV12)].prog;
+
+ pn = _evas_gl_common_context_push(RTYPE_NV12,
+ gc, tex, NULL,
+ prog,
+ x, y, w, h,
+ blend,
+ smooth,
+ 0, 0, 0, 0, 0);
+
+ gc->pipe[pn].region.type = RTYPE_NV12;
+ gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+ gc->pipe[pn].shader.cur_texu = tex->ptuv->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 = 1;
+ gc->pipe[pn].array.use_texuv3 = 0;
+
+ pipe_region_expand(gc, pn, x, y, w, h);
+
+ pnum = gc->pipe[pn].array.num;
+ nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
+ nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
+ gc->pipe[pn].array.num += 6;
+ array_alloc(gc, pn);
+
+ tx1 = (sx) / (double)tex->pt->w;
+ ty1 = (sy) / (double)tex->pt->h;
+ tx2 = (sx + sw) / (double)tex->pt->w;
+ ty2 = (sy + sh) / (double)tex->pt->h;
+
+ t2x1 = sx / (double)tex->ptuv->w;
+ t2y1 = sy / (double)tex->ptuv->h;
+ t2x2 = (sx + sw) / (double)tex->ptuv->w;
+ t2y2 = (sy + sh) / (double)tex->ptuv->h;
+
+ PUSH_VERTEX(pn, x , y , 0);
+ PUSH_VERTEX(pn, x + w, y , 0);
+ PUSH_VERTEX(pn, x , y + h, 0);
+
+ PUSH_TEXUV(pn, tx1, ty1);
+ PUSH_TEXUV(pn, tx2, ty1);
+ PUSH_TEXUV(pn, tx1, ty2);
+
+ PUSH_TEXUV2(pn, t2x1, t2y1);
+ PUSH_TEXUV2(pn, t2x2, t2y1);
+ PUSH_TEXUV2(pn, t2x1, t2y2);
+
+ PUSH_VERTEX(pn, x + w, y , 0);
+ PUSH_VERTEX(pn, x + w, y + h, 0);
+ PUSH_VERTEX(pn, x , y + h, 0);
+
+ PUSH_TEXUV(pn, tx2, ty1);
+ PUSH_TEXUV(pn, tx2, ty2);
+ PUSH_TEXUV(pn, tx1, ty2);
+
+ PUSH_TEXUV2(pn, t2x2, t2y1);
+ PUSH_TEXUV2(pn, t2x2, t2y2);
+ PUSH_TEXUV2(pn, t2x1, t2y2);
+
+ for (i = 0; i < 6; i++)
+ {
+ PUSH_COLOR(pn, r, g, b, a);
+ }
+}
+
+void
evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
int npoints,
break;
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;
im->cs.no_free = 0;
RGBA_Draw_Context *dc;
int r, g, b, a;
int c, cx, cy, cw, ch;
- Eina_Bool yuv = 0;
- Eina_Bool yuy2 = 0;
dc = gc->dc;
if (dc->mul.use)
int i;
int yuv = 0;
int yuy2 = 0;
+ int nv12 = 0;
if (sw < 1) sw = 1;
if (sh < 1) sh = 1;
yuv = 1;
if (im->cs.space == EVAS_COLORSPACE_YCBCR422601_PL)
yuy2 = 1;
+ if ((im->cs.space == EVAS_COLORSPACE_YCBCR420NV12601_PL) ||
+ (im->cs.space == EVAS_COLORSPACE_YCBCR420TM12601_PL))
+ nv12 = 1;
im->tex->im = im;
if (imm) imm->tex->im = imm;
dx, dy, dw, dh,
r, g, b, a,
smooth);
+ else if (nv12)
+ evas_gl_common_context_nv12_push(gc,
+ im->tex,
+ sx, sy, sw, sh,
+ dx, dy, dw, dh,
+ r, g, b, a,
+ smooth);
else
evas_gl_common_context_image_push(gc,
nx, ny, nw, nh,
r, g, b, a,
smooth);
+ else if (nv12)
+ evas_gl_common_context_nv12_push(gc,
+ im->tex,
+ ssx, ssy, ssw, ssh,
+ nx, ny, nw, nh,
+ r, g, b, a,
+ smooth);
else
evas_gl_common_context_image_push(gc,
im->tex,
dx, dy, dw, dh,
r, g, b, a,
smooth);
+ else if (nv12)
+ evas_gl_common_context_nv12_push(gc,
+ im->tex,
+ sx, sy, sw, sh,
+ dx, dy, dw, dh,
+ r, g, b, a,
+ smooth);
else
evas_gl_common_context_image_push(gc,
im->tex,
dx, dy, dw, dh,
r, g, b, a,
smooth);
+ else if (nv12)
+ evas_gl_common_context_nv12_push(gc,
+ im->tex,
+ sx, sy, sw, sh,
+ dx, dy, dw, dh,
+ r, g, b, a,
+ smooth);
else
evas_gl_common_context_image_push(gc,
im->tex,
nx, ny, nw, nh,
r, g, b, a,
smooth);
+ else if (nv12)
+ evas_gl_common_context_nv12_push(gc,
+ im->tex,
+ ssx, ssy, ssw, ssh,
+ nx, ny, nw, nh,
+ r, g, b, a,
+ smooth);
else
evas_gl_common_context_image_push(gc,
im->tex,
#endif
};
+#if defined (GLES_VARIETY_S3C6410)
+const unsigned int nv12_nomul_frag_bin[] =
+{
+# include "shader/nv12_nomul_frag_bin_s3c6410.h"
+};
+#endif
+
+const char nv12_frag_glsl[] =
+#include "shader/nv12_frag.h"
+ ;
+Evas_GL_Program_Source shader_nv12_frag_src =
+{
+ nv12_frag_glsl,
+#if defined (GLES_VARIETY_S3C6410)
+ nv12_frag_bin, sizeof(nv12_frag_bin)
+#else
+ NULL, 0
+#endif
+};
+
+#if defined (GLES_VARIETY_S3C6410)
+const unsigned int nv12_nomul_frag_bin[] =
+{
+# include "shader/nv12_nomul_frag_bin_s3c6410.h"
+};
+#endif
+
+const char nv12_nomul_frag_glsl[] =
+#include "shader/nv12_nomul_frag.h"
+ ;
+Evas_GL_Program_Source shader_nv12_nomul_frag_src =
+{
+ nv12_nomul_frag_glsl,
+#if defined (GLES_VARIETY_S3C6410)
+ nv12_nomul_frag_bin, sizeof(nv12_nomul_frag_bin)
+#else
+ NULL, 0
+#endif
+};
+
/////////////////////////////////////////////
#if defined (GLES_VARIETY_S3C6410)
const unsigned int yuv_nomul_frag_bin[] =
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(NV12, nv12),
+ SHADER_SOURCE_LINE(NV12_NOMUL, nv12_nomul),
SHADER_SOURCE_LINE(TEX, tex),
SHADER_SOURCE_LINE(TEX_NOMUL, tex_nomul),
/* Most of the filters use the image fragment shader */
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)
+ unsigned int uvw, unsigned int uvh,
+ GLenum y_ifmt, GLenum y_fmt,
+ GLenum uv_ifmt, GLenum uv_fmt)
{
Evas_GL_Texture *tex;
tex->gc = gc;
tex->references = 1;
- tex->pt = _pool_tex_new(gc, yw + 1, yh + 1, lum_alpha_ifmt, lum_alpha_fmt);
+ tex->pt = _pool_tex_new(gc, yw + 1, yh + 1, y_ifmt, y_fmt);
if (!tex->pt)
{
free(tex);
tex->pt->slot = -1;
tex->pt->fslot = -1;
tex->pt->whole = 1;
- tex->ptuv = _pool_tex_new(gc, uvw + 1, uvh + 1, rgba8_ifmt, rgba8_fmt);
+ tex->ptuv = _pool_tex_new(gc, uvw + 1, uvh + 1, uv_ifmt, uv_fmt);
if (!tex->ptuv)
{
pt_unref(tex->pt);
{
Evas_GL_Texture *tex;
- tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h);
+ tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h, lum_alpha_ifmt, lum_alpha_fmt, rgba8_ifmt, rgba8_fmt);
evas_gl_common_texture_yuy2_update(tex, rows, w, h);
return tex;
}
{
Evas_GL_Texture *tex;
- tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h / 2);
+ tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h / 2, alpha_ifmt, alpha_fmt, lum_alpha_ifmt, lum_alpha_fmt);
evas_gl_common_texture_nv12_update(tex, rows, w, h);
return tex;
}
{
Evas_GL_Texture *tex;
- tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h / 2);
+ tex = _evas_gl_common_texture_y2uv_new(gc, w, h, w / 2, h / 2, alpha_ifmt, alpha_fmt, lum_alpha_ifmt, lum_alpha_fmt);
evas_gl_common_texture_nv12tiled_update(tex, rows, w, h);
return tex;
}
void
evas_gl_common_texture_nv12tiled_update(Evas_GL_Texture *tex, DATA8 **rows, unsigned int w, unsigned int h)
{
+ unsigned int mb_x, mb_y, mb_w, mb_h;
+ unsigned int base_h;
+
if (!tex->pt) return;
- // FIXME: not done yet
- abort();
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+ glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
+ GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+ mb_w = w / 64;
+ mb_h = h / 32;
+
+ /* Iterate each Y macroblock like we do in evas_convert_yuv.c */
+ for (mb_y = 0; mb_y < (mb_h >> 1); mb_y++)
+ {
+ int step = 2;
+ int offset = 0;
+ int x = 0;
+ int rmb_x = 0;
+ int ry[2];
+
+ ry[0] = mb_y * 2 * 32;
+ ry[1] = ry[0] + 32;
+
+ for (mb_x = 0; mb_x < mb_w * 2; mb_x++, rmb_x += 64 * 32)
+ {
+ _tex_sub_2d(x, ry[offset], 64, 32, tex->pt->format, tex->pt->dataformat, rows[mb_y] + rmb_x);
+
+ step++;
+ if ((step & 0x3) == 0)
+ {
+ offset = 1 - offset;
+ x -= 64;
+ }
+ else
+ {
+ x += 64;
+ }
+ }
+ }
+
+ if (mb_h & 0x1)
+ {
+ int rmb_x = 0;
+ int x = 0;
+ int ry;
+
+ ry = mb_y * 2 * 32;
+
+ for (mb_x = 0; mb_x < mb_w; mb_x++, x += 64, rmb_x += 64 * 32)
+ _tex_sub_2d(x, ry, 64, 32, tex->pt->format, tex->pt->dataformat, rows[mb_y] + rmb_x);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, tex->ptuv->texture);
+ GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+ /* Iterate each UV macroblock like we do in evas_convert_yuv.c */
+ base_h = (mb_h >> 1) + (mb_h & 0x1);
+ for (mb_y = 0; mb_y < (mb_h >> 2); mb_y++)
+ {
+ int step = 2;
+ int offset = 0;
+ int x = 0;
+ int rmb_x = 0;
+ int ry[2];
+
+ ry[0] = mb_y * 2 * 32;
+ ry[1] = ry[0] + 32;
+
+ for (mb_x = 0; mb_x < mb_w * 2; mb_x++, rmb_x += 64 * 32)
+ {
+ _tex_sub_2d(x, ry[offset], 32, 32,
+ tex->ptuv->format, tex->ptuv->dataformat,
+ rows[mb_y + base_h] + rmb_x);
+
+ step++;
+ if ((step & 0x3) == 0)
+ {
+ offset = 1 - offset;
+ x -= 32;
+ }
+ else
+ {
+ x += 32;
+ }
+ }
+ }
+
+ if (mb_h & 0x1)
+ {
+ int rmb_x = 0;
+ int x = 0;
+ int ry;
+
+ ry = mb_y * 2 * 32;
+
+ for (mb_x = 0; mb_x < mb_w; mb_x++, x += 32, rmb_x += 64 * 32)
+ _tex_sub_2d(x, ry, 64, 32, tex->ptuv->format, tex->ptuv->dataformat, rows[mb_y + base_h] + rmb_x);
+ }
}
--- /dev/null
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"uniform sampler2D tex, texuv;\n"
+"varying vec4 col;\n"
+"varying vec2 tex_c, tex_cuv;\n"
+"void main()\n"
+"{\n"
+" float y,u,v,vmu,r,g,b;\n"
+" y=texture2D(tex,tex_c).a;\n"
+" u=texture2D(texuv,tex_cuv).g;\n"
+" v=texture2D(texuv,tex_cuv).a;\n"
+
+" u=u-0.5;\n"
+" v=v-0.5;\n"
+" vmu=v*0.813+u*0.391;\n"
+" u=u*2.018;\n"
+" v=v*1.596;\n"
+" y=(y-0.062)*1.164;\n"
+
+" r=y+v;\n"
+" g=y-vmu;\n"
+" b=y+u;\n"
+
+" gl_FragColor=vec4(r,g,b,1.0) * col;\n"
+"}\n"
+
--- /dev/null
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"uniform sampler2D tex, texuv;\n"
+"varying vec2 tex_c, tex_cuv;\n"
+"void main()\n"
+"{\n"
+" float y,u,v,vmu,r,g,b;\n"
+" y=texture2D(tex,tex_c).a;\n"
+" u=texture2D(texuv,tex_cuv).g;\n"
+" v=texture2D(texuv,tex_cuv).a;\n"
+
+" u=u-0.5;\n"
+" v=v-0.5;\n"
+" vmu=v*0.813+u*0.391;\n"
+" u=u*2.018;\n"
+" v=v*1.596;\n"
+" y=(y-0.062)*1.164;\n"
+
+" r=y+v;\n"
+" g=y-vmu;\n"
+" b=y+u;\n"
+
+" gl_FragColor=vec4(r,g,b,1.0);\n"
+"}\n"
+
"{\n"
" gl_Position = mvp * vertex;\n"
" tex_c = tex_coord;\n"
-" tex_cuv = tex_coord2;\n"
+" tex_cuv = tex_coord2 * 0.5;\n"
"}\n"
" gl_Position = mvp * vertex;\n"
" col = color;\n"
" tex_c = tex_coord;\n"
-" tex_cuv = tex_coord2;\n"
+" tex_cuv = tex_coord2 * 0.5;\n"
"}\n"