Bug 11734:
XRender crashes due to NULL pointer from Cairo on SGI O2
(https://bugs.freedesktop.org/show_bug.cgi?id=1173)
is an example of a case where we try to perform an XRender operation on a
surface with a format that was not supported by the XRender extension. By
marking the extension version as -1 on those surfaces, the current checks
for SURFACE_RENDER_HAS_* always correctly return false and prevent us try
to create a Picture with a NULL xrender_format.
A precondition for using the core XCopyArea protocol is that the source
attributes contain only integer translations. However, we failed to apply
any integer translations from the source matrix to the XCopyArea offsets.
This worked prior to 5b97ee6525 as
_cairo_pattern_acquire_surface_for_surface() was careful to only generate
an identity matrix if the pattern matrix only contained an integer
translation (and thus we would use XCopyArea in the xlib backend).
Move the predicate for starting a new glyph elt into a macro so that it
can be shared between _cairo_xlib_surface_emit_glyphs() and
_emit_glyph_chunks() without code duplication.
This reverts commit 0eb0c26474.
The change was too drastic and overlooked some subleties of the old
code, but the main reason for the revert is that it introduced an
ugly duplicated glyph flush block. I'm working on a more incremental
fix.
show-glyphs-many is triggering an assertion failure within xlib. The cause
appears to be that we are submitting an overlong request.
Reviewing the code and comparing with libXrender/src/Glyph.c I found two
points to address.
1. When encountering the first 2-byte, or 4-byte glyph and thus triggering
the recalculation of the current request_size, we did not check that there
was enough room for the expanded request. In case there is not, we need to
emit the current request (before expansion) and reset.
2. Subtleties in how XRenderCompositeText* constructs the binary protocol
buffer require that xGlyphElts are aligned to 32-bit boundaries and that
it inserts an additional xGlyphElt every 252 glyphs when width==1 or
every 254 glyphs for width==2 || width==4. Thus we need to explicitly
compute how many bytes would be required to add this glyph in accordance
with the above.
Considering the complexity (and apparent fragility since we require tight
coupling to XRender) of the code, I'm sure there are more bugs to be
found.
_surfaces_compatible in cairo-xlib-surface returns true for surfaces with
different xrender_format when each has the same depth and no (NULL)
visual.
Common picture formats will not have the same depth, but
it is possible to create a surface with a non-standard xrender_format
having the same depth as another xrender_format with
cairo_xlib_surface_create_with_xrender_format.
Both cairo_xlib_surface_create_with_xrender_format and
_cairo_xlib_surface_create_similar_with_format create surfaces with no
visual.
The same issue exists in the xcb backend.
Fixes bug https://bugs.freedesktop.org/show_bug.cgi?id=16564.
A little bit of sleep and reflection suggested that the use of
device_offset_[xy] was confusing and clone_offset_[xy] more consistent
with the function naming.
Previously the rule for clone_similar() was that the returned surface
had exactly the same size as the original, but only the contents within
the region of interest needed to be copied. This caused failures for very
large images in the xlib-backend (see test/large-source).
The obvious solution to allow cloning only the region of interest seemed
to be to simply set the device offset on the cloned surface. However, this
fails as a) nothing respects the device offset on the surface at that
layer in the compositing stack and b) possibly returning references to the
original source surface provides further confusion by mixing in another
source of device offset.
The second method was to add extra out parameters so that the
device offset could be returned separately and, for example, mixed into
the pattern matrix. Not as elegant, a couple of extra warts to the
interface, but it works - one less XFAIL...
The adjustments done to the pixman matrix also need to be done for
XTransform. Since an XTransform is just a pixman_transform_t with
another name, we can reuse the conversion function.
Cleanup the code somewhat by passing cairo_xlib_display_t around
internally as opposed to a Display and then having to lookup the
corresponding cairo_xlib_display_t each time.
[To get a cairo_xlib_display_t from a Display is a list traversal under
mutex (though the element we're looking for is most likely at the start),
but to get the Display is just a lockless pointer dereference.]
Kill the allocation and linear search of the close display list on remove,
by embedding a list node into the parent structure.
Original patch by Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation.
https://bugzilla.mozilla.org/show_bug.cgi?id=453199#c5
By inspecting all the users of the close display hooks, we can see that
(a) the key is redundant and (b) the data is unique to the hook. This
means we can trim the interface and stop the linear searches as soon as
we've found the correct element.
Validate that we find an appropriate depth for the Xlib surface, before
attempting to create the surface. This was manifesting itself with
XInitImage() failures during _draw_image_surface() (actually detected as
a segmentation fault in XPutPixel() due to an incomplete XImage). So we
also add a couple of asserts to ensure that XInitImage() is successful -
which to the best of our knowledge, they should always be.
Do this by tiling the surface form the solid pattern. The pattern in
turn calls into xlib's create_solid_surface which returns a dithered
pattern.
This can get into infinite loop right now, because of the way solid
surface cache tries to repaint cached surfaces.
Otherwise we can't do dithering. This drastically improves gradient rendering
on 16bit displays, essentially making them indistinguishable from 32bit ones
with a naked eye.
Remove the intermediate rgb333 for PseudoColor and work on the
cube directly. Also upgrade to a 6x6x6 cube instead of 5x5x5.
Do dithering on both PseudoColor and TrueColor, using a 4x4 pattern.
This only affects X servers with no XRender.
Replace a clip rectangle that covers the entire surface with no
clipping as this is quite a common operation when toolkits (i.e. GTK+)
clear surfaces before drawing and avoids a redundant
XRenderSetClipRectangles.
It is possible for an XRender capable surface to use
_cairo_xlib_surface_solid_fill_rectangle() if the surface
HAS_CREATE_PICTURE() && ! HAS_FILL_RECTANGLES(), in which case we need to
handle the surface having no associated visual.
Fixes test/xlib-expose-event.
Instead of allocating the union of all possible pattern types, just
allocate the specific pattern as used by the function in order to trim
the stack space consumption and flag potential misuse.
In order to avoid re-rasterising a glyph that is pending an
XRenderFreeGlyph, we first scan all glyphsets and their arrays of
pending_free_glyphs for a matching glyph. The additional cost of
scanning the extra arrays should be negligble as most fonts will only
have the single array (which we would scan anyway) but we potentially
save an expensive rasterisation and short-lived image surface.
(As suggested by Behdad Esfahbod.)
Someone reported on cairo list that on some system with gcc, he had the
compile-time assertion failing, meaning that the following struct:
typedef struct {
unsigned long index;
union {
struct {
double x;
double y;
} d;
struct {
int x;
int y;
} i;
} p;
} cairo_xlib_glyph_t;
had a different size from:
typedef struct {
unsigned long index;
double x;
double y;
} cairo_glyph_t;
That looks quite a weird thing for a compiler to do. Anyway, rewriting
our struct like this may help in those weird situations:
typedef union {
cairo_glyph_t d;
unsigned long index;
struct {
unsigned long index;
int x;
int y;
} i;
} cairo_xlib_glyph_t;
That's what we do now.
From -1024..15359, to -4096..122887. This still does not fix the
large-font test as that uses a 10000 font. Working on a proper fix
for glyph dropping now.