Pushing image transport logic down the stack

Owen Taylor otaylor at redhat.com
Sun Sep 3 14:16:39 PDT 2006


Just dumping out an idea here in case it catches someone's fancy.

A common situation for GDK, for cairo (*), and probably any other system
built on top of Xlib is that you have an image in memory in some
format of your own and you want to copy it onto an X drawable in another
format.

The simplest way to handle it is that you create a temporary image in
memory, you convert into that image, then you call XPutImage().

This involves:
 
 - A copy and format conversion  from your own data to the temporary
   image
 - Possibly a copy from the temporary image to Xlib's outgoing buffer
   (for small images that fit in that buffer)
 - A copy from the outgoing buffer to kernel buffers
 - A copy from the kernel buffer into the X server network buffer
 - A copy from the X server buffer onto the destination drawable

Or, alternatively, you could keep one or more shared memory segments
around, and use XShmPutImage, which gives you:

 - A copy from and format conversion from your own data to the 
   shm buffer
 - A copy from the shm buffer onto the destination drawable

Which looks much better, but first requires you to keep preallocated
shared-memory segments around (GDK keeps around 384k of memory in the
typical case!), and also brings in tricky synchronization issues with
knowing when the X server is done with your buffers.

So, thinking about how to improve the first situation, it occurred
to me that you could have a variant of XPutImage() that instead of
taking an XImage, took a pointer to a function to fill in a temporary
buffer with a portion of the source image.

Advantages:

 - You save one copy when the image is small enough to fit into 
   X's network buffer.

 - For large images, the transport library could use something like
   vmsplice() (http://lwn.net/Articles/181169/) to avoid the copy
   into the network buffer.

 - If some better "zero-copy" (**) way of doing image transfers 
   than XShm was introduced, it could be implemented transparently
   to the higher layers.

Just a thought - perhaps something that could be played around with
in XCB. 

                                           - Owen

(*) Well cairo doesn't actually do this right now ... it just assumes
    that pixman can handle anything the server can, and the server can
    handle anything that pixman can. But there are cases it *should*
    be doing this.

(**) You really want one copy somewhere between the app and where
    the image is written to graphics memory because otherwise you
    kill pipelining, but if you have a format conversion, then that
    can be your copy.

P.S. - you could do similar things for XGetImage() ... but if you were
    doing that, you'd probably want to do it at the same time as
    tackling the broken semantics of XGetImage(). It should just give
    you the data it has, XCopyArea() style instead of erroring out at 
    inconvenient times.





More information about the xorg mailing list