[cairo] [RFC] Cairo GLES2 and GL_CLAMP_TO_BORDER

Alexandros Frantzis alexandros.frantzis at linaro.org
Fri Feb 18 06:12:31 PST 2011


Hi all,

one of the few things that is remaining in order to make the cairo GL
backend GLES2 compatible, is the replacement of GL_CLAMP_TO_BORDER with
a different method for GLES2 (GL_CLAMP_TO_BORDER is used with
CAIRO_EXTEND_NONE).

GL_CLAMP_TO_BORDER and all border related functionality have been
removed from OpenGL ES 2.0. Unfortunately, there doesn't seem to be an
efficient and straightforward way to provide a similar effect.  We will
probably need to provide different paths for GL and GLES, so that at
least GL performance won't be affected.

As a first quick experiment I tried to see if we could get away with
something like this in the fragment shader:

   uniform bool clamp_to_border;

   float clamp_to_border_factor (vec2 coords, bool clamp_to_border)
   {
       bvec2 out1 = greaterThan (coords, vec2 (1,1));
       bvec2 out2 = lessThan (coords, vec2 (0,0));
       bool do_clamp = (any (out1) || any (out2)) && clamp_to_border;
       return float (!do_clamp);
   }

   main() {
       vec4 texel = texture2D(...)
       gl_FragColor = texel * clamp_to_border_factor (...)
   }

As hacky as this may seem it works quite well for cases when we don't
zoom in enough to feel the effects of the bilinear magnification
filtering. So, this works for most cases (as the test suite proved).

Unfortunately, this approach fails to provide the "blend from texture to
border color" effect that is expected as we zoom in and the GL_LINEAR
magnification filter kicks in (eg filter-bilinear-extents test case).
This happens because:

1. The shader above does too good a job and it aggressively
   clips all fragments outside the texture limits. We want these
   fragments to continue blending gracefully to the border color
   (the clear color).

2. The fragments near the limits on the inside are still a problem. As we
   can't use GL_CLAMP_TO_BORDER we must use another wrapping method. This
   means that the linear interpolation function will get its samples from
   somewhere and that somewhere will not be what we want (the clear color).

Although such an approach is not 100% correct it may prove to be a good
compromise for GLES2 if the cost of better methods is prohibitive.

Another option I am evaluating now is to force GL_NEAREST and perform the
bilinear filtering (plus the clamp to border related tweaks) completely
in the fragment shader (only for CAIRO_EXTEND_NONE, of course). My main
concern is that this is going be too costly (vs built-in GL_LINEAR and
GL_CLAMP_TO_BORDER).

I would appreciate any other ideas on how we can proceed on this.
Perhaps a completely different approach that doesn't need
GL_CLAMP_TO_BORDER to begin with?

I hope that I am overlooking some simple and elegant solution :)

Thanks,
Alexandros


More information about the cairo mailing list