summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-07-29 14:17:55 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-08-02 15:05:15 +0200
commit66cb0fef6c475f7dddf4387c40bd61782fa90c6b (patch)
treed67c0503e87e56d22a37e8189bf342d2f7fac81d
parent338c96325b24b30b960073e8e2bfe14d15a581f9 (diff)
[WIP] compositor: yuv whatever-visualyuv
-rw-r--r--compositor/compositor.c81
-rw-r--r--compositor/compositor.h4
2 files changed, 85 insertions, 0 deletions
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 177de54..ed17a41 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -403,6 +403,7 @@ wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface)
ec->image_target_texture_2d(GL_TEXTURE_2D, es->image);
es->visual = buffer->visual;
es->pitch = es->width;
+ es->stride = buffer->stride;
}
}
@@ -635,6 +636,7 @@ wlsc_surface_draw(struct wlsc_surface *es,
{
struct wlsc_compositor *ec = es->compositor;
GLfloat *v;
+ struct wlsc_shader *shader;
pixman_region32_t repaint;
GLint filter;
int n;
@@ -655,6 +657,20 @@ wlsc_surface_draw(struct wlsc_surface *es,
glDisable(GL_BLEND);
}
+ if (es->visual == &ec->compositor.yv12_visual) {
+ shader = &ec->texture_yv12_shader;
+ glUseProgram(ec->texture_yv12_shader.program);
+ glUniform1f(ec->texture_yv12_shader.width_uniform, es->width);
+ glUniform1f(ec->texture_yv12_shader.height_uniform, es->height);
+ glUniform1f(ec->texture_yv12_shader.stride_uniform, es->stride);
+ glUniform1i(shader->tex_uniform, 0);
+ } else {
+ shader = &ec->texture_shader;
+ glUseProgram(ec->texture_shader.program);
+ }
+ glUniformMatrix4fv(shader->proj_uniform,
+ 1, GL_FALSE, output->matrix.d);
+
if (es->transform == NULL) {
filter = GL_NEAREST;
n = texture_region(es, &repaint);
@@ -1665,6 +1681,31 @@ static const char texture_fragment_shader[] =
" gl_FragColor = texture2D(tex, v_texcoord)\n;"
"}\n";
+static const char texture_yv12_fragment_shader[] =
+ "precision mediump float;\n"
+ "varying vec2 v_texcoord;\n"
+ "uniform sampler2D tex;\n"
+ "uniform float width;\n"
+ "uniform float height;\n"
+ "uniform float stride;\n"
+ "void main()\n"
+ "{\n"
+ " vec3 trans = -vec3(0.0625, 0.5, 0.5);\n"
+ " mat3 cvt = mat3(vec3(1.16438, 1.16438, 1.16438),\n"
+ " vec3( 0.0, -0.39176, 2.01723),\n"
+ " vec3(1.59603, -0.81297, 0.0));\n"
+ " vec2 y_coord = v_texcoord * vec2(1.0, 2.0/3.0);\n"
+ " bool y_is_odd = bool(mod(v_texcoord.y * height, 2.0));\n"
+ " vec2 offset = vec2(y_is_odd ? 0.5 * stride/width : 0.0, 2.0/3.0);\n"
+ " vec2 v_coord = v_texcoord * vec2(0.5, 1.0/6.0) + offset;\n"
+ " vec2 u_coord = v_coord + vec2(0.0, 1.0/6.0);\n"
+ " vec3 yuv = vec3(texture2D(tex, y_coord).a,\n"
+ " texture2D(tex, u_coord).a,\n"
+ " texture2D(tex, v_coord).a);\n"
+ " vec3 rgb = cvt * (yuv + trans);\n"
+ " gl_FragColor = vec4(rgb, 1.0);\n"
+ "}\n";
+
static const char solid_fragment_shader[] =
"precision mediump float;\n"
"uniform vec4 color;\n"
@@ -1756,6 +1797,42 @@ init_solid_shader(struct wlsc_shader *shader,
return 0;
}
+static int
+init_yv12_shader(struct wlsc_shader *shader,
+ GLuint vertex_shader, const char *fragment_source)
+{
+ GLint status;
+ char msg[512];
+
+ shader->vertex_shader = vertex_shader;
+ shader->fragment_shader =
+ compile_shader(GL_FRAGMENT_SHADER, fragment_source);
+
+ shader->program = glCreateProgram();
+ glAttachShader(shader->program, shader->vertex_shader);
+ glAttachShader(shader->program, shader->fragment_shader);
+ glBindAttribLocation(shader->program, 0, "position");
+ glBindAttribLocation(shader->program, 1, "texcoord");
+
+ glLinkProgram(shader->program);
+ glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
+ if (!status) {
+ glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
+ fprintf(stderr, "link info: %s\n", msg);
+ return -1;
+ }
+
+ shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
+ shader->color_uniform = glGetUniformLocation(shader->program, "color");
+ shader->tex_uniform = glGetUniformLocation(shader->program, "tex");
+
+ shader->width_uniform = glGetUniformLocation(shader->program, "width");
+ shader->height_uniform = glGetUniformLocation(shader->program, "height");
+ shader->stride_uniform = glGetUniformLocation(shader->program, "stride");
+
+ return 0;
+}
+
WL_EXPORT void
wlsc_output_destroy(struct wlsc_output *output)
{
@@ -1944,6 +2021,10 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
ec->texture_shader.vertex_shader,
solid_fragment_shader) < 0)
return -1;
+ if (init_yv12_shader(&ec->texture_yv12_shader,
+ ec->texture_shader.vertex_shader,
+ texture_yv12_fragment_shader) < 0)
+ return -1;
loop = wl_display_get_event_loop(ec->wl_display);
ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
diff --git a/compositor/compositor.h b/compositor/compositor.h
index ea6e9e7..3e51f2b 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -126,6 +126,8 @@ struct wlsc_shader {
GLuint proj_uniform;
GLuint tex_uniform;
GLuint color_uniform;
+
+ GLuint width_uniform, height_uniform, stride_uniform;
};
struct wlsc_animation {
@@ -169,6 +171,7 @@ struct wlsc_compositor {
GLuint proj_uniform, tex_uniform;
struct wlsc_sprite **pointer_sprites;
struct wlsc_shader texture_shader;
+ struct wlsc_shader texture_yv12_shader;
struct wlsc_shader solid_shader;
struct wl_display *wl_display;
@@ -242,6 +245,7 @@ struct wlsc_surface {
pixman_region32_t opaque;
int32_t x, y, width, height;
int32_t pitch;
+ uint32_t stride;
int32_t saved_x, saved_y;
struct wl_list link;
struct wl_list buffer_link;