/* * Copyright © 2013 Keith Packard * Copyright © 2015 Boyan Ding * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of the copyright holders not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no representations * about the suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include "loader_x11.h" /** x11_dri3_open * * Wrapper around xcb_dri3_open */ int x11_dri3_open(xcb_connection_t *conn, xcb_window_t root, uint32_t provider) { xcb_dri3_open_cookie_t cookie; xcb_dri3_open_reply_t *reply; xcb_xfixes_query_version_cookie_t fixes_cookie; xcb_xfixes_query_version_reply_t *fixes_reply; int fd; const xcb_query_extension_reply_t *extension; xcb_prefetch_extension_data(conn, &xcb_dri3_id); extension = xcb_get_extension_data(conn, &xcb_dri3_id); if (!(extension && extension->present)) return -1; cookie = xcb_dri3_open(conn, root, provider); reply = xcb_dri3_open_reply(conn, cookie, NULL); if (!reply || reply->nfd != 1) { free(reply); return -1; } fd = xcb_dri3_open_reply_fds(conn, reply)[0]; free(reply); fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); /* let the server know our xfixes level */ fixes_cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); fixes_reply = xcb_xfixes_query_version_reply(conn, fixes_cookie, NULL); if (fixes_reply->major_version < 2) { close(fd); fd = -1; } free(fixes_reply); return fd; } /* Only request versions of these protocols which we actually support. */ #define DRI3_SUPPORTED_MAJOR 1 #define PRESENT_SUPPORTED_MAJOR 1 #ifdef HAVE_X11_DRM #define DRI3_SUPPORTED_MINOR 2 #define PRESENT_SUPPORTED_MINOR 2 #else #define PRESENT_SUPPORTED_MINOR 0 #define DRI3_SUPPORTED_MINOR 0 #endif bool x11_dri3_check_multibuffer(xcb_connection_t *c, bool *err, bool *explicit_modifiers) { xcb_dri3_query_version_cookie_t dri3_cookie; xcb_dri3_query_version_reply_t *dri3_reply; xcb_present_query_version_cookie_t present_cookie; xcb_present_query_version_reply_t *present_reply; xcb_generic_error_t *error; const xcb_query_extension_reply_t *extension; xcb_prefetch_extension_data(c, &xcb_dri3_id); xcb_prefetch_extension_data(c, &xcb_present_id); extension = xcb_get_extension_data(c, &xcb_dri3_id); if (!(extension && extension->present)) goto error; extension = xcb_get_extension_data(c, &xcb_present_id); if (!(extension && extension->present)) goto error; dri3_cookie = xcb_dri3_query_version(c, DRI3_SUPPORTED_MAJOR, DRI3_SUPPORTED_MINOR); present_cookie = xcb_present_query_version(c, PRESENT_SUPPORTED_MAJOR, PRESENT_SUPPORTED_MINOR); dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error); if (!dri3_reply) { free(error); goto error; } int dri3Major = dri3_reply->major_version; int dri3Minor = dri3_reply->minor_version; free(dri3_reply); present_reply = xcb_present_query_version_reply(c, present_cookie, &error); if (!present_reply) { free(error); goto error; } int presentMajor = present_reply->major_version; int presentMinor = present_reply->minor_version; free(present_reply); #ifdef HAVE_X11_DRM if (presentMajor > 1 || (presentMajor == 1 && presentMinor >= 2)) { *explicit_modifiers = dri3Major > 1 || (dri3Major == 1 && dri3Minor >= 2); if (dri3Major >= 1) return true; } #endif return false; error: *err = true; return false; }