[cairo] Pixmap double buffering in Xlib backend

Owen Taylor otaylor at redhat.com
Tue Jul 19 12:46:59 PDT 2005

On Fri, 2005-07-08 at 12:34 -0700, Keith Packard wrote:
> The classic double buffering mechanism in X uses a pixmap to hold the
> window contents. When the window is resized, the pixmap is destroyed and
> a new one created in the new size.
> With the old cairo_set_target_surface call, this was easily replicated
> with cairo; when the window size changed, the old pixmap would be
> destroyed and a new one created and stuffed into any associated cairo_t
> objects.
> Without this call, the code needs to create a new cairo_t object for the
> new pixmap surface.
> However, I cannot figure out how to extract all of the relevant state
> (including saved gstates) from a cairo_t so that they can be loaded into
> the new cairo_t so that the overlying code (which doesn't care that the
> window has been resized) can continue drawing.

There is an "philosophical" question here about whether keeping 
a cairo_t around over multiple expose events and drawing to it makes
sense. The view I've been pushing is that a cairo_t represents the
state of a single drawing operation, which makes the question of 
how you deal with a changing size for the target of a cairo_t 

But I don't think we have to have consensus answer to this question.

> I see two solutions:
>  1) Provide some cloning mechanism to move gstate information to the new
> cairo_t.
>  2) Add a cairo_xlib_set_drawable function so that the targetted
> drawable can be changed at will. This is much more limited than the old
> cairo_set_target_surface function as the backend and format of the
> target surface cannot change, only the drawable itself.

Right now, if you get a cairo_surface_t reference from GTK+ for a 
GdkWindow in the middle of a gdk_window_begin_paint()/end_paint(),
then that gives you a surface that points to the pixmap. After the
operation ends, GTK+ will call cairo_surface_finish() and drawing
to the surface will give you a cairo status.

[ GTK+ won't actually give you the cairo_surface_t directly, but you
  could a handle to it from cairo_get_target() ]

Even if this function is added, I don't think I'll change that: it
would be a bit of a pain to do that with the way GDK is organized,
and I've designed the API to encourage using GdkDrawable rather
than cairo_surface_t in any case.

But it does indicate to me that a cairo_surface_t that retains its
identity across changes in the backing Xlib drawable could be 
a desirable thing to have. 

On the other hand, the idea of copying state from cairo_t to cairo_t
really is unattractive. It doesn't allow any abstraction from the
user of what is going on, since the cairo_t changes. If we really
wanted to handle it at the cairo_t level, I'd rather restore

So, I'm in agreement with the course you suggest of 
cairo_xlib_surface_set_drawable(). Looking at the proposed patch,

+ * cairo_xlib_surface_set_drawable:
+ * @surface: a #cairo_surface_t for the XLib backend
+ * @drawable: the new drawable for the surface
+ *
+ * Informs cairo of a new X Drawable underlying the
+ * surface. The drawable must match the format
+ * of the surface or the results are undefined
+ **/

Needs to also say that drawable must also match the existing
display and screen of the surface. I'd make the wording stronger 
by dropping "or the results are undefined", since that sounds
a bit like the worst that could be expected is misdrawing.

There also may need to be documentation of how this interacts
with mark_dirty() and flush() once we add those functions,
but that probably needs to wait until we add them...

+    /* XXX: and what about this case? */
+    if (surface->owns_pixmap)
+       return;

Definitely an error; the user doesn't have sufficient information
about the results of create_similar() to be able to create a 
new backing drawable for it. 

The implementation itself looks fine to me.

While I don't think it matters much, I think I'd keep set_size()
a separate function. It doesn't hurt anything to have it separate,
it corresponds to the case of drawing to a Window, so why break
compatibility for no reason.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050719/a52bcd94/attachment.pgp

More information about the cairo mailing list