1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2011-2014 Intel Corporation
3*4882a593Smuzhiyun * Copyright © 2017 Red Hat Inc.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person
6*4882a593Smuzhiyun * obtaining a copy of this software and associated documentation
7*4882a593Smuzhiyun * files (the "Software"), to deal in the Software without
8*4882a593Smuzhiyun * restriction, including without limitation the rights to use, copy,
9*4882a593Smuzhiyun * modify, merge, publish, distribute, sublicense, and/or sell copies
10*4882a593Smuzhiyun * of the Software, and to permit persons to whom the Software is
11*4882a593Smuzhiyun * furnished to do so, subject to the following conditions:
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * The above copyright notice and this permission notice (including
14*4882a593Smuzhiyun * the next paragraph) shall be included in all copies or substantial
15*4882a593Smuzhiyun * portions of the Software.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21*4882a593Smuzhiyun * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22*4882a593Smuzhiyun * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*4882a593Smuzhiyun * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * Authors:
27*4882a593Smuzhiyun * Lyude Paul <lyude@redhat.com>
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include "xwayland.h"
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include <fcntl.h>
34*4882a593Smuzhiyun #include <sys/stat.h>
35*4882a593Smuzhiyun #include <xf86drm.h>
36*4882a593Smuzhiyun #include <drm_fourcc.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define MESA_EGL_NO_X11_HEADERS
39*4882a593Smuzhiyun #define EGL_NO_X11
40*4882a593Smuzhiyun #include <gbm.h>
41*4882a593Smuzhiyun #include <glamor_egl.h>
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #include <glamor.h>
44*4882a593Smuzhiyun #include <glamor_context.h>
45*4882a593Smuzhiyun #include <dri3.h>
46*4882a593Smuzhiyun #include "drm-client-protocol.h"
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun struct xwl_gbm_private {
49*4882a593Smuzhiyun char *device_name;
50*4882a593Smuzhiyun struct gbm_device *gbm;
51*4882a593Smuzhiyun struct wl_drm *drm;
52*4882a593Smuzhiyun struct zwp_linux_dmabuf_v1 *dmabuf;
53*4882a593Smuzhiyun int drm_fd;
54*4882a593Smuzhiyun int fd_render_node;
55*4882a593Smuzhiyun Bool drm_authenticated;
56*4882a593Smuzhiyun uint32_t capabilities;
57*4882a593Smuzhiyun int dmabuf_capable;
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun struct xwl_pixmap {
61*4882a593Smuzhiyun struct wl_buffer *buffer;
62*4882a593Smuzhiyun EGLImage image;
63*4882a593Smuzhiyun unsigned int texture;
64*4882a593Smuzhiyun struct gbm_bo *bo;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun static DevPrivateKeyRec xwl_gbm_private_key;
68*4882a593Smuzhiyun static DevPrivateKeyRec xwl_auth_state_private_key;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun static inline struct xwl_gbm_private *
xwl_gbm_get(struct xwl_screen * xwl_screen)71*4882a593Smuzhiyun xwl_gbm_get(struct xwl_screen *xwl_screen)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun return dixLookupPrivate(&xwl_screen->screen->devPrivates,
74*4882a593Smuzhiyun &xwl_gbm_private_key);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun static uint32_t
gbm_format_for_depth(int depth)78*4882a593Smuzhiyun gbm_format_for_depth(int depth)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun switch (depth) {
81*4882a593Smuzhiyun case 16:
82*4882a593Smuzhiyun return GBM_FORMAT_RGB565;
83*4882a593Smuzhiyun case 24:
84*4882a593Smuzhiyun return GBM_FORMAT_XRGB8888;
85*4882a593Smuzhiyun case 30:
86*4882a593Smuzhiyun return GBM_FORMAT_ARGB2101010;
87*4882a593Smuzhiyun default:
88*4882a593Smuzhiyun ErrorF("unexpected depth: %d\n", depth);
89*4882a593Smuzhiyun case 32:
90*4882a593Smuzhiyun return GBM_FORMAT_ARGB8888;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun static uint32_t
wl_drm_format_for_depth(int depth)95*4882a593Smuzhiyun wl_drm_format_for_depth(int depth)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun switch (depth) {
98*4882a593Smuzhiyun case 15:
99*4882a593Smuzhiyun return WL_DRM_FORMAT_XRGB1555;
100*4882a593Smuzhiyun case 16:
101*4882a593Smuzhiyun return WL_DRM_FORMAT_RGB565;
102*4882a593Smuzhiyun case 24:
103*4882a593Smuzhiyun return WL_DRM_FORMAT_XRGB8888;
104*4882a593Smuzhiyun case 30:
105*4882a593Smuzhiyun return WL_DRM_FORMAT_ARGB2101010;
106*4882a593Smuzhiyun default:
107*4882a593Smuzhiyun ErrorF("unexpected depth: %d\n", depth);
108*4882a593Smuzhiyun case 32:
109*4882a593Smuzhiyun return WL_DRM_FORMAT_ARGB8888;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun static char
is_device_path_render_node(const char * device_path)114*4882a593Smuzhiyun is_device_path_render_node (const char *device_path)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun char is_render_node;
117*4882a593Smuzhiyun int fd;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun fd = open(device_path, O_RDWR | O_CLOEXEC);
120*4882a593Smuzhiyun if (fd < 0)
121*4882a593Smuzhiyun return 0;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun is_render_node = (drmGetNodeTypeFromFd(fd) == DRM_NODE_RENDER);
124*4882a593Smuzhiyun close(fd);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun return is_render_node;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun static PixmapPtr
xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen,struct gbm_bo * bo,int depth)130*4882a593Smuzhiyun xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo,
131*4882a593Smuzhiyun int depth)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun PixmapPtr pixmap;
134*4882a593Smuzhiyun struct xwl_pixmap *xwl_pixmap;
135*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(screen);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun xwl_pixmap = malloc(sizeof *xwl_pixmap);
138*4882a593Smuzhiyun if (xwl_pixmap == NULL)
139*4882a593Smuzhiyun return NULL;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun pixmap = glamor_create_pixmap(screen,
142*4882a593Smuzhiyun gbm_bo_get_width(bo),
143*4882a593Smuzhiyun gbm_bo_get_height(bo),
144*4882a593Smuzhiyun depth,
145*4882a593Smuzhiyun GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
146*4882a593Smuzhiyun if (!pixmap) {
147*4882a593Smuzhiyun free(xwl_pixmap);
148*4882a593Smuzhiyun return NULL;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun xwl_glamor_egl_make_current(xwl_screen);
152*4882a593Smuzhiyun xwl_pixmap->bo = bo;
153*4882a593Smuzhiyun xwl_pixmap->buffer = NULL;
154*4882a593Smuzhiyun xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
155*4882a593Smuzhiyun xwl_screen->egl_context,
156*4882a593Smuzhiyun EGL_NATIVE_PIXMAP_KHR,
157*4882a593Smuzhiyun xwl_pixmap->bo, NULL);
158*4882a593Smuzhiyun if (xwl_pixmap->image == EGL_NO_IMAGE_KHR)
159*4882a593Smuzhiyun goto error;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun glGenTextures(1, &xwl_pixmap->texture);
162*4882a593Smuzhiyun glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture);
163*4882a593Smuzhiyun glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
164*4882a593Smuzhiyun glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
167*4882a593Smuzhiyun if (eglGetError() != EGL_SUCCESS)
168*4882a593Smuzhiyun goto error;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun glBindTexture(GL_TEXTURE_2D, 0);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
173*4882a593Smuzhiyun /* `set_pixmap_texture()` may fail silently if the FBO creation failed,
174*4882a593Smuzhiyun * so we check again the texture to be sure it worked.
175*4882a593Smuzhiyun */
176*4882a593Smuzhiyun if (!glamor_get_pixmap_texture(pixmap))
177*4882a593Smuzhiyun goto error;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
180*4882a593Smuzhiyun xwl_pixmap_set_private(pixmap, xwl_pixmap);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun return pixmap;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun error:
185*4882a593Smuzhiyun if (xwl_pixmap->image != EGL_NO_IMAGE_KHR)
186*4882a593Smuzhiyun eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
187*4882a593Smuzhiyun if (pixmap)
188*4882a593Smuzhiyun glamor_destroy_pixmap(pixmap);
189*4882a593Smuzhiyun free(xwl_pixmap);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return NULL;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun static PixmapPtr
xwl_glamor_gbm_create_pixmap(ScreenPtr screen,int width,int height,int depth,unsigned int hint)195*4882a593Smuzhiyun xwl_glamor_gbm_create_pixmap(ScreenPtr screen,
196*4882a593Smuzhiyun int width, int height, int depth,
197*4882a593Smuzhiyun unsigned int hint)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(screen);
200*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
201*4882a593Smuzhiyun struct gbm_bo *bo;
202*4882a593Smuzhiyun PixmapPtr pixmap = NULL;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun if (width > 0 && height > 0 && depth >= 15 &&
205*4882a593Smuzhiyun (hint == 0 ||
206*4882a593Smuzhiyun hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
207*4882a593Smuzhiyun hint == CREATE_PIXMAP_USAGE_SHARED)) {
208*4882a593Smuzhiyun uint32_t format = gbm_format_for_depth(depth);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
211*4882a593Smuzhiyun if (xwl_gbm->dmabuf_capable) {
212*4882a593Smuzhiyun uint32_t num_modifiers;
213*4882a593Smuzhiyun uint64_t *modifiers = NULL;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
216*4882a593Smuzhiyun bo = gbm_bo_create_with_modifiers(xwl_gbm->gbm, width, height,
217*4882a593Smuzhiyun format, modifiers, num_modifiers);
218*4882a593Smuzhiyun free(modifiers);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun else
221*4882a593Smuzhiyun #endif
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun bo = gbm_bo_create(xwl_gbm->gbm, width, height, format,
224*4882a593Smuzhiyun GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (bo) {
228*4882a593Smuzhiyun pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (!pixmap) {
231*4882a593Smuzhiyun gbm_bo_destroy(bo);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun else if (xwl_screen->rootless && hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP) {
234*4882a593Smuzhiyun glamor_clear_pixmap(pixmap);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun if (!pixmap)
240*4882a593Smuzhiyun pixmap = glamor_create_pixmap(screen, width, height, depth, hint);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun return pixmap;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun static Bool
xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)246*4882a593Smuzhiyun xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
249*4882a593Smuzhiyun struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun if (xwl_pixmap && pixmap->refcnt == 1) {
252*4882a593Smuzhiyun if (xwl_pixmap->buffer)
253*4882a593Smuzhiyun wl_buffer_destroy(xwl_pixmap->buffer);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
256*4882a593Smuzhiyun if (xwl_pixmap->bo)
257*4882a593Smuzhiyun gbm_bo_destroy(xwl_pixmap->bo);
258*4882a593Smuzhiyun free(xwl_pixmap);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun return glamor_destroy_pixmap(pixmap);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun static struct wl_buffer *
xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap,Bool * created)265*4882a593Smuzhiyun xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap,
266*4882a593Smuzhiyun Bool *created)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
269*4882a593Smuzhiyun struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
270*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
271*4882a593Smuzhiyun unsigned short width = pixmap->drawable.width;
272*4882a593Smuzhiyun unsigned short height = pixmap->drawable.height;
273*4882a593Smuzhiyun uint32_t format;
274*4882a593Smuzhiyun struct xwl_format *xwl_format = NULL;
275*4882a593Smuzhiyun Bool modifier_supported = FALSE;
276*4882a593Smuzhiyun int prime_fd;
277*4882a593Smuzhiyun int num_planes;
278*4882a593Smuzhiyun uint32_t strides[4];
279*4882a593Smuzhiyun uint32_t offsets[4];
280*4882a593Smuzhiyun uint64_t modifier;
281*4882a593Smuzhiyun int i;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (xwl_pixmap == NULL)
284*4882a593Smuzhiyun return NULL;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (xwl_pixmap->buffer) {
287*4882a593Smuzhiyun /* Buffer already exists. Return it and inform caller if interested. */
288*4882a593Smuzhiyun if (created)
289*4882a593Smuzhiyun *created = FALSE;
290*4882a593Smuzhiyun return xwl_pixmap->buffer;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun /* Buffer does not exist yet. Create now and inform caller if interested. */
294*4882a593Smuzhiyun if (created)
295*4882a593Smuzhiyun *created = TRUE;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (!xwl_pixmap->bo)
298*4882a593Smuzhiyun return NULL;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun format = wl_drm_format_for_depth(pixmap->drawable.depth);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
303*4882a593Smuzhiyun if (prime_fd == -1)
304*4882a593Smuzhiyun return NULL;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
307*4882a593Smuzhiyun num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo);
308*4882a593Smuzhiyun modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
309*4882a593Smuzhiyun for (i = 0; i < num_planes; i++) {
310*4882a593Smuzhiyun strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
311*4882a593Smuzhiyun offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun #else
314*4882a593Smuzhiyun num_planes = 1;
315*4882a593Smuzhiyun modifier = DRM_FORMAT_MOD_INVALID;
316*4882a593Smuzhiyun strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
317*4882a593Smuzhiyun offsets[0] = 0;
318*4882a593Smuzhiyun #endif
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun for (i = 0; i < xwl_screen->num_formats; i++) {
321*4882a593Smuzhiyun if (xwl_screen->formats[i].format == format) {
322*4882a593Smuzhiyun xwl_format = &xwl_screen->formats[i];
323*4882a593Smuzhiyun break;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun if (xwl_format) {
328*4882a593Smuzhiyun for (i = 0; i < xwl_format->num_modifiers; i++) {
329*4882a593Smuzhiyun if (xwl_format->modifiers[i] == modifier) {
330*4882a593Smuzhiyun modifier_supported = TRUE;
331*4882a593Smuzhiyun break;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if (xwl_gbm->dmabuf && modifier_supported) {
337*4882a593Smuzhiyun struct zwp_linux_buffer_params_v1 *params;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun params = zwp_linux_dmabuf_v1_create_params(xwl_gbm->dmabuf);
340*4882a593Smuzhiyun for (i = 0; i < num_planes; i++) {
341*4882a593Smuzhiyun zwp_linux_buffer_params_v1_add(params, prime_fd, i,
342*4882a593Smuzhiyun offsets[i], strides[i],
343*4882a593Smuzhiyun modifier >> 32, modifier & 0xffffffff);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun xwl_pixmap->buffer =
347*4882a593Smuzhiyun zwp_linux_buffer_params_v1_create_immed(params, width, height,
348*4882a593Smuzhiyun format, 0);
349*4882a593Smuzhiyun zwp_linux_buffer_params_v1_destroy(params);
350*4882a593Smuzhiyun } else if (num_planes == 1) {
351*4882a593Smuzhiyun xwl_pixmap->buffer =
352*4882a593Smuzhiyun wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fd, width, height,
353*4882a593Smuzhiyun format,
354*4882a593Smuzhiyun 0, gbm_bo_get_stride(xwl_pixmap->bo),
355*4882a593Smuzhiyun 0, 0,
356*4882a593Smuzhiyun 0, 0);
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun close(prime_fd);
360*4882a593Smuzhiyun return xwl_pixmap->buffer;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun static void
xwl_glamor_gbm_cleanup(struct xwl_screen * xwl_screen)364*4882a593Smuzhiyun xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if (xwl_gbm->device_name)
369*4882a593Smuzhiyun free(xwl_gbm->device_name);
370*4882a593Smuzhiyun if (xwl_gbm->drm_fd)
371*4882a593Smuzhiyun close(xwl_gbm->drm_fd);
372*4882a593Smuzhiyun if (xwl_gbm->drm)
373*4882a593Smuzhiyun wl_drm_destroy(xwl_gbm->drm);
374*4882a593Smuzhiyun if (xwl_gbm->gbm)
375*4882a593Smuzhiyun gbm_device_destroy(xwl_gbm->gbm);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun free(xwl_gbm);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun struct xwl_auth_state {
381*4882a593Smuzhiyun int fd;
382*4882a593Smuzhiyun ClientPtr client;
383*4882a593Smuzhiyun struct wl_callback *callback;
384*4882a593Smuzhiyun };
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun static void
free_xwl_auth_state(ClientPtr pClient,struct xwl_auth_state * state)387*4882a593Smuzhiyun free_xwl_auth_state(ClientPtr pClient, struct xwl_auth_state *state)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun dixSetPrivate(&pClient->devPrivates, &xwl_auth_state_private_key, NULL);
390*4882a593Smuzhiyun if (state) {
391*4882a593Smuzhiyun wl_callback_destroy(state->callback);
392*4882a593Smuzhiyun free(state);
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun static void
xwl_auth_state_client_callback(CallbackListPtr * pcbl,void * unused,void * data)397*4882a593Smuzhiyun xwl_auth_state_client_callback(CallbackListPtr *pcbl, void *unused, void *data)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
400*4882a593Smuzhiyun ClientPtr pClient = clientinfo->client;
401*4882a593Smuzhiyun struct xwl_auth_state *state;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun switch (pClient->clientState) {
404*4882a593Smuzhiyun case ClientStateGone:
405*4882a593Smuzhiyun case ClientStateRetained:
406*4882a593Smuzhiyun state = dixLookupPrivate(&pClient->devPrivates,
407*4882a593Smuzhiyun &xwl_auth_state_private_key);
408*4882a593Smuzhiyun free_xwl_auth_state(pClient, state);
409*4882a593Smuzhiyun break;
410*4882a593Smuzhiyun default:
411*4882a593Smuzhiyun break;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun static void
sync_callback(void * data,struct wl_callback * callback,uint32_t serial)416*4882a593Smuzhiyun sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun struct xwl_auth_state *state = data;
419*4882a593Smuzhiyun ClientPtr client = state->client;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun /* if the client is gone, the callback is cancelled so it's safe to
422*4882a593Smuzhiyun * assume the client is still in ClientStateRunning at this point...
423*4882a593Smuzhiyun */
424*4882a593Smuzhiyun dri3_send_open_reply(client, state->fd);
425*4882a593Smuzhiyun AttendClient(client);
426*4882a593Smuzhiyun free_xwl_auth_state(client, state);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun static const struct wl_callback_listener sync_listener = {
430*4882a593Smuzhiyun sync_callback
431*4882a593Smuzhiyun };
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun static int
xwl_dri3_open_client(ClientPtr client,ScreenPtr screen,RRProviderPtr provider,int * pfd)434*4882a593Smuzhiyun xwl_dri3_open_client(ClientPtr client,
435*4882a593Smuzhiyun ScreenPtr screen,
436*4882a593Smuzhiyun RRProviderPtr provider,
437*4882a593Smuzhiyun int *pfd)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(screen);
440*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
441*4882a593Smuzhiyun struct xwl_auth_state *state;
442*4882a593Smuzhiyun drm_magic_t magic;
443*4882a593Smuzhiyun int fd;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC);
446*4882a593Smuzhiyun if (fd < 0)
447*4882a593Smuzhiyun return BadAlloc;
448*4882a593Smuzhiyun if (xwl_gbm->fd_render_node) {
449*4882a593Smuzhiyun *pfd = fd;
450*4882a593Smuzhiyun return Success;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun state = malloc(sizeof *state);
454*4882a593Smuzhiyun if (state == NULL) {
455*4882a593Smuzhiyun close(fd);
456*4882a593Smuzhiyun return BadAlloc;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun state->client = client;
460*4882a593Smuzhiyun state->fd = fd;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun if (drmGetMagic(state->fd, &magic) < 0) {
463*4882a593Smuzhiyun close(state->fd);
464*4882a593Smuzhiyun free(state);
465*4882a593Smuzhiyun return BadMatch;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun wl_drm_authenticate(xwl_gbm->drm, magic);
469*4882a593Smuzhiyun state->callback = wl_display_sync(xwl_screen->display);
470*4882a593Smuzhiyun wl_callback_add_listener(state->callback, &sync_listener, state);
471*4882a593Smuzhiyun dixSetPrivate(&client->devPrivates, &xwl_auth_state_private_key, state);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun IgnoreClient(client);
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun return Success;
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun _X_EXPORT PixmapPtr
glamor_pixmap_from_fds(ScreenPtr screen,CARD8 num_fds,const int * fds,CARD16 width,CARD16 height,const CARD32 * strides,const CARD32 * offsets,CARD8 depth,CARD8 bpp,uint64_t modifier)479*4882a593Smuzhiyun glamor_pixmap_from_fds(ScreenPtr screen, CARD8 num_fds, const int *fds,
480*4882a593Smuzhiyun CARD16 width, CARD16 height,
481*4882a593Smuzhiyun const CARD32 *strides, const CARD32 *offsets,
482*4882a593Smuzhiyun CARD8 depth, CARD8 bpp, uint64_t modifier)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(screen);
485*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
486*4882a593Smuzhiyun struct gbm_bo *bo = NULL;
487*4882a593Smuzhiyun PixmapPtr pixmap;
488*4882a593Smuzhiyun int i;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun if (width == 0 || height == 0 || num_fds == 0 ||
491*4882a593Smuzhiyun depth < 15 || bpp != BitsPerPixel(depth) ||
492*4882a593Smuzhiyun strides[0] < width * bpp / 8)
493*4882a593Smuzhiyun goto error;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (xwl_gbm->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) {
496*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
497*4882a593Smuzhiyun struct gbm_import_fd_modifier_data data;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun data.width = width;
500*4882a593Smuzhiyun data.height = height;
501*4882a593Smuzhiyun data.num_fds = num_fds;
502*4882a593Smuzhiyun data.format = gbm_format_for_depth(depth);
503*4882a593Smuzhiyun data.modifier = modifier;
504*4882a593Smuzhiyun for (i = 0; i < num_fds; i++) {
505*4882a593Smuzhiyun data.fds[i] = fds[i];
506*4882a593Smuzhiyun data.strides[i] = strides[i];
507*4882a593Smuzhiyun data.offsets[i] = offsets[i];
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD_MODIFIER, &data,
510*4882a593Smuzhiyun GBM_BO_USE_RENDERING);
511*4882a593Smuzhiyun #endif
512*4882a593Smuzhiyun } else if (num_fds == 1) {
513*4882a593Smuzhiyun struct gbm_import_fd_data data;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun data.fd = fds[0];
516*4882a593Smuzhiyun data.width = width;
517*4882a593Smuzhiyun data.height = height;
518*4882a593Smuzhiyun data.stride = strides[0];
519*4882a593Smuzhiyun data.format = gbm_format_for_depth(depth);
520*4882a593Smuzhiyun bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD, &data,
521*4882a593Smuzhiyun GBM_BO_USE_RENDERING);
522*4882a593Smuzhiyun } else {
523*4882a593Smuzhiyun goto error;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (bo == NULL)
527*4882a593Smuzhiyun goto error;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
530*4882a593Smuzhiyun if (pixmap == NULL) {
531*4882a593Smuzhiyun gbm_bo_destroy(bo);
532*4882a593Smuzhiyun goto error;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun return pixmap;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun error:
538*4882a593Smuzhiyun return NULL;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun _X_EXPORT int
glamor_egl_fds_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,int * fds,uint32_t * strides,uint32_t * offsets,uint64_t * modifier)542*4882a593Smuzhiyun glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
543*4882a593Smuzhiyun uint32_t *strides, uint32_t *offsets,
544*4882a593Smuzhiyun uint64_t *modifier)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun struct xwl_pixmap *xwl_pixmap;
547*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
548*4882a593Smuzhiyun uint32_t num_fds;
549*4882a593Smuzhiyun int i;
550*4882a593Smuzhiyun #endif
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun xwl_pixmap = xwl_pixmap_get(pixmap);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun if (xwl_pixmap == NULL)
555*4882a593Smuzhiyun return 0;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (!xwl_pixmap->bo)
558*4882a593Smuzhiyun return 0;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
561*4882a593Smuzhiyun num_fds = gbm_bo_get_plane_count(xwl_pixmap->bo);
562*4882a593Smuzhiyun *modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun for (i = 0; i < num_fds; i++) {
565*4882a593Smuzhiyun fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
566*4882a593Smuzhiyun strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
567*4882a593Smuzhiyun offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun return num_fds;
571*4882a593Smuzhiyun #else
572*4882a593Smuzhiyun *modifier = DRM_FORMAT_MOD_INVALID;
573*4882a593Smuzhiyun fds[0] = gbm_bo_get_fd(xwl_pixmap->bo);
574*4882a593Smuzhiyun strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
575*4882a593Smuzhiyun offsets[0] = 0;
576*4882a593Smuzhiyun return 1;
577*4882a593Smuzhiyun #endif
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* Not actually used, just defined here so there's something for
581*4882a593Smuzhiyun * _glamor_egl_fds_from_pixmap() to link against
582*4882a593Smuzhiyun */
583*4882a593Smuzhiyun _X_EXPORT int
glamor_egl_fd_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)584*4882a593Smuzhiyun glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
585*4882a593Smuzhiyun CARD16 *stride, CARD32 *size)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun return -1;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun _X_EXPORT struct gbm_bo *
glamor_gbm_bo_from_pixmap(ScreenPtr screen,PixmapPtr pixmap)591*4882a593Smuzhiyun glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun return NULL;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun _X_EXPORT Bool
glamor_get_formats(ScreenPtr screen,CARD32 * num_formats,CARD32 ** formats)597*4882a593Smuzhiyun glamor_get_formats(ScreenPtr screen,
598*4882a593Smuzhiyun CARD32 *num_formats, CARD32 **formats)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(screen);
601*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
602*4882a593Smuzhiyun int i;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun /* Explicitly zero the count as the caller may ignore the return value */
605*4882a593Smuzhiyun *num_formats = 0;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
608*4882a593Smuzhiyun return FALSE;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun if (xwl_screen->num_formats == 0)
611*4882a593Smuzhiyun return TRUE;
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
614*4882a593Smuzhiyun if (*formats == NULL)
615*4882a593Smuzhiyun return FALSE;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun for (i = 0; i < xwl_screen->num_formats; i++)
618*4882a593Smuzhiyun (*formats)[i] = xwl_screen->formats[i].format;
619*4882a593Smuzhiyun *num_formats = xwl_screen->num_formats;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun return TRUE;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun _X_EXPORT Bool
glamor_get_modifiers(ScreenPtr screen,uint32_t format,uint32_t * num_modifiers,uint64_t ** modifiers)625*4882a593Smuzhiyun glamor_get_modifiers(ScreenPtr screen, uint32_t format,
626*4882a593Smuzhiyun uint32_t *num_modifiers, uint64_t **modifiers)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_screen_get(screen);
629*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
630*4882a593Smuzhiyun struct xwl_format *xwl_format = NULL;
631*4882a593Smuzhiyun int i;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun /* Explicitly zero the count as the caller may ignore the return value */
634*4882a593Smuzhiyun *num_modifiers = 0;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
637*4882a593Smuzhiyun return FALSE;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (xwl_screen->num_formats == 0)
640*4882a593Smuzhiyun return TRUE;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun for (i = 0; i < xwl_screen->num_formats; i++) {
643*4882a593Smuzhiyun if (xwl_screen->formats[i].format == format) {
644*4882a593Smuzhiyun xwl_format = &xwl_screen->formats[i];
645*4882a593Smuzhiyun break;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun if (!xwl_format)
650*4882a593Smuzhiyun return FALSE;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
653*4882a593Smuzhiyun if (*modifiers == NULL)
654*4882a593Smuzhiyun return FALSE;
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun for (i = 0; i < xwl_format->num_modifiers; i++)
657*4882a593Smuzhiyun (*modifiers)[i] = xwl_format->modifiers[i];
658*4882a593Smuzhiyun *num_modifiers = xwl_format->num_modifiers;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun return TRUE;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun static const dri3_screen_info_rec xwl_dri3_info = {
664*4882a593Smuzhiyun .version = 2,
665*4882a593Smuzhiyun .open = NULL,
666*4882a593Smuzhiyun .pixmap_from_fds = glamor_pixmap_from_fds,
667*4882a593Smuzhiyun .fds_from_pixmap = glamor_fds_from_pixmap,
668*4882a593Smuzhiyun .open_client = xwl_dri3_open_client,
669*4882a593Smuzhiyun .get_formats = glamor_get_formats,
670*4882a593Smuzhiyun .get_modifiers = glamor_get_modifiers,
671*4882a593Smuzhiyun .get_drawable_modifiers = glamor_get_drawable_modifiers,
672*4882a593Smuzhiyun };
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun static const char *
get_render_node_path_for_device(const drmDevicePtr drm_device,const char * device_path)675*4882a593Smuzhiyun get_render_node_path_for_device(const drmDevicePtr drm_device,
676*4882a593Smuzhiyun const char *device_path)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun char *render_node_path = NULL;
679*4882a593Smuzhiyun char device_found = 0;
680*4882a593Smuzhiyun int i;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun for (i = 0; i < DRM_NODE_MAX; i++) {
683*4882a593Smuzhiyun if ((drm_device->available_nodes & (1 << i)) == 0)
684*4882a593Smuzhiyun continue;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (!strcmp (device_path, drm_device->nodes[i]))
687*4882a593Smuzhiyun device_found = 1;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun if (is_device_path_render_node(drm_device->nodes[i]))
690*4882a593Smuzhiyun render_node_path = drm_device->nodes[i];
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun if (device_found && render_node_path)
693*4882a593Smuzhiyun return render_node_path;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun return NULL;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun static char *
get_render_node_path(const char * device_path)700*4882a593Smuzhiyun get_render_node_path(const char *device_path)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun drmDevicePtr *devices = NULL;
703*4882a593Smuzhiyun char *render_node_path = NULL;
704*4882a593Smuzhiyun int i, n_devices, max_devices;
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun max_devices = drmGetDevices2(0, NULL, 0);
707*4882a593Smuzhiyun if (max_devices <= 0)
708*4882a593Smuzhiyun goto out;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun devices = calloc(max_devices, sizeof(drmDevicePtr));
711*4882a593Smuzhiyun if (!devices)
712*4882a593Smuzhiyun goto out;
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun n_devices = drmGetDevices2(0, devices, max_devices);
715*4882a593Smuzhiyun if (n_devices < 0)
716*4882a593Smuzhiyun goto out;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun for (i = 0; i < n_devices; i++) {
719*4882a593Smuzhiyun const char *node_path = get_render_node_path_for_device(devices[i],
720*4882a593Smuzhiyun device_path);
721*4882a593Smuzhiyun if (node_path) {
722*4882a593Smuzhiyun render_node_path = strdup(node_path);
723*4882a593Smuzhiyun break;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun out:
728*4882a593Smuzhiyun free(devices);
729*4882a593Smuzhiyun return render_node_path;
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun static void
xwl_drm_handle_device(void * data,struct wl_drm * drm,const char * device)733*4882a593Smuzhiyun xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
734*4882a593Smuzhiyun {
735*4882a593Smuzhiyun struct xwl_screen *xwl_screen = data;
736*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
737*4882a593Smuzhiyun drm_magic_t magic;
738*4882a593Smuzhiyun char *render_node_path = NULL;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun if (!is_device_path_render_node(device))
741*4882a593Smuzhiyun render_node_path = get_render_node_path(device);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun if (render_node_path)
744*4882a593Smuzhiyun xwl_gbm->device_name = render_node_path;
745*4882a593Smuzhiyun else
746*4882a593Smuzhiyun xwl_gbm->device_name = strdup(device);
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun if (!xwl_gbm->device_name) {
749*4882a593Smuzhiyun xwl_glamor_gbm_cleanup(xwl_screen);
750*4882a593Smuzhiyun return;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun xwl_gbm->drm_fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC);
754*4882a593Smuzhiyun if (xwl_gbm->drm_fd == -1) {
755*4882a593Smuzhiyun ErrorF("wayland-egl: could not open %s (%s)\n",
756*4882a593Smuzhiyun xwl_gbm->device_name, strerror(errno));
757*4882a593Smuzhiyun xwl_glamor_gbm_cleanup(xwl_screen);
758*4882a593Smuzhiyun return;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (drmGetNodeTypeFromFd(xwl_gbm->drm_fd) == DRM_NODE_RENDER) {
762*4882a593Smuzhiyun xwl_gbm->fd_render_node = 1;
763*4882a593Smuzhiyun xwl_screen->expecting_event--;
764*4882a593Smuzhiyun } else {
765*4882a593Smuzhiyun drmGetMagic(xwl_gbm->drm_fd, &magic);
766*4882a593Smuzhiyun wl_drm_authenticate(xwl_gbm->drm, magic);
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun static void
xwl_drm_handle_format(void * data,struct wl_drm * drm,uint32_t format)771*4882a593Smuzhiyun xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun static void
xwl_drm_handle_authenticated(void * data,struct wl_drm * drm)776*4882a593Smuzhiyun xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun struct xwl_screen *xwl_screen = data;
779*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun xwl_gbm->drm_authenticated = TRUE;
782*4882a593Smuzhiyun xwl_screen->expecting_event--;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun static void
xwl_drm_handle_capabilities(void * data,struct wl_drm * drm,uint32_t value)786*4882a593Smuzhiyun xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun xwl_gbm_get(data)->capabilities = value;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun static const struct wl_drm_listener xwl_drm_listener = {
792*4882a593Smuzhiyun xwl_drm_handle_device,
793*4882a593Smuzhiyun xwl_drm_handle_format,
794*4882a593Smuzhiyun xwl_drm_handle_authenticated,
795*4882a593Smuzhiyun xwl_drm_handle_capabilities
796*4882a593Smuzhiyun };
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun static void
xwl_dmabuf_handle_format(void * data,struct zwp_linux_dmabuf_v1 * dmabuf,uint32_t format)799*4882a593Smuzhiyun xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
800*4882a593Smuzhiyun uint32_t format)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun static void
xwl_dmabuf_handle_modifier(void * data,struct zwp_linux_dmabuf_v1 * dmabuf,uint32_t format,uint32_t modifier_hi,uint32_t modifier_lo)805*4882a593Smuzhiyun xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
806*4882a593Smuzhiyun uint32_t format, uint32_t modifier_hi,
807*4882a593Smuzhiyun uint32_t modifier_lo)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun struct xwl_screen *xwl_screen = data;
810*4882a593Smuzhiyun struct xwl_format *xwl_format = NULL;
811*4882a593Smuzhiyun int i;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun if (modifier_hi == (DRM_FORMAT_MOD_INVALID >> 32) &&
814*4882a593Smuzhiyun modifier_lo == (DRM_FORMAT_MOD_INVALID & 0xffffffff))
815*4882a593Smuzhiyun return;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun for (i = 0; i < xwl_screen->num_formats; i++) {
818*4882a593Smuzhiyun if (xwl_screen->formats[i].format == format) {
819*4882a593Smuzhiyun xwl_format = &xwl_screen->formats[i];
820*4882a593Smuzhiyun break;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (xwl_format == NULL) {
825*4882a593Smuzhiyun xwl_screen->num_formats++;
826*4882a593Smuzhiyun xwl_screen->formats = realloc(xwl_screen->formats,
827*4882a593Smuzhiyun xwl_screen->num_formats * sizeof(*xwl_format));
828*4882a593Smuzhiyun if (!xwl_screen->formats)
829*4882a593Smuzhiyun return;
830*4882a593Smuzhiyun xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
831*4882a593Smuzhiyun xwl_format->format = format;
832*4882a593Smuzhiyun xwl_format->num_modifiers = 0;
833*4882a593Smuzhiyun xwl_format->modifiers = NULL;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun xwl_format->num_modifiers++;
837*4882a593Smuzhiyun xwl_format->modifiers = realloc(xwl_format->modifiers,
838*4882a593Smuzhiyun xwl_format->num_modifiers * sizeof(uint64_t));
839*4882a593Smuzhiyun if (!xwl_format->modifiers)
840*4882a593Smuzhiyun return;
841*4882a593Smuzhiyun xwl_format->modifiers[xwl_format->num_modifiers - 1] = (uint64_t) modifier_lo;
842*4882a593Smuzhiyun xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
846*4882a593Smuzhiyun .format = xwl_dmabuf_handle_format,
847*4882a593Smuzhiyun .modifier = xwl_dmabuf_handle_modifier
848*4882a593Smuzhiyun };
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun Bool
xwl_screen_set_drm_interface(struct xwl_screen * xwl_screen,uint32_t id,uint32_t version)851*4882a593Smuzhiyun xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
852*4882a593Smuzhiyun uint32_t id, uint32_t version)
853*4882a593Smuzhiyun {
854*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun if (version < 2)
857*4882a593Smuzhiyun return FALSE;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun xwl_gbm->drm =
860*4882a593Smuzhiyun wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2);
861*4882a593Smuzhiyun wl_drm_add_listener(xwl_gbm->drm, &xwl_drm_listener, xwl_screen);
862*4882a593Smuzhiyun xwl_screen->expecting_event++;
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun return TRUE;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun Bool
xwl_screen_set_dmabuf_interface(struct xwl_screen * xwl_screen,uint32_t id,uint32_t version)868*4882a593Smuzhiyun xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
869*4882a593Smuzhiyun uint32_t id, uint32_t version)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun if (version < 3)
874*4882a593Smuzhiyun return FALSE;
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun xwl_gbm->dmabuf =
877*4882a593Smuzhiyun wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
878*4882a593Smuzhiyun zwp_linux_dmabuf_v1_add_listener(xwl_gbm->dmabuf, &xwl_dmabuf_listener, xwl_screen);
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun return TRUE;
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun static Bool
xwl_glamor_gbm_init_wl_registry(struct xwl_screen * xwl_screen,struct wl_registry * wl_registry,uint32_t id,const char * name,uint32_t version)884*4882a593Smuzhiyun xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen,
885*4882a593Smuzhiyun struct wl_registry *wl_registry,
886*4882a593Smuzhiyun uint32_t id, const char *name,
887*4882a593Smuzhiyun uint32_t version)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun if (strcmp(name, "wl_drm") == 0) {
890*4882a593Smuzhiyun xwl_screen_set_drm_interface(xwl_screen, id, version);
891*4882a593Smuzhiyun return TRUE;
892*4882a593Smuzhiyun } else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0) {
893*4882a593Smuzhiyun xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
894*4882a593Smuzhiyun return TRUE;
895*4882a593Smuzhiyun }
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun /* no match */
898*4882a593Smuzhiyun return FALSE;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun static Bool
xwl_glamor_gbm_has_egl_extension(void)902*4882a593Smuzhiyun xwl_glamor_gbm_has_egl_extension(void)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun return (epoxy_has_egl_extension(NULL, "EGL_MESA_platform_gbm") ||
905*4882a593Smuzhiyun epoxy_has_egl_extension(NULL, "EGL_KHR_platform_gbm"));
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun static Bool
xwl_glamor_gbm_has_wl_interfaces(struct xwl_screen * xwl_screen)909*4882a593Smuzhiyun xwl_glamor_gbm_has_wl_interfaces(struct xwl_screen *xwl_screen)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun if (xwl_gbm->drm == NULL) {
914*4882a593Smuzhiyun ErrorF("glamor: 'wl_drm' not supported\n");
915*4882a593Smuzhiyun return FALSE;
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun return TRUE;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun static Bool
xwl_glamor_gbm_init_egl(struct xwl_screen * xwl_screen)922*4882a593Smuzhiyun xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
923*4882a593Smuzhiyun {
924*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
925*4882a593Smuzhiyun EGLint major, minor;
926*4882a593Smuzhiyun Bool egl_initialized = FALSE;
927*4882a593Smuzhiyun static const EGLint config_attribs_core[] = {
928*4882a593Smuzhiyun EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
929*4882a593Smuzhiyun EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
930*4882a593Smuzhiyun EGL_CONTEXT_MAJOR_VERSION_KHR,
931*4882a593Smuzhiyun GLAMOR_GL_CORE_VER_MAJOR,
932*4882a593Smuzhiyun EGL_CONTEXT_MINOR_VERSION_KHR,
933*4882a593Smuzhiyun GLAMOR_GL_CORE_VER_MINOR,
934*4882a593Smuzhiyun EGL_NONE
935*4882a593Smuzhiyun };
936*4882a593Smuzhiyun const GLubyte *renderer;
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun if (!xwl_gbm->fd_render_node && !xwl_gbm->drm_authenticated) {
939*4882a593Smuzhiyun ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
940*4882a593Smuzhiyun return FALSE;
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun xwl_gbm->gbm = gbm_create_device(xwl_gbm->drm_fd);
944*4882a593Smuzhiyun if (!xwl_gbm->gbm) {
945*4882a593Smuzhiyun ErrorF("couldn't create gbm device\n");
946*4882a593Smuzhiyun goto error;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun xwl_screen->egl_display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA,
950*4882a593Smuzhiyun xwl_gbm->gbm);
951*4882a593Smuzhiyun if (xwl_screen->egl_display == EGL_NO_DISPLAY) {
952*4882a593Smuzhiyun ErrorF("glamor_egl_get_display() failed\n");
953*4882a593Smuzhiyun goto error;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun egl_initialized = eglInitialize(xwl_screen->egl_display, &major, &minor);
957*4882a593Smuzhiyun if (!egl_initialized) {
958*4882a593Smuzhiyun ErrorF("eglInitialize() failed\n");
959*4882a593Smuzhiyun goto error;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun eglBindAPI(EGL_OPENGL_API);
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun xwl_screen->egl_context = eglCreateContext(
965*4882a593Smuzhiyun xwl_screen->egl_display, NULL, EGL_NO_CONTEXT, config_attribs_core);
966*4882a593Smuzhiyun if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
967*4882a593Smuzhiyun xwl_screen->egl_context = eglCreateContext(
968*4882a593Smuzhiyun xwl_screen->egl_display, NULL, EGL_NO_CONTEXT, NULL);
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
972*4882a593Smuzhiyun ErrorF("Failed to create EGL context\n");
973*4882a593Smuzhiyun goto error;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun if (!eglMakeCurrent(xwl_screen->egl_display,
977*4882a593Smuzhiyun EGL_NO_SURFACE, EGL_NO_SURFACE,
978*4882a593Smuzhiyun xwl_screen->egl_context)) {
979*4882a593Smuzhiyun ErrorF("Failed to make EGL context current\n");
980*4882a593Smuzhiyun goto error;
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun renderer = glGetString(GL_RENDERER);
984*4882a593Smuzhiyun if (!renderer) {
985*4882a593Smuzhiyun ErrorF("glGetString() returned NULL, your GL is broken\n");
986*4882a593Smuzhiyun goto error;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun if (strstr((const char *)renderer, "llvmpipe")) {
989*4882a593Smuzhiyun ErrorF("Refusing to try glamor on llvmpipe\n");
990*4882a593Smuzhiyun goto error;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun if (!epoxy_has_gl_extension("GL_OES_EGL_image")) {
994*4882a593Smuzhiyun ErrorF("GL_OES_EGL_image not available\n");
995*4882a593Smuzhiyun goto error;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun if (epoxy_has_egl_extension(xwl_screen->egl_display,
999*4882a593Smuzhiyun "EXT_image_dma_buf_import") &&
1000*4882a593Smuzhiyun epoxy_has_egl_extension(xwl_screen->egl_display,
1001*4882a593Smuzhiyun "EXT_image_dma_buf_import_modifiers"))
1002*4882a593Smuzhiyun xwl_gbm->dmabuf_capable = TRUE;
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun return TRUE;
1005*4882a593Smuzhiyun error:
1006*4882a593Smuzhiyun if (xwl_screen->egl_context != EGL_NO_CONTEXT) {
1007*4882a593Smuzhiyun eglDestroyContext(xwl_screen->egl_display, xwl_screen->egl_context);
1008*4882a593Smuzhiyun xwl_screen->egl_context = EGL_NO_CONTEXT;
1009*4882a593Smuzhiyun }
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun if (xwl_screen->egl_display != EGL_NO_DISPLAY) {
1012*4882a593Smuzhiyun eglTerminate(xwl_screen->egl_display);
1013*4882a593Smuzhiyun xwl_screen->egl_display = EGL_NO_DISPLAY;
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun xwl_glamor_gbm_cleanup(xwl_screen);
1017*4882a593Smuzhiyun return FALSE;
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun static Bool
xwl_glamor_gbm_init_screen(struct xwl_screen * xwl_screen)1021*4882a593Smuzhiyun xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen)
1022*4882a593Smuzhiyun {
1023*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
1026*4882a593Smuzhiyun ErrorF("Failed to initialize dri3\n");
1027*4882a593Smuzhiyun goto error;
1028*4882a593Smuzhiyun }
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun if (xwl_gbm->fd_render_node)
1031*4882a593Smuzhiyun goto skip_drm_auth;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun if (!dixRegisterPrivateKey(&xwl_auth_state_private_key, PRIVATE_CLIENT,
1034*4882a593Smuzhiyun 0)) {
1035*4882a593Smuzhiyun ErrorF("Failed to register private key\n");
1036*4882a593Smuzhiyun goto error;
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun if (!AddCallback(&ClientStateCallback, xwl_auth_state_client_callback,
1040*4882a593Smuzhiyun NULL)) {
1041*4882a593Smuzhiyun ErrorF("Failed to add client state callback\n");
1042*4882a593Smuzhiyun goto error;
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun skip_drm_auth:
1046*4882a593Smuzhiyun xwl_screen->screen->CreatePixmap = xwl_glamor_gbm_create_pixmap;
1047*4882a593Smuzhiyun xwl_screen->screen->DestroyPixmap = xwl_glamor_gbm_destroy_pixmap;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun return TRUE;
1050*4882a593Smuzhiyun error:
1051*4882a593Smuzhiyun xwl_glamor_gbm_cleanup(xwl_screen);
1052*4882a593Smuzhiyun return FALSE;
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun void
xwl_glamor_init_gbm(struct xwl_screen * xwl_screen)1056*4882a593Smuzhiyun xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
1057*4882a593Smuzhiyun {
1058*4882a593Smuzhiyun struct xwl_gbm_private *xwl_gbm;
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun xwl_screen->gbm_backend.is_available = FALSE;
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun if (!xwl_glamor_gbm_has_egl_extension())
1063*4882a593Smuzhiyun return;
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun if (!dixRegisterPrivateKey(&xwl_gbm_private_key, PRIVATE_SCREEN, 0))
1066*4882a593Smuzhiyun return;
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun xwl_gbm = calloc(sizeof(*xwl_gbm), 1);
1069*4882a593Smuzhiyun if (!xwl_gbm) {
1070*4882a593Smuzhiyun ErrorF("glamor: Not enough memory to setup GBM, disabling\n");
1071*4882a593Smuzhiyun return;
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun dixSetPrivate(&xwl_screen->screen->devPrivates, &xwl_gbm_private_key,
1075*4882a593Smuzhiyun xwl_gbm);
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun xwl_screen->gbm_backend.init_wl_registry = xwl_glamor_gbm_init_wl_registry;
1078*4882a593Smuzhiyun xwl_screen->gbm_backend.has_wl_interfaces = xwl_glamor_gbm_has_wl_interfaces;
1079*4882a593Smuzhiyun xwl_screen->gbm_backend.init_egl = xwl_glamor_gbm_init_egl;
1080*4882a593Smuzhiyun xwl_screen->gbm_backend.init_screen = xwl_glamor_gbm_init_screen;
1081*4882a593Smuzhiyun xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
1082*4882a593Smuzhiyun xwl_screen->gbm_backend.is_available = TRUE;
1083*4882a593Smuzhiyun }
1084