Re: [patch] gl: fix gradient color texture generation

Chris Wilson <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <1343289364_1506@CP5-2952>
On Wed, 25 Jul 2012 22:41:34 +0000, "Henry (Yu) Song - SISA" <[email protected]> wrote:
> commit 143dcad36f057ed2bb4fc2970781a4efc9386602
> Author: Henry Song <[email protected]>
> 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
-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.