xref: /aosp_15_r20/external/mesa3d/src/x11/loader_x11.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2013 Keith Packard
3  * Copyright © 2015 Boyan Ding
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting documentation, and
9  * that the name of the copyright holders not be used in advertising or
10  * publicity pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no representations
12  * about the suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21  * OF THIS SOFTWARE.
22  */
23 
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <xcb/xcb.h>
29 #include <xcb/dri3.h>
30 #include <xcb/present.h>
31 #include <xcb/xfixes.h>
32 #include "loader_x11.h"
33 /** x11_dri3_open
34  *
35  * Wrapper around xcb_dri3_open
36  */
37 int
x11_dri3_open(xcb_connection_t * conn,xcb_window_t root,uint32_t provider)38 x11_dri3_open(xcb_connection_t *conn,
39                  xcb_window_t root,
40                  uint32_t provider)
41 {
42    xcb_dri3_open_cookie_t       cookie;
43    xcb_dri3_open_reply_t        *reply;
44    xcb_xfixes_query_version_cookie_t fixes_cookie;
45    xcb_xfixes_query_version_reply_t *fixes_reply;
46    int                          fd;
47    const xcb_query_extension_reply_t *extension;
48 
49    xcb_prefetch_extension_data(conn, &xcb_dri3_id);
50    extension = xcb_get_extension_data(conn, &xcb_dri3_id);
51    if (!(extension && extension->present))
52       return -1;
53 
54    cookie = xcb_dri3_open(conn,
55                           root,
56                           provider);
57 
58    reply = xcb_dri3_open_reply(conn, cookie, NULL);
59 
60    if (!reply || reply->nfd != 1) {
61       free(reply);
62       return -1;
63    }
64 
65    fd = xcb_dri3_open_reply_fds(conn, reply)[0];
66    free(reply);
67    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
68 
69    /* let the server know our xfixes level */
70    fixes_cookie = xcb_xfixes_query_version(conn,
71                                            XCB_XFIXES_MAJOR_VERSION,
72                                            XCB_XFIXES_MINOR_VERSION);
73    fixes_reply = xcb_xfixes_query_version_reply(conn, fixes_cookie, NULL);
74    if (fixes_reply->major_version < 2) {
75       close(fd);
76       fd = -1;
77    }
78    free(fixes_reply);
79 
80    return fd;
81 }
82 
83 /* Only request versions of these protocols which we actually support. */
84 #define DRI3_SUPPORTED_MAJOR 1
85 #define PRESENT_SUPPORTED_MAJOR 1
86 
87 #ifdef HAVE_X11_DRM
88 #define DRI3_SUPPORTED_MINOR 2
89 #define PRESENT_SUPPORTED_MINOR 2
90 #else
91 #define PRESENT_SUPPORTED_MINOR 0
92 #define DRI3_SUPPORTED_MINOR 0
93 #endif
94 
95 bool
x11_dri3_check_multibuffer(xcb_connection_t * c,bool * err,bool * explicit_modifiers)96 x11_dri3_check_multibuffer(xcb_connection_t *c, bool *err, bool *explicit_modifiers)
97 {
98    xcb_dri3_query_version_cookie_t      dri3_cookie;
99    xcb_dri3_query_version_reply_t       *dri3_reply;
100    xcb_present_query_version_cookie_t   present_cookie;
101    xcb_present_query_version_reply_t    *present_reply;
102    xcb_generic_error_t                  *error;
103    const xcb_query_extension_reply_t    *extension;
104 
105    xcb_prefetch_extension_data(c, &xcb_dri3_id);
106    xcb_prefetch_extension_data(c, &xcb_present_id);
107 
108    extension = xcb_get_extension_data(c, &xcb_dri3_id);
109    if (!(extension && extension->present))
110       goto error;
111 
112    extension = xcb_get_extension_data(c, &xcb_present_id);
113    if (!(extension && extension->present))
114       goto error;
115 
116    dri3_cookie = xcb_dri3_query_version(c,
117                                         DRI3_SUPPORTED_MAJOR,
118                                         DRI3_SUPPORTED_MINOR);
119    present_cookie = xcb_present_query_version(c,
120                                               PRESENT_SUPPORTED_MAJOR,
121                                               PRESENT_SUPPORTED_MINOR);
122 
123    dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error);
124    if (!dri3_reply) {
125       free(error);
126       goto error;
127    }
128 
129    int dri3Major = dri3_reply->major_version;
130    int dri3Minor = dri3_reply->minor_version;
131    free(dri3_reply);
132 
133    present_reply = xcb_present_query_version_reply(c, present_cookie, &error);
134    if (!present_reply) {
135       free(error);
136       goto error;
137    }
138    int presentMajor = present_reply->major_version;
139    int presentMinor = present_reply->minor_version;
140    free(present_reply);
141 
142 #ifdef HAVE_X11_DRM
143    if (presentMajor > 1 || (presentMajor == 1 && presentMinor >= 2)) {
144       *explicit_modifiers = dri3Major > 1 || (dri3Major == 1 && dri3Minor >= 2);
145       if (dri3Major >= 1)
146          return true;
147    }
148 #endif
149    return false;
150 error:
151    *err = true;
152    return false;
153 }
154