[cairo-commit] src/cairo-gl-surface.c
Chris Wilson
ickle at kemper.freedesktop.org
Sun Feb 7 06:36:04 PST 2010
src/cairo-gl-surface.c | 145 +++++++++++++++++++++++++++----------------------
1 file changed, 80 insertions(+), 65 deletions(-)
New commits:
commit 0f99303cd6d68df79070200a843194a20ad1c597
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Sun Feb 7 12:40:19 2010 +0000
gl: Use pixman to create the gradient texture
This is just for consistency as we know that pixman has to handle all
the corner cases anyway...
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index ae77463..c860f30 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -988,6 +988,69 @@ lerp_and_set_color (GLubyte *color,
color[3] = a * 255.0;
}
+static cairo_status_t
+_render_gradient (const cairo_gl_context_t *ctx,
+ cairo_gradient_pattern_t *pattern,
+ void *bytes)
+{
+ 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;
+ if (unlikely (pattern->n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
+ pixman_stops = _cairo_malloc_ab (pattern->n_stops,
+ sizeof (pixman_gradient_stop_t));
+ if (unlikely (pixman_stops == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ for (i = 0; i < pattern->n_stops; i++) {
+ pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
+ pixman_stops[i].color.red = pattern->stops[i].color.red_short;
+ pixman_stops[i].color.green = pattern->stops[i].color.green_short;
+ pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
+ 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;
+ p2.y = 0;
+
+ gradient = pixman_image_create_linear_gradient (&p1, &p2,
+ pixman_stops,
+ pattern->n_stops);
+ if (pixman_stops != pixman_stops_stack)
+ free (pixman_stops);
+
+ if (unlikely (gradient == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1,
+ bytes, sizeof(uint32_t)*width);
+ if (unlikely (image == NULL)) {
+ pixman_image_unref (gradient);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ pixman_image_composite (PIXMAN_OP_SRC,
+ gradient, NULL, image,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, 1);
+
+ pixman_image_unref (gradient);
+ pixman_image_unref (image);
+ return CAIRO_STATUS_SUCCESS;
+}
+
static void
_cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface,
@@ -997,79 +1060,31 @@ _cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
float *last_offset)
{
const int tex_width = ctx->max_texture_size;
- int n_stops = pattern->n_stops;
- cairo_gradient_stop_t *stops = pattern->stops;
- GLubyte *data = 0;
- GLubyte data_stack[4] = { 0, 0, 0, 0 };
- cairo_extend_t extend = pattern->base.extend;
-
- if (stops == 0) {
- data = data_stack;
- *first_offset = 0.0;
- *last_offset = 1.0;
- } else {
- int i, j = 0, stop_index;
- double offset, r, g, b, a;
- double prev_r = 0.0, prev_g = 0.0, prev_b = 0.0, prev_a = 0.0;
- double delta_offsets;
- GLuint size = tex_width * sizeof (GLubyte) * 4;
-
- glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, ctx->texture_load_pbo);
- glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, size, 0, GL_STREAM_DRAW);
- data = glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
-
- *first_offset = stops[0].offset;
- *last_offset = stops[n_stops - 1].offset;
- delta_offsets = *last_offset - *first_offset;
-
- for (i = 0; i < n_stops; ++i) {
- GLubyte *color = 0;
-
- cairo_pattern_get_color_stop_rgba (&pattern->base, i,
- &offset, &r, &g, &b, &a);
- stop_index = (stops[i].offset - *first_offset) / delta_offsets * tex_width;
- if (stop_index == tex_width)
- stop_index = tex_width - 1;
- while (j < stop_index) {
- color = data + j * 4;
- lerp_and_set_color (color,
- (stops[i - 1].offset - *first_offset) / delta_offsets,
- (stops[i].offset - *first_offset) / delta_offsets,
- (float)j / tex_width,
- prev_r, prev_g, prev_b, prev_a,
- r, g, b, a);
- ++j;
- }
-
- /* This is the exact texel for this stop; just set it. */
- color = data + j * 4;
- color[0] = b * a * 255.0;
- color[1] = g * a * 255.0;
- color[2] = r * a * 255.0;
- color[3] = a * 255.0;
- ++j;
-
- prev_r = r;
- prev_g = g;
- prev_b = b;
- prev_a = a;
- }
+ GLubyte *data;
- glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);
- }
+ assert (pattern->n_stops != 0);
+
+ 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);
+ *first_offset = 0.;
+ *last_offset = 1.;
+
+ glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);
glGenTextures (1, tex);
glBindTexture (GL_TEXTURE_1D, *tex);
glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA8, tex_width, 0,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, stops == 0 ? data : 0);
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
- if (stops != 0)
- glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- switch (extend) {
+ switch (pattern->base.extend) {
case CAIRO_EXTEND_NONE:
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
break;
More information about the cairo-commit
mailing list