summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-04-23 16:57:49 +0200
committerBenjamin Otte <otte@redhat.com>2010-04-23 23:34:46 +0200
commitaae8db8df6456b251104b70bd49a975bb1e1a007 (patch)
tree321904ee10e44dcfad545cf00133b15c7f27b793
parente3fb581b4cbd64b07813a1ab785373a7d30fd233 (diff)
gl: Add code for to handle subsampled multiplane surfaces
In fact, we now handle y420, y422 and y444 surfaces.
-rw-r--r--src/cairo-gl-shaders.c28
-rw-r--r--src/cairo-gl-surface.c81
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);
}