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