[cairo] [patch] gl: fix gradient color texture generation
Chris Wilson
chris at chris-wilson.co.uk
Thu Jul 26 00:56:04 PDT 2012
On Wed, 25 Jul 2012 22:41:34 +0000, "Henry (Yu) Song - SISA" <hsong at sisa.samsung.com> wrote:
> commit 143dcad36f057ed2bb4fc2970781a4efc9386602
> Author: Henry Song <henry.song at samsung.com>
> Date: Wed Jul 25 15:34:52 2012 -0700
>
> gl: (1) increase minimal gradient texture width from to 256.
> (2) set gradient color strip center to be a little offset from pixel
> center
>
> (1) gradient texture width of 8 is too small that results in lost of
> color precision when gradient end/start points are far apart.
>
> (2) due to a "bug" in pixman, we should not set p1.x and p2.x to be
> exact of pixel center - this results in a out-of-bound when pixman
> loops of over stops.
>
> fix test cases: huge-radial, huge-linear.
> bring test case: linear-gradient-large closer to reference image
>
> diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
> index ffb5468..c060ca1 100644
> --- a/src/cairo-gl-gradient.c
> +++ b/src/cairo-gl-gradient.c
> @@ -52,7 +52,12 @@ _cairo_gl_gradient_sample_width (unsigned int n_stops,
> unsigned int n;
> int width;
>
> - width = 8;
> + /* minimal 8 sample width is too small for situation where
> + * gradient start/end points are far apart. In GL backend, the
> + * gl shader picks gradient color by interpolation. If the texture
> + * width is too small, it results in lose of color precision
> + */
But it should only be picking the minimum width if the total variation
is very small. Can you give an example which produces a subpar result
currently?
Elsewhere I have just used a max_texture_size ramp since the cache hit
rate is usually high enough not to worry about the creation cost.
> + width = 256;
> for (n = 1; n < n_stops; n++) {
> double dx = stops[n].offset - stops[n-1].offset;
> double delta, max;
> @@ -80,6 +85,7 @@ _cairo_gl_gradient_sample_width (unsigned int n_stops,
> width = ramp;
> }
>
> + /* increment by 8 is OK */
Maybe rounding to the next pot would be better for more hardware?
> width = (width + 7) & -8;
> return MIN (width, 1024);
> }
> @@ -124,9 +130,17 @@ _cairo_gl_gradient_render (const cairo_gl_context_t *ctx,
> pixman_stops[i].color.alpha = stops[i].color.alpha_short;
> }
>
> - p1.x = _cairo_fixed_16_16_from_double (0.5);
> + /* due to a "bug" in pixman, we should not use exact center of pixel
> + * as the p1.x and p2.x. This is beause pixman generates gradient
> + * color by interpolate two adjacent stops. And the step of
> + * interpolation is computed from p2.x - p1.x. If we have set
> + * at the center of pixel, it results pixman picking stop colors from
> + * out-of-bound stops array. see _gradient_walker_reset () in
> + * pixman-gradient-walker.c
> + */
> + p1.x = _cairo_fixed_16_16_from_double (0.6);
How about pixman_fixed_1 - pixman_fixed_1_2 + pixman_fixed_epsilon
which should be (1 << 16) - (1 << 8) + 1?
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
More information about the cairo
mailing list