diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-07-29 14:17:55 +0200 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-08-02 15:05:15 +0200 |
commit | 66cb0fef6c475f7dddf4387c40bd61782fa90c6b (patch) | |
tree | d67c0503e87e56d22a37e8189bf342d2f7fac81d | |
parent | 338c96325b24b30b960073e8e2bfe14d15a581f9 (diff) |
[WIP] compositor: yuv whatever-visualyuv
-rw-r--r-- | compositor/compositor.c | 81 | ||||
-rw-r--r-- | compositor/compositor.h | 4 |
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; |