I need to display RAM-based framebuffer for a virtual GPU device that doesn't have real display connected to it. What I have is mmap'ed chunk of memory after DRM_IOCTL_MODE_MAP_DUMB in RGB32 format. Currently I'm using MIT-SHM shared pixmap created via XShmCreatePixmap() like this:
shminfo.shmid = shmget(IPC_PRIVATE, bytes, IPC_CREAT|0777);
shminfo.readOnly = False;
shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
shmctl(shminfo.shmid, IPC_RMID, 0);
XShmAttach(dpy, &shminfo);
XShmCreatePixmap(dpy, window, shminfo.shmaddr, &shminfo, width, height, 24);
and then simply
while (1) {
struct timespec ts = {0, 999999999L / 30};
nanosleep(&ts, NULL);
memcpy(shminfo.shmaddr, mem, bytes);
XCopyArea(dpy, pixmap, window, gc, 0, 0, width, height, 0, 0);
XFlush(dpy);
}
So it loops 30 times per second, doing memcpy followed XCopyArea. The problem is that it uses a lot of CPU: 50% on a powerful machine. Is there any better way? I could think of two possible improvements:
Get rid of memcpy and just pass mmap'ed memory to MIT-SHM but it looks like MIT-SHM API doesn't support this.
Get some kind of 'content changed' notification to get rid of dumb sleeping (but I haven't found anything appropriate).
Any ideas?
Update: Bottleneck is 'memcpy', if removed CPU usage becomes negligible. The problem seems to be that there's no way to share previously mmap'ed memory (if I understood API correctly) so I'm forced to copy whole buffer every time. I've also tried glDrawPixels() and SDL surfaces, both appeared to be even slower than MIT-SHM.
Update: turns out that MIT-SHM isn't well suited for a task like this. It's main purpose is creating buffer and writing (rendering) to it w/o overhead of X IPC. I don't need to write anything but just "forward" existing buffer to X. In this scenario there's no performance difference between shared pixmaps, shared images and regular X images (XCreateImage).
Conclusion: so far I haven't found API that allows rendering existing buffers w/o copying data around every time.
XShmCreatePixmap()/XCopyArea()
andXShmCreateImage()/XShmPutImage()
? – PuringtonXCreateImage()/XPutImage()
? – Purington