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.
First, XMaxRequestSize returns number of 4-byte words. So multiply by 4 is
needed in all uses. Next, XRenderAddGlyphs uses BIG-REQUEST extension if
available, so when checking for glyph size overflow, we should use
XExtendedMaxRequestSize() first.
Also use the right format when calculating glyph size.
These changes combined, push the biggest font size that can be uploaded to the
server from under 200 to about 5000.
See bug #4339 for history.
Originally reported here:
http://lists.cairographics.org/archives/cairo/2008-May/014032.html
and analyized later in the thread.
Change (font and surface) backend show_glyphs() API to take a
int *remaining_glyphs argument. It's used to communicate to the caller,
by way of setting remaining_glyphs and returning INT_STATUS_UNSUPPORTED,
that some of the glyphs were shown but not the others. The xlib backend
now correctly uses this to handle failure to upload a glyph to the server.
So the large-font test passes now.
An alternative approach could be to add some public value for glyphs
indices that are not shown. -1 perhaps (the xlib backend already uses
that value internally). Then instead of remaining_glyphs, a backend
could simply set glyph indices of glyphs shown to that -1 value.
For every glyph evicted from the cache we would allocate a very small
structure to push onto the xlib work queue. This quickly becomes
noticably for an app that consumes a lot of scaled fonts and glyphs,
e.g. trying to draw text at various angles. So we maintain a small array
of glyphs pending finalisation and issue the XRenderFreeGlyphs() once the
array is full.
During the destruction of every font used with an xlib surface, we send
an XRenderFreeGlyphs() for every single glyph in the cache. These
requests are redundant as the server-side glyphs will be released along
with the XRenderFreeGlyphSet(), so we skip the individual glyph
destruction if the font is marked as finished.