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.
This commit is contained in:
Eric Anholt 2010-02-07 20:26:56 +01:00
parent 3b678a88b0
commit 6542a515f0

View file

@ -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.;