[cairo] On fallback strategies (was Re: GSoC: Scan converting rasteriser update
Behdad Esfahbod
behdad at behdad.org
Sat Oct 18 11:52:40 PDT 2008
Jeff Muizelaar wrote:
> On Mon, Oct 06, 2008 at 11:40:45AM -0400, Behdad Esfahbod wrote:
>> Carl Worth wrote:
>>> On Wed, 2008-10-01 at 15:19 -0400, Jeff Muizelaar wrote:
>>>> Overall comments:
>>>> - I don't really like the make_span_renderer interface. It might be better if
>>>> instead of relying on the fallback surface, we had helpers that would be called from
>>>> the image surface's fill and stroke methods.
>>> Agreed.
>>>
>>> This approach is a general one that could be applied liberally to
>>> cairo's code base to clean it up considerably. That is, it would be nice
>>> to have explicit code in each backend for each interface, calling into
>>> specific helper functions, rather than just returning UNSUPPORTED and
>>> relying on the fallback code to do something, (which might not be
>>> optimal across all backends). And even if the fallback code doesn't
>>> perform poorly, it makes the code much harder to read.
>> Actually I don't agree. Having to make a call instead of just returning
>> UNSUPPORTED is going to make the code for backends considerably uglier. Right
>> now one does ot even need to implement many of the methods. Without
>> UNSUPPORTED one has to copy paste a lot of cruft, that need to be changed in
>> 10 places everytime the fallback implementation details change.
>
> These implementation details are often important to a backend. For
> example, the fallback path goes through a lot of work to deal with the
> mismatch between SOURCE and CLEAR mask bounding that cairo and
> pixman/XRender have. This wouldn't be necessary on other backends.
>
> The UNSUPPORTED model becomes problematic as soon as a backend wants to
> implement one of these methods previously unimplemented methods.
> Fallbacks are a all-or-nothing choice, so implementing anything that
> uses some of the previous fallback is difficult. This makes adjusting
> the behaviour of a fallback difficult for a backend.
Using UNSUPPORTED does not mean we can't have
_cairo_image_fallback_do_some_part_of_filling_and_just_that().
It's not either/or. Define UNSUPPORTED as calling cairo_surface_fallback_XXX().
> Further, I don't see why one would have to copy paste a lot of cruft
> when we can have a utility function that's called. There's no reason a
> fill() implementation would need to be anything more than a single
> function call.
I'm talking about that single-line function that needs to be copied in 12
different backend files, and modified every time the backend signature changes.
>> I think the idiom is very readable and useful when you grasp it: a function
>> returning cairo_int_status_t can return UNSUPPORTED and not worry about what
>> happens, while one returning cairo_status_t can't. That simple, and a lot can
>> be checked using static analysis.
>
> That's not really true; you do need to worry about what happens. If you
> have a backend that doesn't implement fill() you have to implement
> composite_trapezoids(). composite_trapezoids() certainly isn't the only
> logical operation to implement fill with, a backend end could, for
> example, want composite_spans(), composite_flattened_polygon() or
> composite_non_intersecting_polygon(). We wouldn't want to probe each
> backend for each of these possible operations.
Sure, some operations may be better fallbacked using a function calling helper
functions. But for show_glyphs for example, there's no way to do it cleaner
than using UNSUPPORTED. The way it works currently is:
cairo_surface_show_glyphs:
try surface_backend->show_glyphs
cairo_surface_fallback_show_glyphs
cairo_scaled_font_show_glyphs
try font_backend->show_glyphs
create a mask, add glyphs to it and paint it
Vladimir Vukicevic wrote:
> I agree with Carl here -- having the fallback invoked explicitly in
> the backend would lead to much simpler and clearer backend code. The
> way that it's structured currently, there's magic that happens in
> multiple places, and you have to follow the UNSUPPORTED-returns back
> to wherever they were handled. It's pretty confusing and hard to
> read, and also doesn't allow for some optimizations based on having
> more finer-grained control of when/how to invoke fallback code.
Currently the backend interface has like 15 methods, many backends implement
only five of them. How does adding ten one-line functions make it more readable?
behdad
More information about the cairo
mailing list