From 8dbce72ff4bd12e95c967722405b45e666e579ee Mon Sep 17 00:00:00 2001 From: Vladislav Andresov Date: Wed, 20 Jun 2018 23:08:12 +0300 Subject: VIGS: add h/w conversion from ARGB to XBGR Change-Id: I8def07093fce07cf6f1e19d6319ea5468f8a8a35 Signed-off-by: Vladislav Andresov --- hw/vigs/vigs_gl_backend.c | 175 +++++++++++++++++++++++++++++++++++++++++++--- hw/vigs/vigs_gl_backend.h | 6 ++ 2 files changed, 172 insertions(+), 9 deletions(-) (limited to 'hw') diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c index f4c6f4a136..fa5182a463 100644 --- a/hw/vigs/vigs_gl_backend.c +++ b/hw/vigs/vigs_gl_backend.c @@ -47,6 +47,7 @@ (((unsigned int)(d)) << 24)) #define DRM_FORMAT_ARGB8888 MAKE_FOURCC('A', 'R', '2', '4') #define DRM_FORMAT_YUV420 MAKE_FOURCC('Y', 'U', '1', '2') +#define DRM_FORMAT_XBGR8888 MAKE_FOURCC('X', 'B', '2', '4') #endif struct vigs_gl_surface; @@ -362,6 +363,25 @@ static const char *g_fs_yuv420_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_fs_xbgr_source_gl2 = + "#version 120\n\n" + "uniform sampler2D tex;\n" + "varying vec2 v_texCoord;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(texture2D(tex, v_texCoord).bgr, 1.0);\n" + "}\n"; + +static const char *g_fs_xbgr_source_gl3 = + "#version 140\n\n" + "uniform sampler2D tex;\n" + "in vec2 v_texCoord;\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = vec4(texture(tex, v_texCoord).bgr, 1.0);\n" + "}\n"; + static GLuint vigs_gl_backend_alloc_tmp_texture(void *user_data, uint32_t width, uint32_t height, @@ -674,6 +694,27 @@ static void vigs_gl_draw_yuv420_prog(struct vigs_gl_backend *backend, backend->DisableVertexAttribArray(backend->yuv420_prog_vertCoord_loc); } +static void vigs_gl_draw_xbgr_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->xbgr_prog_vertCoord_loc); + backend->EnableVertexAttribArray(backend->xbgr_prog_texCoord_loc); + + backend->VertexAttribPointer(backend->xbgr_prog_vertCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL); + backend->VertexAttribPointer(backend->xbgr_prog_texCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2)); + + backend->DrawArrays(GL_TRIANGLES, 0, count); + + backend->DisableVertexAttribArray(backend->xbgr_prog_texCoord_loc); + backend->DisableVertexAttribArray(backend->xbgr_prog_vertCoord_loc); +} + static void vigs_gl_create_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearf, GLfloat farf, @@ -1791,6 +1832,77 @@ static void vigs_gl_surface_convert_yuv2argb(struct vigs_surface *dst, vigs_gl_draw_yuv420_prog(gl_backend, 6); +out: + gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0); +} + +static void vigs_gl_surface_convert_argb2xbgr(struct vigs_surface *dst, + struct vigs_surface *src) +{ + struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)dst->backend; + struct vigs_gl_surface *gl_dst = (struct vigs_gl_surface*)dst; + struct vigs_gl_surface *gl_src = (struct vigs_gl_surface*)src; + struct vigs_winsys_gl_surface *ws_dst = get_ws_sfc(gl_dst); + struct vigs_winsys_gl_surface *ws_src = get_ws_sfc(gl_src); + GLsizei dst_w = ws_dst->base.base.width; + GLsizei dst_h = ws_dst->base.base.height; + GLfloat *vert_coords; + GLfloat *tex_coords; + + if (!vigs_winsys_gl_surface_create_texture(ws_dst)) { + goto out; + } + + if (!ws_src->tex) { + VIGS_LOG_WARN("copying garbage ???"); + } + + if (!vigs_winsys_gl_surface_create_texture(ws_src)) { + goto out; + } + + if (!vigs_gl_surface_setup_framebuffer(gl_dst, + gl_backend->xbgr_prog_id, + gl_backend->xbgr_prog_proj_loc)) { + goto out; + } + + vigs_vector_resize(&gl_backend->v1, 12 * sizeof(GLfloat)); + vigs_vector_resize(&gl_backend->v2, 12 * sizeof(GLfloat)); + + vert_coords = vigs_vector_data(&gl_backend->v1); + tex_coords = vigs_vector_data(&gl_backend->v2); + + vert_coords[6] = vert_coords[0] = 0; + vert_coords[7] = vert_coords[1] = dst_h; + vert_coords[2] = dst_w; + vert_coords[3] = dst_h; + vert_coords[8] = vert_coords[4] = dst_w; + vert_coords[9] = vert_coords[5] = 0.0; + vert_coords[10] = 0.0; + vert_coords[11] = 0.0; + + tex_coords[6] = tex_coords[0] = 0.0; + tex_coords[7] = tex_coords[1] = 1.0; + tex_coords[2] = 1.0; + tex_coords[3] = 1.0; + tex_coords[8] = tex_coords[4] = 1.0; + tex_coords[9] = tex_coords[5] = 0.0; + tex_coords[10] = 0.0; + tex_coords[11] = 0.0; + + gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + ws_dst->tex, + 0); + + gl_backend->BindTexture(GL_TEXTURE_2D, ws_src->tex); + + gl_backend->UseProgram(gl_backend->xbgr_prog_id); + + vigs_gl_draw_xbgr_prog(gl_backend, 6); + gl_backend->UseProgram(gl_backend->tex_prog_id); out: @@ -1805,6 +1917,7 @@ static void vigs_gl_surface_convert(struct vigs_surface *dst, { uint32_t width = dst->ws_sfc->width; uint32_t height = dst->ws_sfc->height; + bool conversion_supported = true; struct vigsp_copy entry = { .from = { 0, 0 }, @@ -1819,18 +1932,32 @@ static void vigs_gl_surface_convert(struct vigs_surface *dst, -1.0f, 1.0f, gl_dst->ortho); } - /* - * Currently only ARGB8888 destination format is needed for support - */ - switch (src_format) { - case DRM_FORMAT_YUV420: - vigs_gl_surface_convert_yuv2argb(dst, src); - break; + switch (dst_format) { case DRM_FORMAT_ARGB8888: - vigs_gl_surface_copy(dst, src, &entry, 1); + switch (src_format) { + case DRM_FORMAT_YUV420: + vigs_gl_surface_convert_yuv2argb(dst, src); + break; + case DRM_FORMAT_ARGB8888: + vigs_gl_surface_copy(dst, src, &entry, 1); + break; + default: + conversion_supported = false; + break; + } + break; + case DRM_FORMAT_XBGR8888: + switch (src_format) { + case DRM_FORMAT_ARGB8888: + vigs_gl_surface_convert_argb2xbgr(dst, src); + break; + default: + conversion_supported = false; + break; + } break; default: - VIGS_LOG_ERROR("source format 0x%x is not supported", src_format); + conversion_supported = false; break; } @@ -1838,6 +1965,12 @@ static void vigs_gl_surface_convert(struct vigs_surface *dst, vigs_gl_create_ortho(0.0f, width, 0.0f, height, -1.0f, 1.0f, gl_dst->ortho); } + + if (!conversion_supported) { + VIGS_LOG_ERROR("format conversion from 0x%x to 0x%x is not supported", + src_format, + dst_format); + } } static void vigs_gl_surface_destroy(struct vigs_surface *sfc) @@ -2653,6 +2786,30 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) 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->xbgr_prog_fs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_fs_xbgr_source_gl2 : g_fs_xbgr_source_gl3), + GL_FRAGMENT_SHADER); + + if (!gl_backend->xbgr_prog_fs_id) { + goto fail; + } + + /* + * Let's borrow compiled vertex shader from tex program + */ + + gl_backend->xbgr_prog_id = vigs_gl_create_program(gl_backend, + gl_backend->tex_prog_vs_id, + gl_backend->xbgr_prog_fs_id); + + if (!gl_backend->xbgr_prog_id) { + goto fail; + } + + gl_backend->xbgr_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->xbgr_prog_id, "proj"); + gl_backend->xbgr_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->xbgr_prog_id, "vertCoord"); + gl_backend->xbgr_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->xbgr_prog_id, "texCoord"); + gl_backend->GenBuffers(1, &gl_backend->vbo); if (!gl_backend->vbo) { VIGS_LOG_CRITICAL("cannot create VBOs"); diff --git a/hw/vigs/vigs_gl_backend.h b/hw/vigs/vigs_gl_backend.h index c9cd54e3c2..9a2b4b38b4 100644 --- a/hw/vigs/vigs_gl_backend.h +++ b/hw/vigs/vigs_gl_backend.h @@ -212,6 +212,12 @@ struct vigs_gl_backend GLint yuv420_prog_utex_loc; GLint yuv420_prog_vtex_loc; + GLuint xbgr_prog_fs_id; + GLuint xbgr_prog_id; + GLint xbgr_prog_proj_loc; + GLint xbgr_prog_vertCoord_loc; + GLint xbgr_prog_texCoord_loc; + GLuint vbo; uint32_t vbo_size; -- cgit v1.2.3