[cairo-commit] 3 commits - src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-surface.c
Eric Anholt
anholt at kemper.freedesktop.org
Tue Feb 16 13:30:47 PST 2010
src/cairo-gl-glyphs.c | 25 +++---
src/cairo-gl-private.h | 1
src/cairo-gl-shaders.c | 44 +++++++++++
src/cairo-gl-surface.c | 196 ++++++++++++++++++++++++++++++++-----------------
4 files changed, 187 insertions(+), 79 deletions(-)
New commits:
commit e845450905f373e4fcb9ae4717cfd2c3e6472423
Author: Eric Anholt <eric at anholt.net>
Date: Tue Feb 16 13:18:33 2010 -0800
gl: Add GLSL support for ARB_texture_rectangle, and repeat/reflect fallbacks.
Most testcases are now passing like the ARB_texture_non_power_of_two
case. EXT_texture_rectangle support is dropped in favor of
ARB_texture_non_power_of_two. If we have issues with drivers not
having that but having EXT (which just lacks the GLSL part of the
spec), we can split it out. Right now non-GLSL support in cairo-gl is
probably in bad shape anyway and will require someone that cares for
it in order to get fixed up.
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index e2797d5..70a8c75 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -717,6 +717,13 @@ static const char *fs_source_texture =
"{\n"
" return texture2D(source_sampler, source_texcoords);\n"
"}\n";
+static const char *fs_source_texture_rect =
+ "uniform sampler2DRect source_sampler;\n"
+ "varying vec2 source_texcoords;\n"
+ "vec4 get_source()\n"
+ "{\n"
+ " return texture2DRect(source_sampler, source_texcoords);\n"
+ "}\n";
static const char *fs_source_texture_alpha =
"uniform sampler2D source_sampler;\n"
"varying vec2 source_texcoords;\n"
@@ -724,6 +731,13 @@ static const char *fs_source_texture_alpha =
"{\n"
" return vec4(0, 0, 0, texture2D(source_sampler, source_texcoords).a);\n"
"}\n";
+static const char *fs_source_texture_alpha_rect =
+ "uniform sampler2DRect source_sampler;\n"
+ "varying vec2 source_texcoords;\n"
+ "vec4 get_source()\n"
+ "{\n"
+ " return vec4(0, 0, 0, texture2DRect(source_sampler, source_texcoords).a);\n"
+ "}\n";
static const char *fs_source_linear_gradient =
"uniform sampler1D source_sampler;\n"
"uniform mat4 source_matrix;\n"
@@ -784,6 +798,13 @@ static const char *fs_mask_texture =
"{\n"
" return texture2D(mask_sampler, mask_texcoords);\n"
"}\n";
+static const char *fs_mask_texture_rect =
+ "uniform sampler2DRect mask_sampler;\n"
+ "varying vec2 mask_texcoords;\n"
+ "vec4 get_mask()\n"
+ "{\n"
+ " return texture2DRect(mask_sampler, mask_texcoords);\n"
+ "}\n";
static const char *fs_mask_texture_alpha =
"uniform sampler2D mask_sampler;\n"
"varying vec2 mask_texcoords;\n"
@@ -791,6 +812,13 @@ static const char *fs_mask_texture_alpha =
"{\n"
" return vec4(0, 0, 0, texture2D(mask_sampler, mask_texcoords).a);\n"
"}\n";
+static const char *fs_mask_texture_alpha_rect =
+ "uniform sampler2DRect mask_sampler;\n"
+ "varying vec2 mask_texcoords;\n"
+ "vec4 get_mask()\n"
+ "{\n"
+ " return vec4(0, 0, 0, texture2DRect(mask_sampler, mask_texcoords).a);\n"
+ "}\n";
static const char *fs_mask_linear_gradient =
"uniform sampler1D mask_sampler;\n"
"uniform mat4 mask_matrix;\n"
@@ -935,6 +963,22 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
source_source = source_sources[source];
mask_source = mask_sources[mask];
in_source = in_sources[in];
+
+ /* For ARB_texture_rectangle, rewrite sampler2D and texture2D to
+ * sampler2DRect and texture2DRect.
+ */
+ if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) {
+ if (source_source == fs_source_texture)
+ source_source = fs_source_texture_rect;
+ else if (source_source == fs_source_texture_alpha)
+ source_source = fs_source_texture_alpha_rect;
+
+ if (mask_source == fs_mask_texture)
+ mask_source = fs_mask_texture_rect;
+ else if (mask_source == fs_mask_texture_alpha)
+ mask_source = fs_mask_texture_alpha_rect;
+ }
+
fs_source = _cairo_malloc (strlen(source_source) +
strlen(mask_source) +
strlen(in_source) +
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 6470f69..f86a4fd 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -119,10 +119,10 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
}
if (! GLEW_ARB_texture_non_power_of_two &&
- ! GLEW_EXT_texture_rectangle ) {
+ ! GLEW_ARB_texture_rectangle ) {
fprintf (stderr,
"Required GL extensions not available:\n");
- fprintf (stderr, " GL_ARB_texture_non_power_of_two, GL_EXT_texture_rectangle\n");
+ fprintf (stderr, " GL_ARB_texture_non_power_of_two, GL_ARB_texture_rectangle\n");
}
if (!GLEW_ARB_texture_non_power_of_two)
@@ -382,11 +382,10 @@ _cairo_gl_set_texture_surface (int tex_unit, GLuint tex,
{
if (tex_target == GL_TEXTURE_RECTANGLE_EXT) {
- if (attributes->extend == CAIRO_EXTEND_REPEAT ||
- attributes->extend == CAIRO_EXTEND_REFLECT)
- fprintf(stderr,"cannot use rect texture for repeat/reflect\n");
+ assert (attributes->extend != CAIRO_EXTEND_REPEAT &&
+ attributes->extend != CAIRO_EXTEND_REFLECT);
}
-
+
glActiveTexture (GL_TEXTURE0 + tex_unit);
glBindTexture (tex_target, tex);
switch (attributes->extend) {
@@ -1175,6 +1174,16 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand,
if (unlikely (status))
return status;
+ if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT &&
+ (attributes->extend == CAIRO_EXTEND_REPEAT ||
+ attributes->extend == CAIRO_EXTEND_REFLECT))
+ {
+ _cairo_pattern_release_surface (operand->pattern,
+ &surface->base,
+ attributes);
+ return UNSUPPORTED ("EXT_texture_rectangle with repeat/reflect");
+ }
+
assert (surface->base.backend == &_cairo_gl_surface_backend);
operand->operand.texture.surface = surface;
commit 40294377cb26fab7bcf17ee98b8e4f5bf9778ca2
Author: Dave Airlie <airlied at redhat.com>
Date: Sat Jan 30 19:24:31 2010 +1000
gl: initial support for EXT_texture_rectangle extension
The only issue is the repeat modes aren't supported for rectangular
textures. In any case even with ARB_npot radeon's pre-r600 lie and
fail to do repeats anyway.
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 9e130d0..dbd24c5 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -50,7 +50,8 @@ typedef struct _cairo_gl_glyph_private {
} cairo_gl_glyph_private_t;
static cairo_status_t
-_cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache,
+_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
+ cairo_gl_glyph_cache_t *cache,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
@@ -110,7 +111,7 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache,
glPixelStorei (GL_UNPACK_ROW_LENGTH,
glyph_surface->stride /
(PIXMAN_FORMAT_BPP (glyph_surface->pixman_format) / 8));
- glTexSubImage2D (GL_TEXTURE_2D, 0,
+ glTexSubImage2D (ctx->tex_target, 0,
node->x, node->y,
glyph_surface->width, glyph_surface->height,
format, type,
@@ -181,10 +182,10 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
}
glGenTextures (1, &cache->tex);
- glBindTexture (GL_TEXTURE_2D, cache->tex);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D (GL_TEXTURE_2D, 0, internal_format,
+ glBindTexture (ctx->tex_target, cache->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,
GLYPH_CACHE_WIDTH, GLYPH_CACHE_HEIGHT, 0,
internal_format, GL_FLOAT, NULL);
}
@@ -271,7 +272,7 @@ _cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
* the loop over glyphs below.
*/
glActiveTexture (GL_TEXTURE1);
- glEnable (GL_TEXTURE_2D);
+ glEnable (ctx->tex_target);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
@@ -555,7 +556,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
cache = cairo_gl_context_get_glyph_cache (ctx,
scaled_glyph->surface->format);
- glBindTexture (GL_TEXTURE_2D, cache->tex);
+ glBindTexture (ctx->tex_target, cache->tex);
last_format = scaled_glyph->surface->format;
/* If we're doing component alpha in this function, it should
@@ -571,13 +572,13 @@ _render_glyphs (cairo_gl_surface_t *dst,
}
if (scaled_glyph->surface_private == NULL) {
- status = _cairo_gl_glyph_cache_add_glyph (cache, scaled_glyph);
+ status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
/* Cache is full, so flush existing prims and try again. */
_cairo_gl_flush_glyphs (ctx, &setup);
_cairo_gl_glyph_cache_unlock (cache);
- status = _cairo_gl_glyph_cache_add_glyph (cache, scaled_glyph);
+ status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
}
if (unlikely (_cairo_status_is_error (status)))
@@ -612,12 +613,12 @@ _render_glyphs (cairo_gl_surface_t *dst,
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE0);
glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
+ glDisable (ctx->tex_target);
glClientActiveTexture (GL_TEXTURE1);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE1);
- glDisable (GL_TEXTURE_2D);
+ glDisable (ctx->tex_target);
_cairo_gl_use_program (NULL);
glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 6cd3ec8..6faaffa 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -122,6 +122,7 @@ typedef struct _cairo_gl_context {
GLuint vbo;
GLint max_framebuffer_size;
GLint max_texture_size;
+ GLenum tex_target;
cairo_bool_t using_glsl;
cairo_bool_t using_shaders;
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 919c6cf..6470f69 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -100,7 +100,6 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
if (! GLEW_EXT_framebuffer_object ||
! GLEW_ARB_texture_env_combine ||
- ! GLEW_ARB_texture_non_power_of_two ||
! GLEW_EXT_bgra)
{
fprintf (stderr,
@@ -109,8 +108,6 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
fprintf (stderr, " GL_EXT_framebuffer_object\n");
if (! GLEW_ARB_texture_env_combine)
fprintf (stderr, " GL_ARB_texture_env_combine\n");
- if (! GLEW_ARB_texture_non_power_of_two)
- fprintf (stderr, " GL_ARB_texture_non_power_of_two\n");
/* EXT_bgra is used in two places:
* - draw_image to upload common pixman formats without hand-swizzling.
* - get_image to download common pixman formats without hand-swizzling.
@@ -121,6 +118,19 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
}
+ if (! GLEW_ARB_texture_non_power_of_two &&
+ ! GLEW_EXT_texture_rectangle ) {
+ fprintf (stderr,
+ "Required GL extensions not available:\n");
+ fprintf (stderr, " GL_ARB_texture_non_power_of_two, GL_EXT_texture_rectangle\n");
+ }
+
+ if (!GLEW_ARB_texture_non_power_of_two)
+ ctx->tex_target = GL_TEXTURE_RECTANGLE_EXT;
+ else
+ ctx->tex_target = GL_TEXTURE_2D;
+
+
if (GLEW_VERSION_2_0 ||
(GLEW_ARB_fragment_shader &&
GLEW_ARB_vertex_shader &&
@@ -133,8 +143,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
/* Set up the dummy texture for tex_env_combine with constant color. */
glGenTextures (1, &ctx->dummy_tex);
- glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
+ glBindTexture (ctx->tex_target, ctx->dummy_tex);
+ glTexImage2D (ctx->tex_target, 0, GL_RGBA, 1, 1, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
/* PBO for any sort of texture upload */
@@ -367,45 +377,53 @@ _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
static void
_cairo_gl_set_texture_surface (int tex_unit, GLuint tex,
- cairo_surface_attributes_t *attributes)
+ cairo_surface_attributes_t *attributes,
+ GLint tex_target)
{
+
+ if (tex_target == GL_TEXTURE_RECTANGLE_EXT) {
+ if (attributes->extend == CAIRO_EXTEND_REPEAT ||
+ attributes->extend == CAIRO_EXTEND_REFLECT)
+ fprintf(stderr,"cannot use rect texture for repeat/reflect\n");
+ }
+
glActiveTexture (GL_TEXTURE0 + tex_unit);
- glBindTexture (GL_TEXTURE_2D, tex);
+ glBindTexture (tex_target, tex);
switch (attributes->extend) {
case CAIRO_EXTEND_NONE:
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
break;
case CAIRO_EXTEND_PAD:
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
break;
case CAIRO_EXTEND_REPEAT:
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
break;
case CAIRO_EXTEND_REFLECT:
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
break;
}
switch (attributes->filter) {
case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break;
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
break;
default:
case CAIRO_FILTER_GAUSSIAN:
ASSERT_NOT_REACHED;
}
- glEnable (GL_TEXTURE_2D);
+ glEnable (tex_target);
}
void
@@ -472,10 +490,10 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
/* Create the texture used to store the surface's data. */
glGenTextures (1, &surface->tex);
- glBindTexture (GL_TEXTURE_2D, surface->tex);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0,
+ glBindTexture (ctx->tex_target, surface->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, format, width, height, 0,
format, GL_UNSIGNED_BYTE, NULL);
/* Create a framebuffer object wrapping the texture so that we can render
@@ -485,7 +503,7 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D,
+ ctx->tex_target,
surface->tex,
0);
ctx->current_target = NULL;
@@ -664,6 +682,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
GLenum internal_format, format, type;
cairo_bool_t has_alpha;
cairo_image_surface_t *clone = NULL;
+ cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device;
int cpp;
if (! _cairo_gl_get_image_format_and_type (src->pixman_format,
@@ -691,12 +710,12 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;
- glBindTexture (GL_TEXTURE_2D, dst->tex);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindTexture (ctx->tex_target, dst->tex);
+ glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
- glTexSubImage2D (GL_TEXTURE_2D, 0,
+ glTexSubImage2D (ctx->tex_target, 0,
dst_x, dst_y, width, height,
format, GL_UNSIGNED_BYTE,
src->data + src_y * src->stride + src_x * cpp);
@@ -1143,7 +1162,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand,
cairo_matrix_t m;
cairo_gl_surface_t *surface;
cairo_surface_attributes_t *attributes;
-
+ cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device;
attributes = &operand->operand.texture.attributes;
status = _cairo_pattern_acquire_surface (src, &dst->base,
@@ -1183,9 +1202,15 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand,
* (unnormalized src -> unnormalized src) to
* (unnormalized dst -> normalized src)
*/
- cairo_matrix_init_scale (&m,
- 1.0 / surface->width,
- 1.0 / surface->height);
+ if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) {
+ cairo_matrix_init_scale (&m,
+ 1.0,
+ 1.0);
+ } else {
+ cairo_matrix_init_scale (&m,
+ 1.0 / surface->width,
+ 1.0 / surface->height);
+ }
cairo_matrix_multiply (&attributes->matrix,
&attributes->matrix,
&m);
@@ -1415,8 +1440,8 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
/* Fall back to fixed function */
glActiveTexture (GL_TEXTURE0 + tex_unit);
/* Have to have a dummy texture bound in order to use the combiner unit. */
- glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex);
- glEnable (GL_TEXTURE_2D);
+ glBindTexture (ctx->tex_target, ctx->dummy_tex);
+ glEnable (ctx->tex_target);
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@@ -1460,7 +1485,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
break;
case OPERAND_TEXTURE:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
- src_attributes);
+ src_attributes, ctx->tex_target);
if (!setup->shader) {
/* Set up the constant color we use to set color to 0 if needed. */
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
@@ -1573,7 +1598,7 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
break;
case OPERAND_TEXTURE:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
- src_attributes);
+ src_attributes, ctx->tex_target);
if (!setup->shader) {
/* Set up the combiner to just set color to the sampled texture. */
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@@ -1699,9 +1724,9 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
setup->src.operand.constant.color[2],
setup->src.operand.constant.color[3]);
} else {
- glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex);
+ glBindTexture (ctx->tex_target, ctx->dummy_tex);
glActiveTexture (GL_TEXTURE1);
- glEnable (GL_TEXTURE_2D);
+ glEnable (ctx->tex_target);
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
setup->mask.operand.constant.color);
@@ -1714,7 +1739,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
break;
case OPERAND_TEXTURE:
_cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
- mask_attributes);
+ mask_attributes, ctx->tex_target);
if (!setup->shader) {
/* Set up the constant color we use to set color to 0 if needed. */
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
@@ -1980,13 +2005,13 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE0);
glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
+ glDisable (ctx->tex_target);
glClientActiveTexture (GL_TEXTURE1);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE1);
glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
+ glDisable (ctx->tex_target);
while ((err = glGetError ()))
fprintf (stderr, "GL error 0x%08x\n", (int) err);
@@ -2107,7 +2132,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
case OPERAND_TEXTURE:
_cairo_gl_set_texture_surface (1, setup.mask.operand.texture.tex,
- mask_attributes);
+ mask_attributes, ctx->tex_target);
if (!setup.shader) {
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
@@ -2227,13 +2252,13 @@ _cairo_gl_surface_composite (cairo_operator_t op,
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE0);
glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
+ glDisable (ctx->tex_target);
glClientActiveTexture (GL_TEXTURE1);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE1);
glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
+ glDisable (ctx->tex_target);
while ((err = glGetError ()))
fprintf (stderr, "GL error 0x%08x\n", (int) err);
@@ -2750,11 +2775,11 @@ _cairo_gl_surface_span_renderer_finish (void *abstract_renderer)
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glActiveTexture (GL_TEXTURE0);
glDisable (GL_TEXTURE_1D);
- glDisable (GL_TEXTURE_2D);
+ glDisable (renderer->ctx->tex_target);
if (!renderer->setup.shader) {
glActiveTexture (GL_TEXTURE1);
- glDisable (GL_TEXTURE_2D);
+ glDisable (renderer->ctx->tex_target);
}
glDisable (GL_BLEND);
@@ -2791,6 +2816,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
cairo_region_t *clip_region)
{
cairo_gl_surface_t *dst = abstract_dst;
+ cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device;
cairo_gl_surface_span_renderer_t *renderer;
cairo_status_t status;
cairo_surface_attributes_t *src_attributes;
@@ -2850,8 +2876,8 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
/* Set up the mask to source from the incoming vertex color. */
glActiveTexture (GL_TEXTURE1);
/* Have to have a dummy texture bound in order to use the combiner unit. */
- glBindTexture (GL_TEXTURE_2D, renderer->ctx->dummy_tex);
- glEnable (GL_TEXTURE_2D);
+ glBindTexture (ctx->tex_target, renderer->ctx->dummy_tex);
+ glEnable (ctx->tex_target);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
commit 6542a515f04d52d10fdc89ee9abc76e54282a2d8
Author: Eric Anholt <eric at anholt.net>
Date: Sun Feb 7 20:26:56 2010 +0100
gl: Reduce the size of the gradient texture for small numbers of stops.
This code is stolen straight from cairo-drm-intel.c. This saves a
bunch of time calculating interpolated points when we just do
interpolation between points at sampling time anyway. Reduces
firefox-talos-svg from 47 seconds back to the 42 it was at before the
pixman change.
This regresses the reported result of huge-radial, but there's no
visible difference.
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 9c7c28e..919c6cf 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -973,31 +973,58 @@ _cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst,
return CAIRO_STATUS_SUCCESS;
}
-
-static inline void
-lerp_and_set_color (GLubyte *color,
- double t0, double t1, double t,
- double r0, double g0, double b0, double a0,
- double r1, double g1, double b1, double a1)
+static int
+_cairo_gl_gradient_sample_width (const cairo_gradient_pattern_t *gradient)
{
- double alpha = (t - t0) / (t1 - t0);
- double a = ((1.0 - alpha) * a0 + alpha * a1);
- color[0] = ((1.0 - alpha) * b0 + alpha * b1) * a * 255.0;
- color[1] = ((1.0 - alpha) * g0 + alpha * g1) * a * 255.0;
- color[2] = ((1.0 - alpha) * r0 + alpha * r1) * a * 255.0;
- color[3] = a * 255.0;
+ unsigned int n;
+ int width;
+
+ width = 8;
+ for (n = 1; n < gradient->n_stops; n++) {
+ double dx = gradient->stops[n].offset - gradient->stops[n-1].offset;
+ double delta, max;
+ int ramp;
+
+ if (dx == 0)
+ continue;
+
+ max = gradient->stops[n].color.red -
+ gradient->stops[n-1].color.red;
+
+ delta = gradient->stops[n].color.green -
+ gradient->stops[n-1].color.green;
+ if (delta > max)
+ max = delta;
+
+ delta = gradient->stops[n].color.blue -
+ gradient->stops[n-1].color.blue;
+ if (delta > max)
+ max = delta;
+
+ delta = gradient->stops[n].color.alpha -
+ gradient->stops[n-1].color.alpha;
+ if (delta > max)
+ max = delta;
+
+ ramp = 128 * max / dx;
+ if (ramp > width)
+ width = ramp;
+ }
+
+ width = (width + 7) & -8;
+ return MIN (width, 1024);
}
static cairo_status_t
_render_gradient (const cairo_gl_context_t *ctx,
cairo_gradient_pattern_t *pattern,
- void *bytes)
+ void *bytes,
+ int width)
{
pixman_image_t *gradient, *image;
pixman_gradient_stop_t pixman_stops_stack[32];
pixman_gradient_stop_t *pixman_stops;
pixman_point_fixed_t p1, p2;
- int width;
unsigned int i;
pixman_stops = pixman_stops_stack;
@@ -1016,8 +1043,6 @@ _render_gradient (const cairo_gl_context_t *ctx,
pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
}
- width = ctx->max_texture_size;
-
p1.x = 0;
p1.y = 0;
p2.x = width << 16;
@@ -1059,16 +1084,18 @@ _cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
float *first_offset,
float *last_offset)
{
- const int tex_width = ctx->max_texture_size;
+ int tex_width;
GLubyte *data;
assert (pattern->n_stops != 0);
+ tex_width = _cairo_gl_gradient_sample_width (pattern);
+
glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, ctx->texture_load_pbo);
glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, tex_width * sizeof (uint32_t), 0, GL_STREAM_DRAW);
data = glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
- _render_gradient (ctx, pattern, data);
+ _render_gradient (ctx, pattern, data, tex_width);
*first_offset = 0.;
*last_offset = 1.;
More information about the cairo-commit
mailing list