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