summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/vigs/vigs_gl_backend.c175
-rw-r--r--hw/vigs/vigs_gl_backend.h6
2 files changed, 172 insertions, 9 deletions
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;