Use the cow-snapshotting mechanism to store the meta surface replay (either
to an image inside acquire_source_image() or to a similar surface during
clone_similar()).
Fixes Bug 17971 -- Extreme slowdown for manual convolutions in most
vector backends.
https://bugs.freedesktop.org/show_bug.cgi?id=17971
The meta-surface is a vital tool to record a trace of drawing commands
in-memory. As such it is used throughout cairo.
The value of such a surface is immediately obvious and should be
applicable for many applications. The first such case is by
cairo-test-trace which wants to record the entire graph of drawing commands
that affect a surface in the event of a failure.
Explicitly handle a region clip which represents that the
entire surface is clipped out by passing in a temporary
empty region to the backend set_clip_region() method.
Previously the passed in region may have been NULL even
when clip->all_clipped = TRUE.
Fixes a bug tickled by the clip-all test case which was
brought to light by 394e139213.
Previously the reference to the newly created snapshot was owned by the
containing pattern. The consequence of this was that when the pattern was
destroyed the snapshot was cleaned up which prevent reuse of the snapshot
across multiple pages. Transferring ownership upon attachment of the
snapshot to the target means that the snapshot stays in existence until
the target itself is destroyed or modified *and* the containing pattern
is consumed. Obvious in hindsight.
Provide a mechanism for backends to attach and remove snapshots. This can
be used by backends to provide a cache for _cairo_surface_clone_similar(),
or by the meta-surfaces to only emit a single pattern for each unique
snapshot.
In order to prevent stale data being returned upon a snapshot operation,
if the surface is modified (via the 5 high level operations, and on
notification of external modification) we break the association with any
current snapshot of the surface and thus preserve the current data for
their use.
The number of mime-types attached to a surface is usually small,
typically zero. Therefore it is quicker to do a strcmp() against
each key in the private mime-data array than it is to intern the
string (i.e. compute a hash, search the hash table, and do a final
strcmp).
If the backend cannot create a similar surface to hold the image, then
report back the failure before embarking upon an infinite recursion.
The UNSUPPORTED return should percolate up through the call stack and
trigger a fallback.
As an aide to tracking down the source of uninitialised reads, run
VALGRIND_CHECK_MEM_IS_DEFINED() over the contents of image surfaces at the
boundary between backends, e.g. upon setting a glyph image or acquiring
a source image.
Damian Frank noted
[http://lists.cairographics.org/archives/cairo/2009-May/017095.html]
a performance problem with an older XServer with an
unaccelerated composite - similar problems will be seen with non-XRender
servers which will trigger extraneous fallbacks. The problem he found was
that painting an ARGB32 image onto an RGB24 destination window (using
SOURCE) was going via the RENDER protocol and not core. He was able to
demonstrate that this could be worked around by declaring the pixel data as
an RGB24 image. The issue is that the image is uploaded into a temporary
pixmap of matching depth (i.e. 32 bit for ARGB32 and 24 bit for RGB23
data), however the core protocol can only blit between Drawables of
matching depth - so without the work-around the Drawables are mismatched
and we either need to use RENDER or fallback.
This patch adds a content mask to _cairo_surface_clone_similar() to
provide the extra bit of information to the backends for when it is
possible for them to drop channels from the clone. This is used by the
xlib backend to only create a 24 bit source when blitting to a Window.
Specifically,
cairo_region_union_rect -> cairo_region_union_rectangle
cairo_region_create_rect -> cairo_region_create_rectangle
Also delete cairo_region_clear() which is not that useful.
Usually, rectangles are more useful than boxes, so regions should only
expose rectangles in their public API.
Specifically,
_cairo_region_num_boxes becomes _cairo_region_num_rectangles
_cairo_region_get_box becomes _cairo_region_get_rectangle
Remove the cairo_box_int_t type
The _cairo_region_get_boxes() interface was difficult to use and often
caused unnecessary memory allocation. With _cairo_region_get_box() it
is possible to access the boxes of a region without allocating a big
temporary array.
Move the mime-data into its own array so that it cannot be confused with
user-data and we do not need to hard-code the copy list during
snapshotting. The copy-on-snapshotting code becomes far simpler and will
accommodate all future mime-types.
Keeping mime-data separate from user-data is important due to the
principle of least surprise - the API is different and so it would be
surprising if you queried for user-data and were returned an opaque
mime-data pointer, and vice versa. (Note this should have been prevented
by using interned strings, but conceptually it is cleaner to make the
separation.) Also it aides in trimming the user data arrays which are
linearly searched.
Based on the original patch by Adrian Johnson:
http://cgit.freedesktop.org/~ajohnson/cairo/commit/?h=metadata&id=37e607cc777523ad12a2d214708d79ecbca5b380
Adds an error code replacing CAIRO_STATUS_NO_MEMORY in one case where it
is not really appropriate. CAIRO_STATUS_INVALID_SIZE is used by several
backends that do not support image sizes beyond 2^15 pixels on each side.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
If we are dithering on the Xlib backend we can not simply repaint the
surface used for a solid pattern and must recreate it from scratch.
However, for ordinary XRender usage we do not want to have to pay that
price - so query the backend to see if we can reuse the surface.
A surface will have the chance to use span rendering at cairo_fill()
time by creating a renderer for a specific combination of
pattern/dst/op before the path is scan converted. The protocol is to
first call check_span_renderer() to see if the surface wants to render
with spans and then later call create_span_renderer() to create the
renderer for real once the extents of the path are known.
No backends have an implementation yet.
When computing the bounds of the clip path, we care more for a fast result
than absolute precision as the extents are only used as a guide to trim
the future operations. So computing the extents of the path suffices.
Allow the user to pass in a pre-allocated array and use it if the number
of boxes permits. This eliminates the frequent allocations during clipping
by toolkits.
By using a NULL backend for the error surfaces, instead of a pointer to
the image surface backend end, we save a few lookup/redirections during
dynamic linking.
A limitation of the current API was that the destroy notifier was called
on the mime-data block. This prevents the user from passing in a pointer
to a managed block, for example a mime-data block belonging to a
ref-counted object. We can overcome this by allowing the user to specify
the closure to be used with the destroy notifier.
Instead of doing a full-copy of the mime data (which can be 10K-100K,
or even larger) just copy a reference to the original mime to the
snapshot surface (as suggested by Behdad).
Use the surface user-data array allow to store an arbitrary set of
alternate image representations keyed by an interned string (which
ensures that it has a unique key in the user-visible namespace).
Update the API to mirror that of cairo_surface_set_user_data() [i.e.
return a status indicator] and switch internal users of the mime-data to
the public functions.
Add a "cairo_rectangle_int_t *extents" argument to to the following
backend functions:
paint
mask,
stroke
fill
show_glyphs
show_text_glyphs
This will be used to pass the extents of each operation computed by
the analysis surface to the backend. This is required for implementing
EXTEND_PAD.
No need to copy font options if the similar surface is from the same
backend and no special options have been applied by the user. Doing so
breaks lazy initialisation of backend specific options.
Only copy the pattern if we need to modify it, e.g. preserve a copy in a
snapshot or a soft-mask, or to modify the matrix. Otherwise we can
continue to use the original pattern and mark it as const in order to
generate compiler warnings if we do attempt to write to it.
Adrian Johnson discovered cases where we mistakenly compared the result
of unsigned arithmetic where we need signed quantities. Look for similar
cases in the users of cairo_rectangle_int_t.
After discussing the scaled font locking with Behdad, it transpired that it
is not sufficient for a font to be locked for the lifetime of a scaled glyph,
but that the scaled font's glyph cache must be frozen for the glyph'
lifetime. If the cache is not frozen, then there is a possibility that the
glyph may be evicted before the reference goes out of scope i.e. the glyph
becomes invalid whilst we are trying to use it.
Since the freezing of the cache is the stronger barrier, we remove the
locking/unlocking of the mutex from the backends and instead move the
mutex acquisition into the freeze/thaw routines. Then update the rule on
acquiring glyphs to enforce that the cache is frozen and review the usage
of freeze/thaw by all the backends to ensure that the cache is frozen for
the lifetime of the glyph.