Present extension changes needed for GL/Vulkan vblank modes
Keith Packard
keithp at keithp.com
Tue Oct 17 04:52:15 UTC 2017
I know, Present was supposed to support all of the GL vblank modes, and
it mostly does, except for the most common case...
In any case, here's a summary of four presentation modes from Vulkan,
how you'd get that with GL and Present and what they mean:
Vulkan GL Present
IMMEDIATE glXSwapIntervalEXT(dpy, draw, 0) PresentPixmap(target-msc=0,
glXSwapBuffers(dpy, draw) PresentOptionAsync)
Display the presented frame immediately, even if
that makes the screen tear.
MAILBOX glXSwapBuffersMscOML(dpy, draw, 0, PresentPixmap(target-msc=0)
0, 0, NULL, NULL, NULL)
Display the presented frame at the next vblank
interval, replacing any frame already queued at
that time.
FIFO glXSwapIntervalEXT(dpy, draw, 1) PresentPixmap(target-msc=previous-msc+1)
glXSwapBuffers(dpy, draw)
Place the frame to be presented at the end of a
queue. At each vblank interval, if the queue is
non-empty, display the first member of the
queue.
FIFO_RELAXED glXSwapIntervalEXT(dpy, draw, -1) PresentPixmap(target-msc=previous-msc+1,
glXSwapBuffers(dpy, draw) PresentOptionAsync)
Place the frame to be presented at the end of a
queue. At each vblank interval, if the queue is
non-empty, display the first member of the
queue. Additionally, if the queue was empty and
no frame switch happened for this vblank
interval, immediately switch to the new frame
From the X protocol perspective, I think we're all set for IMMEDIATE and
MAILBOX. However, I think both FIFO and FIFO_RELAXED cannot be done
because they rely on the client knowing the previous MSC (Media Stream
Counter, or frame counter) value, which the client really isn't going to
know unless it's presenting every frame.
To fix them, I think we need to add relative MSC values to Present,
so we can ask that the X server do the right thing.
PresentOptionRelative
If 'options' contains PresentOptionRelative, then the most
recent actual MSC for a PresentPixmap request to the same
drawable (i.e., the MSC value that would have been reported in
the associated PresentCompleteNotify event) will be added to
MSC
0
a Present(target-msc=1, PresentOptionRelative)
target-msc = 1 + 0 (current drawable msc)
1 a present here
b Present(target-msc=1, PresentOptionRelative)
target-msc = 1 + 1 (previous Present actual MSC)
2 b present here
Oops, we're late
3
c Present(target-msc=1, PresentOptionRelative)
target=msc = 1 + 2 (previous Present actual MSC)
d Present(target-msc=1, PresentOptionRelative)
target=msc = 1 + 4 (previous Present actual MSC)
4 c present here
5 d present here
target-msc.
If no PresentPixmap request has been made to this drawable, then
the current MSC value for the drawable will be added to
target-msc.
FIFO can be done by:
PresentPixmap(target-msc=1, PresentOptionRelative)
FIFO_RELAXED can be done by:
PresentPixmap(target-msc=1, PresentOptionRelative|PresentOptionAsync)
In addition, MAILBOX can be done more naturally by:
PresentPixmap(target-msc=0, PresentOptionRelative)
Ok, so let's make sure it works on paper.
FIFO:
FIFO_RELAXED:
MSC
0
a Present(target-msc=1, PresentOptionRelative|PresentOptionAsync)
target-msc = 1 + 0 (current drawable msc)
1 a present here
b Present(target-msc=1, PresentOptionRelative|PresentOptionAsync)
target-msc = 1 + 1 (previous Present actual MSC)
2 b present here
Oops, we're late
3
c Present(target-msc=1, PresentOptionRelative|PresentOptionAsync)
target=msc = 1 + 2 (previous Present actual MSC)
c present here
d Present(target-msc=1, PresentOptionRelative|PresentOptionAsync)
target=msc = 1 + 3 (previous Present actual MSC)
4 d present here
5
That looks like I want it to; the difference from the current code is
that the FIFO case doesn't skip a frame; with the current code, we'd
skip frame c:
MSC
0
a Present(target-msc=1)
target-msc = 1
1 a present here
b Present(target-msc=2)
target-msc = 2
2 b present here
Oops, we're late
3
c Present(target-msc=3)
target=msc = 3
d Present(target-msc=4)
target=msc = 4
4 d present here
5
Even in the FIFO_RELAXED case, if we miss more than one frame, we're
going to be skipping frames. Now, it's true that the current Mesa code
attempts to adjust the target-msc values based on the actual MSC values
it sees coming back in events, so the target-msc values it uses won't
get arbitrarily out of whack, they'll just get occasionally out of whack
by a frame or two.
Of course, one can argue that you really want the application to be
running in real time and that dropping frames is the correct thing to
do. If so, we already have OML_sync_control that does this; what this
message is about is respecting the semantics of the standard
glXSwapBuffers request.
Coding this up will take very little time; it's just a tiny bit of math
in the PresentPixmap request.
--
-keith
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <https://lists.x.org/archives/xorg-devel/attachments/20171016/b386bab3/attachment.sig>
More information about the xorg-devel
mailing list