[cairo] GL backend work
whatwasthataddress at gmail.com
Thu Jan 7 18:48:30 PST 2010
I've recently been working on the OpenGL backend on a repo hosted on GitHub:
Ive fixed a majority of the GL regressions. There are two main classes of
failures that I understand, but so far cannot fix. A full test summary is
Known failure type #1: The cairo-gl span renderer was pretty badly broken
before I got there. It rendered all spans as black, with the alpha associated
with each span. No creation of a mask and then masking a source was being
done. I changed it to render the source color, using the alpha for each span.
This at least makes tests like ft-text-vertical-layout-type1 look
approximately right, though it's producing incorrect color values. If I
understood better what pixman was doing to combine a span and source color
with a destination color I could fix this. Anyone got any advice on this?
Known failure type #2: Texturing in shaders does not work given the current
use of FBOs. I have no idea why. I have a post in on the opengl.org forums
asking for help. Maybe one of the gurus there can help me fix it. Shaders
are certainly desirable for doing certain things more efficiently, but they
are essentially optional in most cases. However, for cases in which a source
texture is being rendered onto a target texture under extend policy
CAIRO_EXTEND_NONE, a shader is required. This is because CAIRO_EXTEND_NONE is
implemented as GL_CLAMP_TO_BORDER, which is completely appropriate, except
that it can't be done with textures bound to framebuffers as all the textures
are in cairo_gl_surface_t's. Setting a gl_surface's texture border to 1
causes the framebuffer to be incomplete. This is true when using the
EXT_framebuffer_object extension, and when using the framebuffer support in
core GL > 3.0. It's undocumented, but I found it to be consistent, at least
for NVidia GL implementations (and that's a pretty big chunk of the end user
environment space). The only way to simulate the behavior of
GL_CLAMP_TO_BORDER is with a truly trivial shader. I have already implemented
it, but haven't committed it until I get a fix to the shader texturing/FBO
There is a notable gap in the tests w.r.t. cairo_paint() and radial gradient
patterns. This code path doesn't appear to be tested anywhere in the tests.
Everywhere radial gradient patterns are rendered in the tests, it is done via
cairo_fill() instead. Linear gradients are covered. Is this desired
behavior? I'm unfamiliar enough with how Cairo should be used no to know if
this is a useless code path, but when I changed huge-radial to call
cairo_paint() instead of cairo_fill(), the results were the same.
The test summary HTML page reports 415/53/16/0. Note that this fixes one
XFAIL (alpha-similar), and breaks two others (device-offset-fractional and
overlapping-glyphs). This means that the "real" report after changing
*.xfail.png would be 415/49/20/0.
All my testing reflected below was done using NVidia hardware (8800GT,
9800GTX, and 295 GTX), using drivers from 180.x, 185.x, and 190.x series. The
results didn't change across these changes in hardware and drivers. I did a
little testing using Mesa software rendering, which exhibits a few more errors
(including some crashes).
Unless otherwise indicated, each test name below indicates both the argb32 and
The argb32 clip-unbounded test appears to be broken to me (the rgb24 version
passes). Why should the left half of the result be 0-alpha, if the source is
black, 100%-alpha, and the operator is CAIRO_OPERATOR_SOURCE?
Either close enough that it doen't really need fixing, or maybe will be fixed
by fixing the span renderer:
finer-grained-fallbacks (rgb24 only, argb32 passes)
smask (mainly due to a difference in font selection from the reference
smask-text (probably font selection again)
Broken, because of a problem in the span renderer:
Significantly broken, and still in need of investigation:
device-offset-fractional (marked XFAIL, but output has changed)
overlapping-glyphs (marked XFAIL, but output has changed)
Easy to fix, once texturing in shaders is fixed:
In addition to fixing regressions, I added some new functionality. I
implemented several more cases in _cairo_gl_surface_paint(). It only
implemented CAIRO_OPERATOR_CLEAR before. For all supported
CAIRO_OPERATOR_*'s, it now paints: constant color patterns, surface patterns,
and gradient patterns (though these are nonfunctional due to the shader
texturing issue). These code paths are far shorter than the fallback of using
the much more general _cairo_gl_surface_composite(). They do things in a much
smaller number of GL calls, and use shaders where appropriate, such as the
Notes and Concers:
In several places in cairo-gl-surface.c, I've included C++-style "// ..."
comments. I used this form only so that they would stand out from the C-style
"/* ... */" comments. I consider these temporary, thus the break with the
coding conventions, Some of these are notes for myself, but the majority are
potential problems I've spotted in the code. Please have a look and we can
discuss these concerns on-list. Many of them are more requests for
clarification of what's happening at that point in the code -- they're not
necessarily claims of having found a bug.
Once I get the shader texturing thing worked out, I'd like to keep adding to
the implementations of paint, mask, stroke, and fill. I'd really like to
simplify the code paths used to render everything, so that the number of GL
calls is reduced, hopefully making things more efficient, and so that
maintainance (specifically, optimization) is easier. The current
implementations seems to follow what cairo-image-surface.c does, even when
there are GL shortcuts available. I also haven't looked at the glyph code
much at all -- it might do with some simplification as well.
Please have a look at the work so far, and let me know if you see any issues.
More information about the cairo