xref: /OK3568_Linux_fs/external/xserver/hw/xwayland/xwayland-glamor-gbm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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