diff options
author | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2014-07-04 17:37:21 +0400 |
---|---|---|
committer | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2014-08-19 12:36:03 +0400 |
commit | 8ef16bb3f7bdb29f74edeb87a0f292594c666baf (patch) | |
tree | dace9232c699704f5b6e2bfceb9be73d14a97dbe | |
parent | 6850615bbe0a496183e9639b498fe6cc8d7487dd (diff) | |
download | qemu-8ef16bb3f7bdb29f74edeb87a0f292594c666baf.tar.gz qemu-8ef16bb3f7bdb29f74edeb87a0f292594c666baf.tar.bz2 qemu-8ef16bb3f7bdb29f74edeb87a0f292594c666baf.zip |
VIGS: Support YUV420 planar format
Change-Id: If015f4e6fece5c2d1463c0428565ad3e46083a5d
Signed-off-by: Stanislav Vorobiov <s.vorobiov@samsung.com>
-rw-r--r-- | hw/vigs/vigs_gl_backend.c | 197 | ||||
-rw-r--r-- | hw/vigs/vigs_gl_backend.h | 14 | ||||
-rw-r--r-- | hw/vigs/vigs_protocol.h | 5 | ||||
-rw-r--r-- | hw/vigs/vigs_utils.c | 1 |
4 files changed, 213 insertions, 4 deletions
diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c index ba6baab2ab..17ebe3d8ea 100644 --- a/hw/vigs/vigs_gl_backend.c +++ b/hw/vigs/vigs_gl_backend.c @@ -278,6 +278,87 @@ static const char *g_fs_nv21_source_gl3 = " FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n" "}\n"; +static const char *g_vs_yuv420_source_gl2 = + "#version 120\n\n" + "attribute vec4 vertCoord;\n" + "uniform mat4 proj;\n" + "attribute vec2 texCoord;\n" + "varying vec2 v_texCoord;\n" + "void main()\n" + "{\n" + " v_texCoord = texCoord;\n" + " gl_Position = proj * vertCoord;\n" + "}\n"; + +static const char *g_vs_yuv420_source_gl3 = + "#version 140\n\n" + "in vec4 vertCoord;\n" + "uniform mat4 proj;\n" + "in vec2 texCoord;\n" + "out vec2 v_texCoord;\n" + "void main()\n" + "{\n" + " v_texCoord = texCoord;\n" + " gl_Position = proj * vertCoord;\n" + "}\n"; + +static const char *g_fs_yuv420_source_gl2 = + "#version 120\n\n" + "uniform sampler2D ytex;\n" + "uniform sampler2D utex;\n" + "uniform sampler2D vtex;\n" + "uniform vec2 size;\n" + "uniform vec2 ytexSize;\n" + "uniform vec2 utexSize;\n" + "uniform vec2 vtexSize;\n" + "varying vec2 v_texCoord;\n" + "void main()\n" + "{\n" + " float ypos = floor((1.0 - v_texCoord.y) * size.y) * size.x + floor(v_texCoord.x * size.x);\n" + " float ytexPos = floor(ypos / 4);\n" + " vec4 ytexColor = texture2D(ytex, vec2((mod(ytexPos, ytexSize.x) + 0.5) / ytexSize.x, 1.0 - (floor(ytexPos / ytexSize.x) + 0.5) / ytexSize.y));\n" + " float y = ytexColor[3 - int(mod(ypos + 1, 4))];\n" + " float uvpos = floor(floor((1.0 - v_texCoord.y) * size.y) / 2) * size.x + floor(v_texCoord.x * size.x);\n" + " float uvtexPos = floor(uvpos / 8);\n" + " vec4 utexColor = texture2D(utex, vec2((mod(uvtexPos, utexSize.x) + 0.5) / utexSize.x, 1.0 - (floor(uvtexPos / utexSize.x) + 0.5) / utexSize.y));\n" + " vec4 vtexColor = texture2D(vtex, vec2((mod(uvtexPos, vtexSize.x) + 0.5) / vtexSize.x, 1.0 - (floor(uvtexPos / vtexSize.x) + 0.5) / vtexSize.y));\n" + " int index = 3 - int(mod((uvpos / 2) + 1, 4));\n" + " float u = utexColor[index];\n" + " float v = vtexColor[index];\n" + " u -= 0.5;\n" + " v -= 0.5;\n" + " gl_FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n" + "}\n"; + +static const char *g_fs_yuv420_source_gl3 = + "#version 140\n\n" + "uniform sampler2D ytex;\n" + "uniform sampler2D utex;\n" + "uniform sampler2D vtex;\n" + "uniform vec2 size;\n" + "uniform vec2 ytexSize;\n" + "uniform vec2 utexSize;\n" + "uniform vec2 vtexSize;\n" + "in vec2 v_texCoord;\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " float ypos = floor((1.0 - v_texCoord.y) * size.y) * size.x + floor(v_texCoord.x * size.x);\n" + " float ytexPos = floor(ypos / 4);\n" + " vec4 ytexColor = texture2D(ytex, vec2((mod(ytexPos, ytexSize.x) + 0.5) / ytexSize.x, 1.0 - (floor(ytexPos / ytexSize.x) + 0.5) / ytexSize.y));\n" + " float y = ytexColor[3 - int(mod(ypos + 1, 4))];\n" + " float uvpos = floor(floor((1.0 - v_texCoord.y) * size.y) / 2) * size.x + floor(v_texCoord.x * size.x);\n" + " float uvtexPos = floor(uvpos / 8);\n" + " vec4 utexColor = texture2D(utex, vec2((mod(uvtexPos, utexSize.x) + 0.5) / utexSize.x, 1.0 - (floor(uvtexPos / utexSize.x) + 0.5) / utexSize.y));\n" + " vec4 vtexColor = texture2D(vtex, vec2((mod(uvtexPos, vtexSize.x) + 0.5) / vtexSize.x, 1.0 - (floor(uvtexPos / vtexSize.x) + 0.5) / vtexSize.y));\n" + " int index = 3 - int(mod((uvpos / 2) + 1, 4));\n" + " float u = utexColor[index];\n" + " float v = vtexColor[index];\n" + " u -= 0.5;\n" + " v -= 0.5;\n" + " FragColor = vec4(y + 1.59765625 * v, y - 0.390625 * u - 0.8125 * v, y + 2.015625 * u, 1.0);\n" + "}\n"; + static GLuint vigs_gl_backend_alloc_tmp_texture(void *user_data, uint32_t width, uint32_t height, @@ -533,7 +614,7 @@ static void vigs_gl_draw_color_prog(struct vigs_gl_backend *backend, backend->DisableVertexAttribArray(backend->color_prog_vertCoord_loc); } -static void vigs_gl_draw_nv12_prog(struct vigs_gl_backend *backend, +static void vigs_gl_draw_nv21_prog(struct vigs_gl_backend *backend, uint32_t count) { uint32_t size = count * 16; @@ -554,6 +635,27 @@ static void vigs_gl_draw_nv12_prog(struct vigs_gl_backend *backend, backend->DisableVertexAttribArray(backend->nv21_prog_vertCoord_loc); } +static void vigs_gl_draw_yuv420_prog(struct vigs_gl_backend *backend, + uint32_t count) +{ + uint32_t size = count * 16; + + vigs_gl_draw_update_vert_tex_buffer(backend, size); + + backend->EnableVertexAttribArray(backend->yuv420_prog_vertCoord_loc); + backend->EnableVertexAttribArray(backend->yuv420_prog_texCoord_loc); + + backend->VertexAttribPointer(backend->yuv420_prog_vertCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL); + backend->VertexAttribPointer(backend->yuv420_prog_texCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2)); + + backend->DrawArrays(GL_TRIANGLES, 0, count); + + backend->DisableVertexAttribArray(backend->yuv420_prog_texCoord_loc); + backend->DisableVertexAttribArray(backend->yuv420_prog_vertCoord_loc); +} + static void vigs_gl_create_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearf, GLfloat farf, @@ -1524,7 +1626,51 @@ static bool vigs_gl_backend_composite_planes(struct vigs_gl_backend *gl_backend, gl_backend->Uniform2f(gl_backend->nv21_prog_size_loc, src_w, src_h); - vigs_gl_draw_nv12_prog(gl_backend, 6); + vigs_gl_draw_nv21_prog(gl_backend, 6); + + gl_backend->UseProgram(gl_backend->tex_prog_id); + } else if (plane->format == vigsp_plane_yuv420) { + struct vigs_gl_surface *gl_sfc; + struct vigs_winsys_gl_surface *ws_sfc; + + gl_backend->UseProgram(gl_backend->yuv420_prog_id); + + gl_backend->UniformMatrix4fv(gl_backend->yuv420_prog_proj_loc, + 1, GL_FALSE, ortho); + + gl_sfc = (struct vigs_gl_surface*)plane->surfaces[2]; + ws_sfc = get_ws_sfc(gl_sfc); + + gl_backend->ActiveTexture(GL_TEXTURE2); + gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex); + + gl_backend->Uniform2f(gl_backend->yuv420_prog_vtexSize_loc, + ws_sfc->base.base.width, + ws_sfc->base.base.height); + + gl_sfc = (struct vigs_gl_surface*)plane->surfaces[1]; + ws_sfc = get_ws_sfc(gl_sfc); + + gl_backend->ActiveTexture(GL_TEXTURE1); + gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex); + + gl_backend->Uniform2f(gl_backend->yuv420_prog_utexSize_loc, + ws_sfc->base.base.width, + ws_sfc->base.base.height); + + gl_sfc = (struct vigs_gl_surface*)plane->surfaces[0]; + ws_sfc = get_ws_sfc(gl_sfc); + + gl_backend->ActiveTexture(GL_TEXTURE0); + gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex); + + gl_backend->Uniform2f(gl_backend->yuv420_prog_ytexSize_loc, + ws_sfc->base.base.width, + ws_sfc->base.base.height); + + gl_backend->Uniform2f(gl_backend->yuv420_prog_size_loc, src_w, src_h); + + vigs_gl_draw_yuv420_prog(gl_backend, 6); gl_backend->UseProgram(gl_backend->tex_prog_id); } else { @@ -1899,6 +2045,41 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) gl_backend->nv21_prog_ytex_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "ytex"); gl_backend->nv21_prog_ctex_loc = gl_backend->GetUniformLocation(gl_backend->nv21_prog_id, "ctex"); + gl_backend->yuv420_prog_vs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_vs_yuv420_source_gl2 : g_vs_yuv420_source_gl3), + GL_VERTEX_SHADER); + + if (!gl_backend->yuv420_prog_vs_id) { + goto fail; + } + + gl_backend->yuv420_prog_fs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_fs_yuv420_source_gl2 : g_fs_yuv420_source_gl3), + GL_FRAGMENT_SHADER); + + if (!gl_backend->yuv420_prog_fs_id) { + goto fail; + } + + gl_backend->yuv420_prog_id = vigs_gl_create_program(gl_backend, + gl_backend->yuv420_prog_vs_id, + gl_backend->yuv420_prog_fs_id); + + if (!gl_backend->yuv420_prog_id) { + goto fail; + } + + gl_backend->yuv420_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "proj"); + gl_backend->yuv420_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->yuv420_prog_id, "vertCoord"); + gl_backend->yuv420_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->yuv420_prog_id, "texCoord"); + gl_backend->yuv420_prog_size_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "size"); + gl_backend->yuv420_prog_ytexSize_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "ytexSize"); + gl_backend->yuv420_prog_utexSize_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "utexSize"); + gl_backend->yuv420_prog_vtexSize_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtexSize"); + gl_backend->yuv420_prog_ytex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "ytex"); + gl_backend->yuv420_prog_utex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "utex"); + gl_backend->yuv420_prog_vtex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtex"); + gl_backend->GenBuffers(1, &gl_backend->vbo); if (!gl_backend->vbo) { @@ -1912,6 +2093,11 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) gl_backend->Uniform1i(gl_backend->nv21_prog_ytex_loc, 0); gl_backend->Uniform1i(gl_backend->nv21_prog_ctex_loc, 1); + gl_backend->UseProgram(gl_backend->yuv420_prog_id); + gl_backend->Uniform1i(gl_backend->yuv420_prog_ytex_loc, 0); + gl_backend->Uniform1i(gl_backend->yuv420_prog_utex_loc, 1); + gl_backend->Uniform1i(gl_backend->yuv420_prog_vtex_loc, 2); + gl_backend->UseProgram(gl_backend->tex_prog_id); gl_backend->cur_prog_id = gl_backend->tex_prog_id; @@ -1952,6 +2138,13 @@ void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend) if (gl_backend->make_current(gl_backend, true)) { gl_backend->DeleteBuffers(1, &gl_backend->pbo); gl_backend->DeleteBuffers(1, &gl_backend->vbo); + gl_backend->DetachShader(gl_backend->yuv420_prog_id, + gl_backend->yuv420_prog_vs_id); + gl_backend->DetachShader(gl_backend->yuv420_prog_id, + gl_backend->yuv420_prog_fs_id); + gl_backend->DeleteShader(gl_backend->yuv420_prog_vs_id); + gl_backend->DeleteShader(gl_backend->yuv420_prog_fs_id); + gl_backend->DeleteProgram(gl_backend->yuv420_prog_id); gl_backend->DetachShader(gl_backend->nv21_prog_id, gl_backend->nv21_prog_vs_id); gl_backend->DetachShader(gl_backend->nv21_prog_id, diff --git a/hw/vigs/vigs_gl_backend.h b/hw/vigs/vigs_gl_backend.h index 72f663075c..bfa41101a6 100644 --- a/hw/vigs/vigs_gl_backend.h +++ b/hw/vigs/vigs_gl_backend.h @@ -194,6 +194,20 @@ struct vigs_gl_backend GLint nv21_prog_ytex_loc; GLint nv21_prog_ctex_loc; + GLuint yuv420_prog_vs_id; + GLuint yuv420_prog_fs_id; + GLuint yuv420_prog_id; + GLint yuv420_prog_proj_loc; + GLint yuv420_prog_vertCoord_loc; + GLint yuv420_prog_texCoord_loc; + GLint yuv420_prog_size_loc; + GLint yuv420_prog_ytexSize_loc; + GLint yuv420_prog_utexSize_loc; + GLint yuv420_prog_vtexSize_loc; + GLint yuv420_prog_ytex_loc; + GLint yuv420_prog_utex_loc; + GLint yuv420_prog_vtex_loc; + GLuint vbo; uint32_t vbo_size; diff --git a/hw/vigs/vigs_protocol.h b/hw/vigs/vigs_protocol.h index e4663d5a22..31a5eebdb7 100644 --- a/hw/vigs/vigs_protocol.h +++ b/hw/vigs/vigs_protocol.h @@ -37,7 +37,7 @@ /* * Bump this whenever protocol changes. */ -#define VIGS_PROTOCOL_VERSION 18 +#define VIGS_PROTOCOL_VERSION 19 #define VIGS_MAX_PLANES 2 @@ -99,7 +99,8 @@ typedef enum vigsp_plane_bgra8888 = 0x1, vigsp_plane_nv21 = 0x2, vigsp_plane_nv42 = 0x3, - vigsp_plane_nv61 = 0x4 + vigsp_plane_nv61 = 0x4, + vigsp_plane_yuv420 = 0x5 } vigsp_plane_format; #pragma pack(1) diff --git a/hw/vigs/vigs_utils.c b/hw/vigs/vigs_utils.c index bca7de6a34..0438d114a0 100644 --- a/hw/vigs/vigs_utils.c +++ b/hw/vigs/vigs_utils.c @@ -51,6 +51,7 @@ int vigs_format_num_buffers(vigsp_plane_format format) case vigsp_plane_nv21: return 2; case vigsp_plane_nv42: return 2; case vigsp_plane_nv61: return 2; + case vigsp_plane_yuv420: return 3; default: assert(false); VIGS_LOG_CRITICAL("unknown format: %d", format); |