From aae8db8df6456b251104b70bd49a975bb1e1a007 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 23 Apr 2010 16:57:49 +0200 Subject: gl: Add code for to handle subsampled multiplane surfaces In fact, we now handle y420, y422 and y444 surfaces. --- src/cairo-gl-shaders.c | 28 +++++++++++++---- src/cairo-gl-surface.c | 81 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 89 insertions(+), 20 deletions(-) diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c index 48d85be0..590eb95f 100644 --- a/src/cairo-gl-shaders.c +++ b/src/cairo-gl-shaders.c @@ -979,7 +979,7 @@ const char *vs_draw_sources[] = { "{\n" " gl_Position = ftransform();\n" " texcoords0 = gl_MultiTexCoord0.xy;\n" - " texcoords0 = gl_MultiTexCoord1.xy;\n" + " texcoords1 = gl_MultiTexCoord1.xy;\n" "}\n", "varying vec2 texcoords0;\n" @@ -989,8 +989,8 @@ const char *vs_draw_sources[] = { "{\n" " gl_Position = ftransform();\n" " texcoords0 = gl_MultiTexCoord0.xy;\n" - " texcoords0 = gl_MultiTexCoord1.xy;\n" - " texcoords0 = gl_MultiTexCoord2.xy;\n" + " texcoords1 = gl_MultiTexCoord1.xy;\n" + " texcoords2 = gl_MultiTexCoord2.xy;\n" "}\n" }; @@ -1036,13 +1036,30 @@ const char *fs_draw_main[] = { "void main()\n" "{\n" " gl_FragColor = transform_color (texture2D(texture0, texcoords0));\n" + "}\n", + + "uniform sampler2D texture0;\n" + "uniform sampler2D texture1;\n" + "uniform sampler2D texture2;\n" + "varying vec2 texcoords0;\n" + "void main()\n" + "{\n" + " gl_FragColor = transform_color (vec4(texture2D(texture0, texcoords0).r,\n" + " texture2D(texture1, texcoords0).r,\n" + " texture2D(texture2, texcoords0).r,\n" + " 1.0));\n" "}\n" + }; static unsigned int _cairo_gl_draw_shader_get_index_for_format (pixman_format_code_t format) { switch ((unsigned int) format) { + case PIXMAN_y444: + case PIXMAN_y422: + case PIXMAN_y420: + return 1; default: return 0; } @@ -1114,7 +1131,7 @@ _cairo_gl_get_draw_shader (cairo_gl_context_t *ctx, assert (ARRAY_LENGTH (vs_draw_sources) >= pixman_format_num_planes (format)); status = create_shader_program (&entry->program, - vs_draw_sources[pixman_format_num_planes (format) - 1], + vs_draw_sources[0], fs_source); free (fs_source); @@ -1123,7 +1140,8 @@ _cairo_gl_get_draw_shader (cairo_gl_context_t *ctx, char name[20]; sprintf (name, "texture%u", i); status = bind_texture_to_shader (entry->program.program, name, i); - assert (status == CAIRO_STATUS_SUCCESS); + if (status != CAIRO_STATUS_SUCCESS) + printf ("failed binding %s\n", name); } _cairo_gl_use_program (NULL); status = _cairo_cache_insert (&ctx->shader_cache, &entry->base); diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index 26c7955c..25d46ad9 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -288,6 +288,15 @@ _cairo_gl_get_image_format_and_type (pixman_color_space_t color_space, *type = GL_UNSIGNED_BYTE; return TRUE; + case PIXMAN_y444: + case PIXMAN_y422: + case PIXMAN_y420: + *requires_shader = TRUE; + *internal_format = GL_LUMINANCE; + *format = GL_LUMINANCE; + *type = GL_UNSIGNED_BYTE; + return TRUE; + case PIXMAN_a2b10g10r10: case PIXMAN_x2b10g10r10: case PIXMAN_a4r4g4b4: @@ -315,12 +324,12 @@ _cairo_gl_get_image_format_and_type (pixman_color_space_t color_space, case PIXMAN_a2r10g10b10: case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8: - case PIXMAN_yv12: - case PIXMAN_y444: case PIXMAN_yuy2: case PIXMAN_yvyu: case PIXMAN_vyuy: case PIXMAN_uyvy: + /* deprecated */ + case PIXMAN_yv12: default: return FALSE; } @@ -783,6 +792,31 @@ _cairo_gl_surface_create_similar (void *abstract_surface, return surface; } +static int +_cairo_gl_x_subsampling_for_plane (pixman_format_code_t format, int plane) +{ + if (plane == 0) + return 1; + + if (format == PIXMAN_y422 || + format == PIXMAN_y420) + return 2; + + return 1; +} + +static int +_cairo_gl_y_subsampling_for_plane (pixman_format_code_t format, int plane) +{ + if (plane == 0) + return 1; + + if (format == PIXMAN_y420) + return 2; + + return 1; +} + cairo_status_t _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, cairo_image_surface_t *src, @@ -804,7 +838,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, &format, &type, &has_alpha) || - (requires_shader && ! ((cairo_gl_context_t *) dst->base.device)->using_glsl)) + (requires_shader && (! ((cairo_gl_context_t *) dst->base.device)->using_glsl) || + src_x != 0 || src_y != 0)) { cairo_bool_t is_supported; @@ -869,8 +904,10 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } else { - GLuint tex; + GLuint tex[CAIRO_FORMAT_MAX_PLANES]; GLfloat vertices[8], texcoords[8]; + unsigned int i, num_planes; + int x_subsample, y_subsample; if (ctx->using_glsl) { cairo_gl_shader_program_t *program; @@ -891,13 +928,26 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, _cairo_gl_set_destination (ctx, dst); - glGenTextures (1, &tex); - glActiveTexture (GL_TEXTURE0); - glBindTexture (ctx->tex_target, tex); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D (ctx->tex_target, 0, internal_format, width, height, 0, - format, type, cairo_image_surface_get_data_for_row (src, src_y) + src_x * cpp); + num_planes = pixman_format_num_planes (src->pixman_format); + if (num_planes > 1) + cpp = 1; + + glGenTextures (num_planes, tex); + for (i = 0; i < num_planes; i++) { + glActiveTexture (GL_TEXTURE0 + i); + glBindTexture (ctx->tex_target, tex[i]); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei (GL_UNPACK_ROW_LENGTH, + pixman_image_get_stride_for_plane (src->pixman_image, i) / cpp); + x_subsample = _cairo_gl_x_subsampling_for_plane (src->pixman_format, i); + y_subsample = _cairo_gl_y_subsampling_for_plane (src->pixman_format, i); + glTexImage2D (ctx->tex_target, 0, internal_format, + (width + x_subsample - 1) / x_subsample, + (height + y_subsample - 1) / y_subsample, + 0, format, type, + pixman_image_get_data_for_plane (src->pixman_image, i)); + } glEnable (ctx->tex_target); glDisable (GL_BLEND); @@ -921,6 +971,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, texcoords[6] = 0; texcoords[7] = 1; } else { + /* XXX: subsampling */ texcoords[0] = 0; texcoords[1] = 0; texcoords[2] = width; @@ -934,9 +985,9 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices); glEnableClientState (GL_VERTEX_ARRAY); - glClientActiveTexture (GL_TEXTURE0); - glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, texcoords); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); + glClientActiveTexture (GL_TEXTURE0); + glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, texcoords); + glEnableClientState (GL_TEXTURE_COORD_ARRAY); glDrawArrays (GL_QUADS, 0, 4); @@ -946,7 +997,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, if (ctx->using_glsl) _cairo_gl_use_program (NULL); - glDeleteTextures (1, &tex); + glDeleteTextures (num_planes, tex); glDisable (ctx->tex_target); } -- cgit v1.2.3