From 91d8220be91e855c331f36af35393e89f821ca49 Mon Sep 17 00:00:00 2001 From: raster Date: Sat, 10 Oct 2009 13:24:15 +0000 Subject: [PATCH] yuv support is back now. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@43000 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/modules/engines/gl_common/evas_gl_common.h | 54 +++--- src/modules/engines/gl_common/evas_gl_context.c | 190 +++++++++++++++++---- src/modules/engines/gl_common/evas_gl_image.c | 81 +++++++-- src/modules/engines/gl_common/evas_gl_shader.c | 42 +++++ src/modules/engines/gl_common/evas_gl_texture.c | 77 ++++++++- .../engines/gl_common/shader/compile-s3c6410.sh | 1 + .../engines/gl_common/shader/compile-sgx.sh | 1 + src/modules/engines/gl_common/shader/yuv_frag.h | 19 +++ src/modules/engines/gl_common/shader/yuv_frag.shd | 19 +++ src/modules/engines/gl_common/shader/yuv_vert.h | 16 ++ src/modules/engines/gl_common/shader/yuv_vert.shd | 16 ++ 11 files changed, 448 insertions(+), 68 deletions(-) create mode 100644 src/modules/engines/gl_common/shader/yuv_frag.h create mode 100644 src/modules/engines/gl_common/shader/yuv_frag.shd create mode 100644 src/modules/engines/gl_common/shader/yuv_vert.h create mode 100644 src/modules/engines/gl_common/shader/yuv_vert.shd diff --git a/src/modules/engines/gl_common/evas_gl_common.h b/src/modules/engines/gl_common/evas_gl_common.h index 8fca477..1202034 100644 --- a/src/modules/engines/gl_common/evas_gl_common.h +++ b/src/modules/engines/gl_common/evas_gl_common.h @@ -41,6 +41,8 @@ #define SHAD_VERTEX 0 #define SHAD_COLOR 1 #define SHAD_TEXUV 2 +#define SHAD_TEXUV2 3 +#define SHAD_TEXUV3 4 typedef struct _Evas_GL_Program Evas_GL_Program; typedef struct _Evas_GL_Program_Source Evas_GL_Program_Source; @@ -49,14 +51,13 @@ typedef struct _Evas_GL_Texture_Pool Evas_GL_Texture_Pool; typedef struct _Evas_GL_Texture Evas_GL_Texture; typedef struct _Evas_GL_Image Evas_GL_Image; typedef struct _Evas_GL_Font_Texture Evas_GL_Font_Texture; - - - +/* typedef struct _Evas_GL_Polygon Evas_GL_Polygon; typedef struct _Evas_GL_Polygon_Point Evas_GL_Polygon_Point; typedef struct _Evas_GL_Gradient Evas_GL_Gradient; typedef struct _Evas_GL_Font_Texture_Pool Evas_GL_Font_Texture_Pool; typedef struct _Evas_GL_Font_Texture_Pool_Allocation Evas_GL_Font_Texture_Pool_Allocation; +*/ struct _Evas_GL_Program { @@ -96,9 +97,15 @@ struct _Evas_GL_Context struct { Evas_GL_Program rect, img, font, yuv; GLuint cur_prog; - GLuint cur_tex; + GLuint cur_tex, cur_texu, cur_texv; Eina_Bool smooth : 1; Eina_Bool blend : 1; + struct { + GLuint cur_prog; + GLuint cur_tex, cur_texum, cur_texv; + Eina_Bool smooth : 1; + Eina_Bool blend : 1; + } current; } shader; struct { int num; @@ -106,6 +113,8 @@ struct _Evas_GL_Context GLint *vertex; GLfloat *color; GLfloat *texuv; + GLfloat *texuv2; + GLfloat *texuv3; } array; struct { Eina_Bool size : 1; @@ -128,7 +137,7 @@ struct _Evas_GL_Texture_Pool struct _Evas_GL_Texture { Evas_GL_Context *gc; - Evas_GL_Texture_Pool *pt; + Evas_GL_Texture_Pool *pt, *ptu, *ptv; int x, y, w, h; int references; }; @@ -153,12 +162,7 @@ struct _Evas_GL_Font_Texture { Evas_GL_Texture *tex; }; - - - - - - +/* struct _Evas_GL_Polygon { Eina_List *points; @@ -186,6 +190,7 @@ struct _Evas_GL_Font_Texture_Pool GLuint texture; unsigned char rectangle : 1; }; +*/ extern Evas_GL_Program_Source shader_rect_frag_src; extern Evas_GL_Program_Source shader_rect_vert_src; @@ -193,6 +198,8 @@ extern Evas_GL_Program_Source shader_img_frag_src; extern Evas_GL_Program_Source shader_img_vert_src; extern Evas_GL_Program_Source shader_font_frag_src; extern Evas_GL_Program_Source shader_font_vert_src; +extern Evas_GL_Program_Source shader_yuv_frag_src; +extern Evas_GL_Program_Source shader_yuv_vert_src; void glerr(const char *file, const char *func, int line, const char *op); @@ -215,6 +222,12 @@ void evas_gl_common_context_font_push(Evas_GL_Context *gc, double sx, double sy, double sw, double sh, int x, int y, int w, int h, int r, int g, int b, int a); +void evas_gl_common_context_yuv_push(Evas_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_flush(Evas_GL_Context *gc); void evas_gl_common_shader_program_init(Evas_GL_Program *p, @@ -228,7 +241,9 @@ void evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image void evas_gl_common_texture_free(Evas_GL_Texture *tex); Evas_GL_Texture *evas_gl_common_texture_alpha_new(Evas_GL_Context *gc, DATA8 *pixels, int w, int h, int fh); void evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA8 *pixels, int w, int h, int fh); - +Evas_GL_Texture *evas_gl_common_texture_yuv_new(Evas_GL_Context *gc, DATA8 **rows, int w, int h); +void evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, int w, int h); + Evas_GL_Image *evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo); Evas_GL_Image *evas_gl_common_image_new_from_data(Evas_GL_Context *gc, int w, int h, DATA32 *data, int alpha, int cspace); Evas_GL_Image *evas_gl_common_image_new_from_copied_data(Evas_GL_Context *gc, int w, int h, DATA32 *data, int alpha, int cspace); @@ -260,7 +275,7 @@ void evas_gl_font_texture_draw(Evas_GL_Context *gc, void *surface, - +/* Evas_GL_Polygon *evas_gl_common_poly_point_add(Evas_GL_Polygon *poly, int x, int y); Evas_GL_Polygon *evas_gl_common_poly_points_clear(Evas_GL_Polygon *poly); @@ -289,17 +304,6 @@ void evas_gl_common_swap_rect(Evas_GL_Context *gc, int x, int y, in void evas_gl_common_line_draw(Evas_GL_Context *gc, int x1, int y1, int x2, int y2); void evas_gl_common_poly_draw(Evas_GL_Context *gc, Evas_GL_Polygon *poly); - - -/* FIXME: - * - * for images: - * speculative cache for textures too - * texture mesh support - * - * for text/fonts: - * need to not render to a texture each time.... this is sloooooow. - * but its a "bootstrap" for just right now. - */ +*/ #endif diff --git a/src/modules/engines/gl_common/evas_gl_context.c b/src/modules/engines/gl_common/evas_gl_context.c index 480f5f1..c23f78a 100644 --- a/src/modules/engines/gl_common/evas_gl_context.c +++ b/src/modules/engines/gl_common/evas_gl_context.c @@ -98,6 +98,10 @@ evas_gl_common_context_new(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16); #endif + glEnableVertexAttribArray(SHAD_VERTEX); + glEnableVertexAttribArray(SHAD_COLOR); + glEnableVertexAttribArray(SHAD_TEXUV); + evas_gl_common_shader_program_init(&(gc->shader.rect), &(shader_rect_vert_src), &(shader_rect_frag_src)); @@ -107,6 +111,13 @@ evas_gl_common_context_new(void) evas_gl_common_shader_program_init(&(gc->shader.font), &(shader_font_vert_src), &(shader_font_frag_src)); + evas_gl_common_shader_program_init(&(gc->shader.yuv), + &(shader_yuv_vert_src), + &(shader_yuv_frag_src)); + glUseProgram(gc->shader.yuv.prog); + glUniform1i(glGetUniformLocation(gc->shader.yuv.prog, "tex"), 0); + glUniform1i(glGetUniformLocation(gc->shader.yuv.prog, "texu"), 1); + glUniform1i(glGetUniformLocation(gc->shader.yuv.prog, "texv"), 2); _evas_gl_common_viewport_set(gc); gc->checked = 1; } @@ -155,23 +166,33 @@ evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h) #define PUSH_TEXUV(u, v) \ gc->array.texuv[nu++] = u; \ gc->array.texuv[nu++] = v +#define PUSH_TEXUV2(u, v) \ + gc->array.texuv2[nu2++] = u; \ + gc->array.texuv2[nu2++] = v +#define PUSH_TEXUV3(u, v) \ + gc->array.texuv3[nu3++] = u; \ + gc->array.texuv3[nu3++] = v #define COLOR_FLOAT(r, g, b, a, fr, fg, fb, fa) \ fr = ((GLfloat)(r)) / 255.0; \ fg = ((GLfloat)(g)) / 255.0; \ fb = ((GLfloat)(b)) / 255.0; \ fa = ((GLfloat)(a)) / 255.0 -static void +static inline void _evas_gl_common_context_array_alloc(Evas_GL_Context *gc) { if (gc->array.num <= gc->array.alloc) return; - gc->array.alloc += 1024; + gc->array.alloc += 6 * 1024; gc->array.vertex = realloc(gc->array.vertex, gc->array.alloc * sizeof(GLint) * 3); gc->array.color = realloc(gc->array.color, gc->array.alloc * sizeof(GLfloat) * 4); gc->array.texuv = realloc(gc->array.texuv, gc->array.alloc * sizeof(GLfloat) * 2); + gc->array.texuv2 = realloc(gc->array.texuv2, + gc->array.alloc * sizeof(GLfloat) * 2); + gc->array.texuv3 = realloc(gc->array.texuv3, + gc->array.alloc * sizeof(GLfloat) * 2); } void @@ -337,6 +358,90 @@ evas_gl_common_context_font_push(Evas_GL_Context *gc, } void +evas_gl_common_context_yuv_push(Evas_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 rr, gg, bb, aa, tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2; + Eina_Bool blend = 0; + + if (a < 255) blend = 1; + + if ((gc->shader.cur_tex != tex->pt->texture) + || (gc->shader.cur_prog != gc->shader.yuv.prog) + || (gc->shader.smooth != smooth) + || (gc->shader.blend != blend) + ) + { + shader_array_flush(gc); + gc->shader.cur_tex = tex->pt->texture; + gc->shader.cur_texu = tex->ptu->texture; + gc->shader.cur_texv = tex->ptv->texture; + gc->shader.cur_prog = gc->shader.yuv.prog; + gc->shader.smooth = smooth; + gc->shader.blend = blend; + } + + pnum = gc->array.num; + nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; + nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4; + gc->array.num += 6; + _evas_gl_common_context_array_alloc(gc); + + 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->ptu->w; + t2y1 = (sy) / (double)tex->ptu->h; + t2x2 = (sx + sw) / (double)tex->ptu->w; + t2y2 = (sy + sh) / (double)tex->ptu->h; + + PUSH_VERTEX(x , y , 0); + PUSH_VERTEX(x + w, y , 0); + PUSH_VERTEX(x , y + h, 0); + + PUSH_TEXUV(tx1, ty1); + PUSH_TEXUV(tx2, ty1); + PUSH_TEXUV(tx1, ty2); + + PUSH_TEXUV2(t2x1, t2y1); + PUSH_TEXUV2(t2x2, t2y1); + PUSH_TEXUV2(t2x1, t2y2); + + PUSH_TEXUV3(t2x1, t2y1); + PUSH_TEXUV3(t2x2, t2y1); + PUSH_TEXUV3(t2x1, t2y2); + + PUSH_VERTEX(x + w, y , 0); + PUSH_VERTEX(x + w, y + h, 0); + PUSH_VERTEX(x , y + h, 0); + + PUSH_TEXUV(tx2, ty1); + PUSH_TEXUV(tx2, ty2); + PUSH_TEXUV(tx1, ty2); + + PUSH_TEXUV2(t2x2, t2y1); + PUSH_TEXUV2(t2x2, t2y2); + PUSH_TEXUV2(t2x1, t2y2); + + PUSH_TEXUV3(t2x2, t2y1); + PUSH_TEXUV3(t2x2, t2y2); + PUSH_TEXUV3(t2x1, t2y2); + + COLOR_FLOAT(r, g, b, a, rr, gg, bb, aa); + for (i = 0; i < 6; i++) + { + PUSH_COLOR(rr, gg, bb, aa); + } +} + +void evas_gl_common_context_flush(Evas_GL_Context *gc) { shader_array_flush(gc); @@ -349,58 +454,80 @@ shader_array_flush(Evas_GL_Context *gc) if (gc->array.num <= 0) return; // fprintf(stderr, " flush array %i\n", gc->array.num); - glUseProgram(gc->shader.cur_prog); - - if (gc->shader.cur_tex) + if (gc->shader.cur_prog != gc->shader.current.cur_prog) + glUseProgram(gc->shader.cur_prog); + + if (gc->shader.cur_tex != gc->shader.current.cur_tex) { glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex); } - else + if (gc->shader.blend != gc->shader.current.blend) { - glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex); + if (gc->shader.blend) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); } - if (gc->shader.blend) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); - if (gc->shader.smooth) + if (gc->shader.smooth != gc->shader.current.smooth) { + if (gc->shader.smooth) + { #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16); #endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else - { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + else + { #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); #endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } } - - glEnableVertexAttribArray(SHAD_VERTEX); + glVertexAttribPointer(SHAD_VERTEX, 3, GL_INT, GL_FALSE, 0, gc->array.vertex); - - glEnableVertexAttribArray(SHAD_COLOR); glVertexAttribPointer(SHAD_COLOR, 4, GL_FLOAT, GL_FALSE, 0, gc->array.color); - - glEnableVertexAttribArray(SHAD_TEXUV); glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv); + if ((gc->array.texuv2) && (gc->array.texuv3)) + { + glEnableVertexAttribArray(SHAD_TEXUV2); + glEnableVertexAttribArray(SHAD_TEXUV3); + glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv2); + glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv3); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, gc->shader.cur_texu); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, gc->shader.cur_texv); + } + else + { + glDisableVertexAttribArray(SHAD_TEXUV2); + glDisableVertexAttribArray(SHAD_TEXUV3); + } glDrawArrays(GL_TRIANGLES, 0, gc->array.num); - - gc->shader.cur_prog = 0; - gc->shader.cur_tex = 0; + + gc->shader.current.cur_prog = gc->shader.cur_prog; + gc->shader.current.cur_tex = gc->shader.cur_tex; + gc->shader.current.blend = gc->shader.blend; + gc->shader.current.smooth = gc->shader.smooth; free(gc->array.vertex); free(gc->array.color); free(gc->array.texuv); + free(gc->array.texuv2); + free(gc->array.texuv3); gc->array.vertex = NULL; gc->array.color = NULL; gc->array.texuv = NULL; + gc->array.texuv2 = NULL; + gc->array.texuv3 = NULL; gc->array.num = 0; gc->array.alloc = 0; @@ -455,4 +582,7 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc) glUseProgram(gc->shader.font.prog); glUniformMatrix4fv(glGetUniformLocation(gc->shader.font.prog, "mvp"), 1, GL_FALSE, proj); + glUseProgram(gc->shader.yuv.prog); + glUniformMatrix4fv(glGetUniformLocation(gc->shader.yuv.prog, "mvp"), 1, + GL_FALSE, proj); } diff --git a/src/modules/engines/gl_common/evas_gl_image.c b/src/modules/engines/gl_common/evas_gl_image.c index 435f5d0..f1b12a1 100644 --- a/src/modules/engines/gl_common/evas_gl_image.c +++ b/src/modules/engines/gl_common/evas_gl_image.c @@ -195,6 +195,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy Cutout_Rect *rct; int c, cx, cy, cw, ch; int i; + int yuv = 0; if (sw < 1) sw = 1; if (sh < 1) sh = 1; @@ -210,7 +211,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy { r = g = b = a = 255; } - +/* if ((im->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) || (im->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL)) { @@ -230,6 +231,7 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy space = EVAS_COLORSPACE_ARGB8888; } else + */ space = im->cs.space; switch (space) @@ -243,10 +245,27 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy } if (!im->tex) im->tex = evas_gl_common_texture_new(gc, im->im); + if (!im->tex) return; break; case EVAS_COLORSPACE_YCBCR422P601_PL: case EVAS_COLORSPACE_YCBCR422P709_PL: - break; + if ((im->tex) && (im->dirty)) + { + evas_gl_common_texture_yuv_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_yuv_new(gc, im->cs.data, + im->im->cache_entry.w, + im->im->cache_entry.h); + im->dirty = 0; + } + yuv = 1; + if (!im->tex) return; + break; default: printf("unhandled img format\n"); break; @@ -267,12 +286,20 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy if ((nw < 1) || (nh < 1)) return; if ((nx == dx) && (ny == dy) && (nw == dw) && (nh == dh)) { - evas_gl_common_context_image_push(gc, + if (yuv) + evas_gl_common_context_yuv_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, + sx, sy, sw, sh, + dx, dy, dw, dh, + r, g, b, a, + smooth); return; } @@ -280,21 +307,37 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy ssy = (double)sy + ((double)(sh * (ny - dy)) / (double)(dh)); ssw = ((double)sw * (double)(nw)) / (double)(dw); ssh = ((double)sh * (double)(nh)) / (double)(dh); - evas_gl_common_context_image_push(gc, + if (yuv) + evas_gl_common_context_yuv_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, + ssx, ssy, ssw, ssh, + nx, ny, nw, nh, + r, g, b, a, + smooth); } else { - evas_gl_common_context_image_push(gc, + if (yuv) + evas_gl_common_context_yuv_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, + sx, sy, sw, sh, + dx, dy, dw, dh, + r, g, b, a, + smooth); } return; } @@ -320,24 +363,40 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy if ((nw < 1) || (nh < 1)) continue; if ((nx == dx) && (ny == dy) && (nw == dw) && (nh == dh)) { - evas_gl_common_context_image_push(gc, - im->tex, - sx, sy, sw, sh, - dx, dy, dw, dh, + if (yuv) + evas_gl_common_context_yuv_push(gc, + im->tex, + sx, sy, sw, sh, + dx, dy, dw, dh, r, g, b, a, - smooth); + smooth); + else + evas_gl_common_context_image_push(gc, + im->tex, + sx, sy, sw, sh, + dx, dy, dw, dh, + r, g, b, a, + smooth); continue; } ssx = (double)sx + ((double)(sw * (nx - dx)) / (double)(dw)); ssy = (double)sy + ((double)(sh * (ny - dy)) / (double)(dh)); ssw = ((double)sw * (double)(nw)) / (double)(dw); ssh = ((double)sh * (double)(nh)) / (double)(dh); - evas_gl_common_context_image_push(gc, + if (yuv) + evas_gl_common_context_yuv_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, + ssx, ssy, ssw, ssh, + nx, ny, nw, nh, + r, g, b, a, + smooth); } evas_common_draw_context_apply_clear_cutouts(rects); /* restore clip info */ diff --git a/src/modules/engines/gl_common/evas_gl_shader.c b/src/modules/engines/gl_common/evas_gl_shader.c index e45341a..ca7f121 100644 --- a/src/modules/engines/gl_common/evas_gl_shader.c +++ b/src/modules/engines/gl_common/evas_gl_shader.c @@ -120,6 +120,46 @@ Evas_GL_Program_Source shader_font_vert_src = #endif }; +///////////////////////////////////////////// +#if defined (GLES_VARIETY_S3C6410) +const unsigned int yuv_frag_bin[] = +{ +# include "shader/yuv_frag_bin.h" +}; +#endif + +const char yuv_frag_glsl[] = +#include "shader/yuv_frag.h" + ; +Evas_GL_Program_Source shader_yuv_frag_src = +{ + yuv_frag_glsl, +#if defined (GLES_VARIETY_S3C6410) + yuv_frag_bin, sizeof(yuv_frag_bin_end) +#else + NULL, 0 +#endif +}; + +#if defined (GLES_VARIETY_S3C6410) +const unsigned int yuv_frag_bin[] = +{ +# include "shader/yuv_vert_bin.h" +}; +#endif +const char yuv_vert_glsl[] = +#include "shader/yuv_vert.h" + ; +Evas_GL_Program_Source shader_yuv_vert_src = +{ + yuv_vert_glsl, +#if defined (GLES_VARIETY_S3C6410) + yuv_vert_bin, sizeof(yuv_vert_bin) +#else + NULL, 0 +#endif +}; + @@ -174,6 +214,8 @@ evas_gl_common_shader_program_init(Evas_GL_Program *p, glBindAttribLocation(p->prog, SHAD_VERTEX, "vertex"); glBindAttribLocation(p->prog, SHAD_COLOR, "color"); glBindAttribLocation(p->prog, SHAD_TEXUV, "tex_coord"); + glBindAttribLocation(p->prog, SHAD_TEXUV2, "tex_coord2"); + glBindAttribLocation(p->prog, SHAD_TEXUV3, "tex_coord3"); glLinkProgram(p->prog); glGetProgramiv(p->prog, GL_LINK_STATUS, &ok); diff --git a/src/modules/engines/gl_common/evas_gl_texture.c b/src/modules/engines/gl_common/evas_gl_texture.c index 484c14d..3b80cc0 100644 --- a/src/modules/engines/gl_common/evas_gl_texture.c +++ b/src/modules/engines/gl_common/evas_gl_texture.c @@ -44,6 +44,8 @@ _tex_format_index(GLuint format) return 1; case GL_ALPHA: return 2; + case GL_LUMINANCE: + return 3; default: break; } @@ -68,7 +70,7 @@ _pool_tex_new(Evas_GL_Context *gc, int w, int h, GLuint format) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, - format, GL_UNSIGNED_BYTE, NULL); + format, GL_UNSIGNED_BYTE/* fixme - pass this in */, NULL); glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex); return pt; } @@ -204,7 +206,7 @@ evas_gl_common_texture_new(Evas_GL_Context *gc, RGBA_Image *im) void evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im) { -#ifdef defined(GL_UNSIGNED_INT_8_8_8_8_REV) && defined(GL_BGRA) +#if defined(GL_UNSIGNED_INT_8_8_8_8_REV) && defined(GL_BGRA) #define COLOR_FORMAT GL_RGBA #define PIXEL_FORMAT GL_UNSIGNED_BYTE // FIXME: need to change shader for this to work @@ -215,6 +217,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im) #define PIXEL_FORMAT GL_UNSIGNED_BYTE #endif glBindTexture(GL_TEXTURE_2D, tex->pt->texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // +-+ // +-+ @@ -338,6 +341,7 @@ void evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA8 *pixels, int w, int h, int fh) { glBindTexture(GL_TEXTURE_2D, tex->pt->texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexSubImage2D(GL_TEXTURE_2D, 0, tex->x, tex->y, w, h, @@ -348,3 +352,72 @@ evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA8 *pixels, int w, glBindTexture(GL_TEXTURE_2D, tex->gc->shader.cur_tex); } } + +Evas_GL_Texture * +evas_gl_common_texture_yuv_new(Evas_GL_Context *gc, DATA8 **rows, int w, int h) +{ + Evas_GL_Texture *tex; + Eina_List *l_after = NULL; + int u = 0, v = 0; + + tex = calloc(1, sizeof(Evas_GL_Texture)); + if (!tex) return NULL; + + tex->gc = gc; + tex->references = 1; + tex->pt = _pool_tex_new(gc, w + 1, h + 1, GL_LUMINANCE); + gc->tex.whole = eina_list_prepend(gc->tex.whole, tex->pt); + tex->pt->slot = -1; + tex->pt->fslot = -1; + tex->pt->whole = 1; + tex->ptu = _pool_tex_new(gc, (w / 2) + 1, (h / 2) + 1, GL_LUMINANCE); + gc->tex.whole = eina_list_prepend(gc->tex.whole, tex->ptu); + tex->ptu->slot = -1; + tex->ptu->fslot = -1; + tex->ptu->whole = 1; + tex->ptv = _pool_tex_new(gc, (w / 2) + 1, (h / 2) + 1, GL_LUMINANCE); + gc->tex.whole = eina_list_prepend(gc->tex.whole, tex->ptv); + tex->ptv->slot = -1; + tex->ptv->fslot = -1; + tex->ptv->whole = 1; + tex->x = 0; + tex->y = 0; + tex->w = w; + tex->h = h; + tex->pt->allocations = eina_list_prepend(tex->pt->allocations, tex); + tex->ptu->allocations = eina_list_prepend(tex->ptu->allocations, tex); + tex->ptv->allocations = eina_list_prepend(tex->ptv->allocations, tex); + tex->pt->references++; + tex->ptu->references++; + tex->ptv->references++; + evas_gl_common_texture_yuv_update(tex, rows, w, h); + return tex; +} + +void +evas_gl_common_texture_yuv_update(Evas_GL_Texture *tex, DATA8 **rows, int w, int h) +{ + glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[1] - rows[0]); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, tex->pt->texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, 0, w, h, + GL_LUMINANCE, GL_UNSIGNED_BYTE, + rows[0]); + glBindTexture(GL_TEXTURE_2D, tex->ptu->texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[h + 1] - rows[h]); + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, 0, w / 2, h / 2, + GL_LUMINANCE, GL_UNSIGNED_BYTE, + rows[h]); + glBindTexture(GL_TEXTURE_2D, tex->ptv->texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rows[h + (h / 2) + 1] - rows[h + (h / 2)]); + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, 0, w / 2, h / 2, + GL_LUMINANCE, GL_UNSIGNED_BYTE, + rows[h + (h / 2)]); + if (tex->pt->texture != tex->gc->shader.cur_tex) + { + glBindTexture(GL_TEXTURE_2D, tex->gc->shader.cur_tex); + } +} diff --git a/src/modules/engines/gl_common/shader/compile-s3c6410.sh b/src/modules/engines/gl_common/shader/compile-s3c6410.sh index de2e37e..af1c030 100755 --- a/src/modules/engines/gl_common/shader/compile-s3c6410.sh +++ b/src/modules/engines/gl_common/shader/compile-s3c6410.sh @@ -32,3 +32,4 @@ function compile() compile rect compile img compile font +compile yuv diff --git a/src/modules/engines/gl_common/shader/compile-sgx.sh b/src/modules/engines/gl_common/shader/compile-sgx.sh index ce2be80..4b23af7 100755 --- a/src/modules/engines/gl_common/shader/compile-sgx.sh +++ b/src/modules/engines/gl_common/shader/compile-sgx.sh @@ -10,3 +10,4 @@ function compile() compile rect compile img compile font +compile yuv diff --git a/src/modules/engines/gl_common/shader/yuv_frag.h b/src/modules/engines/gl_common/shader/yuv_frag.h new file mode 100644 index 0000000..cc3f1e5 --- /dev/null +++ b/src/modules/engines/gl_common/shader/yuv_frag.h @@ -0,0 +1,19 @@ +"uniform sampler2D tex, texu, texv;\n" +"varying vec4 col;\n" +"varying vec2 tex_c;\n" +"varying vec2 tex_c2;\n" +"varying vec2 tex_c3;\n" +"void main()\n" +"{\n" +" float r, g, b, y, u, v;\n" +" y = texture2D(tex, tex_c.xy).r;\n" +" u = texture2D(texu, tex_c2.xy).r;\n" +" v = texture2D(texv, tex_c3.xy).r;\n" +" y = (y - 0.0625) * 1.164;\n" +" u = u - 0.5;\n" +" v = v - 0.5;\n" +" r = y + (1.402 * v);\n" +" g = y - (0.34414 * u) - (0.71414 * v);\n" +" b = y + (1.772 * u);\n" +" gl_FragColor = vec4(r, g, b, 1.0) * col;\n" +"}\n" diff --git a/src/modules/engines/gl_common/shader/yuv_frag.shd b/src/modules/engines/gl_common/shader/yuv_frag.shd new file mode 100644 index 0000000..612470e --- /dev/null +++ b/src/modules/engines/gl_common/shader/yuv_frag.shd @@ -0,0 +1,19 @@ +uniform sampler2D tex, texu, texv; +varying vec4 col; +varying vec2 tex_c; +varying vec2 tex_c2; +varying vec2 tex_c3; +void main() +{ + float r, g, b, y, u, v; + y = texture2D(tex, tex_c.xy).r; + u = texture2D(texu, tex_c2.xy).r; + v = texture2D(texv, tex_c3.xy).r; + y = (y - 0.0625) * 1.164; + u = u - 0.5; + v = v - 0.5; + r = y + (1.402 * v); + g = y - (0.34414 * u) - (0.71414 * v); + b = y + (1.772 * u); + gl_FragColor = vec4(r, g, b, 1.0) * col; +} diff --git a/src/modules/engines/gl_common/shader/yuv_vert.h b/src/modules/engines/gl_common/shader/yuv_vert.h new file mode 100644 index 0000000..be803cd --- /dev/null +++ b/src/modules/engines/gl_common/shader/yuv_vert.h @@ -0,0 +1,16 @@ +"attribute vec4 vertex;\n" +"attribute vec4 color;\n" +"attribute vec2 tex_coord;\n" +"attribute vec2 tex_coord2;\n" +"attribute vec2 tex_coord3;\n" +"uniform mat4 mvp;\n" +"varying vec4 col;\n" +"varying vec4 tex_c;\n" +"void main()\n" +"{\n" +" gl_Position = mvp * vertex;\n" +" col = color;\n" +" tex_c = tex_coord;\n" +" tex_c2 = tex_coord2;\n" +" tex_c3 = tex_coord3;\n" +"}\n" diff --git a/src/modules/engines/gl_common/shader/yuv_vert.shd b/src/modules/engines/gl_common/shader/yuv_vert.shd new file mode 100644 index 0000000..60a969b --- /dev/null +++ b/src/modules/engines/gl_common/shader/yuv_vert.shd @@ -0,0 +1,16 @@ +attribute vec4 vertex; +attribute vec4 color; +attribute vec2 tex_coord; +attribute vec2 tex_coord2; +attribute vec2 tex_coord3; +uniform mat4 mvp; +varying vec4 col; +varying vec4 tex_c; +void main() +{ + gl_Position = mvp * vertex; + col = color; + tex_c = tex_coord; + tex_c2 = tex_coord2; + tex_c3 = tex_coord3; +} -- 2.7.4