[cairo] Solid pattern caching revisited

Behdad Esfahbod behdad at behdad.org
Fri Apr 13 22:53:28 PDT 2007


Hi,

Given our failed solid pattern surface caching that caused access to the
X server from multiple threads, I've been thinking about how to tackle
that problem, and the other problem that currently an image pattern has
to be transferred to the server every time.  That is, the problem is not
limited to solid patterns only...

Now I think I've came up with a firm proposal.  The solution is twofold:
one fixing the xlib threading issue, the other extending the caching
mechanism to all kind of patterns.  In this message I will propose a fix
to the xlib threading issue, and solid pattern caching only.  In a
followup message I discuss pattern caching for other types of patterns


The xlib problem already exists with scaled fonts.  That is, if a scaled
font is evicted from the cairo cache, it will cause xlib traffic that
may cause the same problems that the solid pattern cache did.  To fix
this and allow caching of patterns, we will introduce a per-display work
queue in cairo-xlib-screen.c, or better yet, separate the display struct
from the screen struct (currently we use a screen=NULL argument for
per-display stuff).  When something should be evicted from the X server,
it will be queued and called back whenever a request to that display is
being processed (either a drawing operation or a XCloseDisplay
callback).  This solves the xlib threading problem.  The queues of
course need to be protected by a per-display mutex.

There are two slightly different semantics that can be implemented when
queuing something for destruction, that is, the callback holds a
reference to the cairo object associated with the server resource, or
not holding such a reference.  If we go for holding the reference, there
is a change of reviving the object from destruction if needed later, but
given that the object has been removed from the cairo cache already,
it's not obvious how to do so.  So, we cannot revive it.  So, whether we
retain a reference or not is not that important.  So it may as well look
like:

  _cairo_xlib_display_queue_work (_cairo_xlib_display_t *display,
                                  _cairo_xlib_display_job_t callback,
                                  int resource);

and used like: 

  _cairo_xlib_display_queue_work (display,
                                  _cairo_xlib_display_free_glyph_set,
                                  scaled_font->surface_private->glyphset);

This is different in _cairo_xlib_add_close_display_hook() in that we
pass cairo objects to close_display callbacks, but the work queue is
used to free server resources when cairo resources are destroyed.  So it
just takes a server resource id.



We want to cache image for all pattern types.  Currently, to get good
performance one has to manually upload an image surface to the server by
painting it to a create_similar()ed surface first before drawing that
many times to an X surface.  With correct caching, this will not be
necessary.

Each pattern type has its own unique properties, so different caching
techniques will be required:

  - Solid patterns:  As discussed in the original solid pattern caching
thread, just caching images per pattern is not effective as new solid
patterns are created all the time.  So a cache like the one that was
committed will work, and the xlib surface is fixed to queue free
operations instead of performing them right away.


That is all for now.  I think it would be natural for Chris Wilson,
given his recent experience with the xlib screen stuff, to implement the
xlib part and then porting Jorn's solid pattern cache to it will be
trivial.


Cheers,
-- 
behdad
http://behdad.org/

"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759





More information about the cairo mailing list