Software rendering with XCB: (MIT-SHM + Present) or (dma-buf + DRI3 + Present) or other?

Tristan Cadet <[email protected]> Wed, 4 Mar 2026 00:49:16 +0100
Newsgroups gmane.comp.freedesktop.xcb
Message-ID <CAOjo+TaL=yhFZZyMx-=wW=Z-sBncGifYyckZeGZSG9zTh0ACMA@mail.gmail.com>
--0000000000008bef93064c275afa
Content-Type: text/plain; charset="UTF-8"

Hello,

I am trying to organize an XCB event loop for a software renderer.
By "software renderer" I mean a C function that takes a pointer to a pixel
buffer and writes to the buffer directly.
I want the presentation of the buffer to be efficient and free of tearing
and other artifacts.

(Note: I am relatively new to XCB and low-level rendering, so apologies if
I am misunderstanding some concepts.)

I could not find a guide on writing XCB software renderers, but based on my
investigation, the options are:

Option A) MIT-SHM extension + Present

1. get a pixel buffer: `xcb_shm_create_segment` + `mmap`
2. get a pixmap associated with the buffer: `xcb_shm_create_pixmap`
3. event loop:
     - software render in buffer
     - present with `xcb_present_pixmap`
     - block until `XCB_PRESENT_COMPLETE_NOTIFY` (VSYNC)
     - continue

Questions:
  a) Is it recommended to create the pixel buffer on the client side
(`memfd_create` + `xcb_shm_attach_fd`) or on the server side
(`xcb_shm_create_segment`)?
  b) Is the event loop correctly organized? I heard that I should
double-buffer to avoid tearing, but it does not seem necessary. If I
synchronize rendering to VSYNC (blocking on `XCB_PRESENT_COMPLETE_NOTIFY`
after presenting), I know that when the next frame begins the buffer of the
previous frame has been displayed and is free to render into, so single
buffering should be enough. The only issue I see is if a frame takes too
long to render, in that case the loop blocks until the next VSYNC and
latency doubles to 33ms. To avoid that, it would be helpful to receive a
stream of VSYNC events I can drain (or alternatively I could use a
client-side clock to detect when a frame runs late). Is there a standard
way to approach that for an XCB software renderer?
  c) What is the performance of `xcb_present_pixmap`? I suppose what
matters is the number of frame copies it does? Does it basically do 1 CPU
memcpy of the frame to VRAM?

Option B) dma-buf + DRI3 + Present

1. get a pixel buffer: `memfd_create` + `mmap` + `ioctl` with
`UDMABUF_CREATE`
2. get a pixmap associated with the buffer: `xcb_dri3_pixmap_from_buffer`
3. event loop: same as for MIT-SHM

Questions:
  a) As far as I understand, DRI3 is intended for GPU rendering, so I am
surprised that this works with memfd buffers. Is it just luck or is this a
supported path?
  b) Performance doesn't seem very different from the MIT-SHM approach,
except maybe slightly less CPU usage. dma-buf is supposed to allow passing
buffers directly to devices, but is there any benefit here given that the
backing memory is a memfd rather than VRAM? My current understanding is
that in the best case this turns the CPU copy of the MIT-SHM path into a
slightly cheaper GPU copy?

Option C) DRM dumb buffer

1. get a pointer to a pixel buffer: `xcb_dri3_open` + `ioctl`
`DRM_IOCTL_MODE_CREATE_DUMB`, `DRM_IOCTL_MODE_MAP_DUMB`,
`DRM_IOCTL_PRIME_HANDLE_TO_FD` + `mmap`
2. get a pixmap: same as B)
3. event loop: same as B)

Questions:
  a) So far I get a black window with this approach, is it supposed to work?
  b) Are dumb buffers supposed to enable zero-copy software rendering?
  c) Read performance on the dumb buffer is terrible (6 times worse than
RAM based off quick tests) which I believe is due to write-combined memory.
I have seen suggestions to render in a normal buffer and copy to the dumb
buffer at the end, doesn't that negate the benefit of the DRM dumb buffer?
Is there a better way to use dumb buffers?

---

I also read something about fences, are these only for the GPU path, or are
these (or some other means of synchronization besides Present)
required/recommended for a software renderer?

---

In addition to the above questions, are there any other trade-offs or
points I should pay attention to for an XCB software renderer?
What approach do you think would be best?

---

Thank you

--0000000000008bef93064c275afa
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Hello,<br><br>I am trying to organize an XCB event lo=
op for a software renderer.<br>By &quot;software renderer&quot; I mean a C =
function that takes a pointer to a pixel buffer and writes to the buffer di=
rectly.<br>I want the presentation of the buffer to be efficient and free o=
f tearing and other artifacts.<br><br>(Note: I am relatively new to XCB and=
 low-level rendering, so apologies if I am misunderstanding some concepts.)=
<br><br>I could not find a guide on writing XCB software renderers, but bas=
ed on my investigation, the options are:<br><br>Option A) MIT-SHM extension=
 + Present<br><br>1. get a pixel buffer: `xcb_shm_create_segment` + `mmap`<=
br>2. get a pixmap associated with the buffer: `xcb_shm_create_pixmap`<br>3=
. event loop:<br>=C2=A0 =C2=A0 =C2=A0- software render in buffer<br>=C2=A0 =
=C2=A0 =C2=A0- present with `xcb_present_pixmap`<br>=C2=A0 =C2=A0 =C2=A0- b=
lock until `XCB_PRESENT_COMPLETE_NOTIFY` (VSYNC)<br>=C2=A0 =C2=A0 =C2=A0- c=
ontinue<br><br>Questions:<br>=C2=A0 a) Is it recommended to create the pixe=
l buffer on the client side (`memfd_create` + `xcb_shm_attach_fd`) or on th=
e server side (`xcb_shm_create_segment`)?<br>=C2=A0 b) Is the event loop co=
rrectly organized? I heard that I should double-buffer to avoid tearing, bu=
t it does not seem necessary. If I synchronize rendering to VSYNC (blocking=
 on `XCB_PRESENT_COMPLETE_NOTIFY` after presenting), I know that when the n=
ext frame begins the buffer of the previous frame has been displayed and is=
 free to render into, so single buffering should be enough. The only issue =
I see is if a frame takes too long to render, in that case the loop blocks =
until the next VSYNC and latency doubles to 33ms. To avoid that, it would b=
e helpful to receive a stream of VSYNC events I can drain (or alternatively=
 I could use a client-side clock to detect when a frame runs late). Is ther=
e a standard way to approach that for an XCB software renderer?<br>=C2=A0 c=
) What is the performance of `xcb_present_pixmap`? I suppose what matters i=
s the number of frame copies it does? Does it basically do 1 CPU memcpy of =
the frame to VRAM?<br><br>Option B) dma-buf + DRI3 + Present<br><br>1. get =
a pixel buffer: `memfd_create` + `mmap` + `ioctl` with `UDMABUF_CREATE`<br>=
2. get a pixmap associated with the buffer: `xcb_dri3_pixmap_from_buffer`<b=
r>3. event loop: same as for MIT-SHM<br><br>Questions:<br>=C2=A0 a) As far =
as I understand, DRI3 is intended for GPU rendering, so I am surprised that=
 this works with memfd buffers. Is it just luck or is this a supported path=
?<br>=C2=A0 b) Performance doesn&#39;t seem very different from the MIT-SHM=
 approach, except maybe slightly less CPU usage. dma-buf is supposed to all=
ow passing buffers directly to devices, but is there any benefit here given=
 that the backing memory is a memfd rather than VRAM? My current understand=
ing is that in the best case this turns the CPU copy of the MIT-SHM path in=
to a slightly cheaper GPU copy?<br><br>Option C) DRM dumb buffer<br><br>1. =
get a pointer to a pixel buffer: `xcb_dri3_open` + `ioctl` `DRM_IOCTL_MODE_=
CREATE_DUMB`, `DRM_IOCTL_MODE_MAP_DUMB`, `DRM_IOCTL_PRIME_HANDLE_TO_FD` + `=
mmap`<br>2. get a pixmap: same as B)<br>3. event loop: same as B) <br><br>Q=
uestions:<br>=C2=A0 a) So far I get a black window with this approach, is i=
t supposed to work?<br>=C2=A0 b) Are dumb buffers supposed to enable zero-c=
opy software rendering?<br>=C2=A0 c) Read performance on the dumb buffer is=
 terrible (6 times worse than RAM based off quick tests) which I believe is=
 due to write-combined memory. I have seen suggestions to render in a norma=
l buffer and copy to the dumb buffer at the end, doesn&#39;t that negate th=
e benefit of the DRM dumb buffer? Is there a better way to use dumb buffers=
?<br><br>---<br><br>I also read something about fences, are these only for =
the GPU path, or are these (or some other means of synchronization besides =
Present) required/recommended for a software renderer?<br><br>---<br><br>In=
 addition to the above questions, are there any other trade-offs or points =
I should pay attention to for an XCB software renderer?<br>What approach do=
 you think would be best?<br><br>---<br><br>Thank you<br></div></div>

--0000000000008bef93064c275afa--