glx/dri3: Implement GLX_EXT_swap_control_tear
Not wired up for DRI2 because it would require server-side support, which I'm not especially interested in writing. Fixes: mesa/mesa#96 Reviewed-by: Michel Dänzer <mdaenzer@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6671>
This commit is contained in:
@@ -4,3 +4,4 @@ GL_NV_half_float
|
|||||||
EGL_KHR_swap_buffers_with_damage on X11 (DRI3)
|
EGL_KHR_swap_buffers_with_damage on X11 (DRI3)
|
||||||
VK_PRESENT_MODE_FIFO_RELAXED on X11
|
VK_PRESENT_MODE_FIFO_RELAXED on X11
|
||||||
GLX_EXT_swap_control for DRI2 and DRI3
|
GLX_EXT_swap_control for DRI2 and DRI3
|
||||||
|
GLX_EXT_swap_control_tear for DRI3
|
||||||
|
@@ -742,6 +742,7 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
|
|||||||
extensions = psc->core->getExtensions(psc->driScreen);
|
extensions = psc->core->getExtensions(psc->driScreen);
|
||||||
|
|
||||||
__glXEnableDirectExtension(&psc->base, "GLX_EXT_swap_control");
|
__glXEnableDirectExtension(&psc->base, "GLX_EXT_swap_control");
|
||||||
|
__glXEnableDirectExtension(&psc->base, "GLX_EXT_swap_control_tear");
|
||||||
__glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
|
__glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
|
||||||
__glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
|
__glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
|
||||||
__glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
|
__glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
|
||||||
|
@@ -352,6 +352,10 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
|
|||||||
} else if (attribute == GLX_MAX_SWAP_INTERVAL_EXT) {
|
} else if (attribute == GLX_MAX_SWAP_INTERVAL_EXT) {
|
||||||
*value = INT_MAX;
|
*value = INT_MAX;
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (attribute == GLX_LATE_SWAPS_TEAR_EXT) {
|
||||||
|
*value = __glXExtensionBitIsEnabled(pdraw->psc,
|
||||||
|
EXT_swap_control_tear_bit);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1863,7 +1863,8 @@ glXSwapIntervalEXT(Display *dpy, GLXDrawable drawable, int interval)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interval < 0) {
|
if (interval < 0 &&
|
||||||
|
!__glXExtensionBitIsEnabled(pdraw->psc, EXT_swap_control_tear_bit)) {
|
||||||
__glXSendError(dpy, BadValue, interval, 0, True);
|
__glXSendError(dpy, BadValue, interval, 0, True);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -148,6 +148,7 @@ static const struct extension_info known_glx_extensions[] = {
|
|||||||
{ GLX(EXT_framebuffer_sRGB), VER(0,0), Y, Y, N, N },
|
{ GLX(EXT_framebuffer_sRGB), VER(0,0), Y, Y, N, N },
|
||||||
{ GLX(EXT_import_context), VER(0,0), Y, Y, N, N },
|
{ GLX(EXT_import_context), VER(0,0), Y, Y, N, N },
|
||||||
{ GLX(EXT_swap_control), VER(0,0), Y, N, N, Y },
|
{ GLX(EXT_swap_control), VER(0,0), Y, N, N, Y },
|
||||||
|
{ GLX(EXT_swap_control_tear), VER(0,0), Y, N, N, Y },
|
||||||
{ GLX(EXT_texture_from_pixmap), VER(0,0), Y, N, N, N },
|
{ GLX(EXT_texture_from_pixmap), VER(0,0), Y, N, N, N },
|
||||||
{ GLX(EXT_visual_info), VER(0,0), Y, Y, N, N },
|
{ GLX(EXT_visual_info), VER(0,0), Y, Y, N, N },
|
||||||
{ GLX(EXT_visual_rating), VER(0,0), Y, Y, N, N },
|
{ GLX(EXT_visual_rating), VER(0,0), Y, Y, N, N },
|
||||||
|
@@ -52,6 +52,7 @@ enum
|
|||||||
EXT_framebuffer_sRGB_bit,
|
EXT_framebuffer_sRGB_bit,
|
||||||
EXT_import_context_bit,
|
EXT_import_context_bit,
|
||||||
EXT_swap_control_bit,
|
EXT_swap_control_bit,
|
||||||
|
EXT_swap_control_tear_bit,
|
||||||
EXT_texture_from_pixmap_bit,
|
EXT_texture_from_pixmap_bit,
|
||||||
EXT_visual_info_bit,
|
EXT_visual_info_bit,
|
||||||
EXT_visual_rating_bit,
|
EXT_visual_rating_bit,
|
||||||
|
@@ -969,7 +969,7 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
|
|||||||
*/
|
*/
|
||||||
++draw->send_sbc;
|
++draw->send_sbc;
|
||||||
if (target_msc == 0 && divisor == 0 && remainder == 0)
|
if (target_msc == 0 && divisor == 0 && remainder == 0)
|
||||||
target_msc = draw->msc + draw->swap_interval *
|
target_msc = draw->msc + abs(draw->swap_interval) *
|
||||||
(draw->send_sbc - draw->recv_sbc);
|
(draw->send_sbc - draw->recv_sbc);
|
||||||
else if (divisor == 0 && remainder > 0) {
|
else if (divisor == 0 && remainder > 0) {
|
||||||
/* From the GLX_OML_sync_control spec:
|
/* From the GLX_OML_sync_control spec:
|
||||||
@@ -989,11 +989,19 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
|
|||||||
* "If <interval> is set to a value of 0, buffer swaps are not
|
* "If <interval> is set to a value of 0, buffer swaps are not
|
||||||
* synchronized to a video frame."
|
* synchronized to a video frame."
|
||||||
*
|
*
|
||||||
|
* From GLX_EXT_swap_control_tear:
|
||||||
|
*
|
||||||
|
* "If <interval> is negative, the minimum number of video frames
|
||||||
|
* between buffer swaps is the absolute value of <interval>. In this
|
||||||
|
* case, if abs(<interval>) video frames have already passed from
|
||||||
|
* the previous swap when the swap is ready to be performed, the
|
||||||
|
* swap will occur without synchronization to a video frame."
|
||||||
|
*
|
||||||
* Implementation note: It is possible to enable triple buffering
|
* Implementation note: It is possible to enable triple buffering
|
||||||
* behaviour by not using XCB_PRESENT_OPTION_ASYNC, but this should not be
|
* behaviour by not using XCB_PRESENT_OPTION_ASYNC, but this should not be
|
||||||
* the default.
|
* the default.
|
||||||
*/
|
*/
|
||||||
if (draw->swap_interval == 0)
|
if (draw->swap_interval <= 0)
|
||||||
options |= XCB_PRESENT_OPTION_ASYNC;
|
options |= XCB_PRESENT_OPTION_ASYNC;
|
||||||
|
|
||||||
/* If we need to populate the new back, but need to reuse the back
|
/* If we need to populate the new back, but need to reuse the back
|
||||||
|
Reference in New Issue
Block a user