xref: /OK3568_Linux_fs/external/xserver/glamor/glamor_egl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2010 Intel Corporation.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person
5*4882a593Smuzhiyun  * obtaining a copy of this software and associated documentation
6*4882a593Smuzhiyun  * files (the "Software"), to deal in the Software without
7*4882a593Smuzhiyun  * restriction, including without limitation the rights to use, copy,
8*4882a593Smuzhiyun  * modify, merge, publish, distribute, sublicense, and/or sell copies
9*4882a593Smuzhiyun  * of the Software, and to permit persons to whom the Software is
10*4882a593Smuzhiyun  * furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including
13*4882a593Smuzhiyun  * the next paragraph) shall be included in all copies or substantial
14*4882a593Smuzhiyun  * portions of the Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*4882a593Smuzhiyun  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20*4882a593Smuzhiyun  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21*4882a593Smuzhiyun  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*4882a593Smuzhiyun  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Authors:
26*4882a593Smuzhiyun  *    Zhigang Gong <zhigang.gong@linux.intel.com>
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include "dix-config.h"
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define GLAMOR_FOR_XORG
33*4882a593Smuzhiyun #include <unistd.h>
34*4882a593Smuzhiyun #include <fcntl.h>
35*4882a593Smuzhiyun #include <sys/ioctl.h>
36*4882a593Smuzhiyun #include <errno.h>
37*4882a593Smuzhiyun #include <xf86.h>
38*4882a593Smuzhiyun #include <xf86Priv.h>
39*4882a593Smuzhiyun #include <xf86drm.h>
40*4882a593Smuzhiyun #define EGL_DISPLAY_NO_X_MESA
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #include <gbm.h>
43*4882a593Smuzhiyun #include <drm_fourcc.h>
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #include "glamor_egl.h"
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #include "glamor.h"
48*4882a593Smuzhiyun #include "glamor_priv.h"
49*4882a593Smuzhiyun #include "dri3.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #ifndef GBM_FORMAT_R8
52*4882a593Smuzhiyun #define GBM_FORMAT_R8                __gbm_fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun struct glamor_egl_screen_private {
56*4882a593Smuzhiyun     EGLDisplay display;
57*4882a593Smuzhiyun     EGLContext context;
58*4882a593Smuzhiyun     char *device_path;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun     CreateScreenResourcesProcPtr CreateScreenResources;
61*4882a593Smuzhiyun     CloseScreenProcPtr CloseScreen;
62*4882a593Smuzhiyun     int fd;
63*4882a593Smuzhiyun     struct gbm_device *gbm;
64*4882a593Smuzhiyun     int dmabuf_capable;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun     CloseScreenProcPtr saved_close_screen;
67*4882a593Smuzhiyun     DestroyPixmapProcPtr saved_destroy_pixmap;
68*4882a593Smuzhiyun     xf86FreeScreenProc *saved_free_screen;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun int xf86GlamorEGLPrivateIndex = -1;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static struct glamor_egl_screen_private *
glamor_egl_get_screen_private(ScrnInfoPtr scrn)75*4882a593Smuzhiyun glamor_egl_get_screen_private(ScrnInfoPtr scrn)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun     return (struct glamor_egl_screen_private *)
78*4882a593Smuzhiyun         scrn->privates[xf86GlamorEGLPrivateIndex].ptr;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun static void
glamor_egl_make_current(struct glamor_context * glamor_ctx)82*4882a593Smuzhiyun glamor_egl_make_current(struct glamor_context *glamor_ctx)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun     /* There's only a single global dispatch table in Mesa.  EGL, GLX,
85*4882a593Smuzhiyun      * and AIGLX's direct dispatch table manipulation don't talk to
86*4882a593Smuzhiyun      * each other.  We need to set the context to NULL first to avoid
87*4882a593Smuzhiyun      * EGL's no-op context change fast path when switching back to
88*4882a593Smuzhiyun      * EGL.
89*4882a593Smuzhiyun      */
90*4882a593Smuzhiyun     eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
91*4882a593Smuzhiyun                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun     if (!eglMakeCurrent(glamor_ctx->display,
94*4882a593Smuzhiyun                         EGL_NO_SURFACE, EGL_NO_SURFACE,
95*4882a593Smuzhiyun                         glamor_ctx->ctx)) {
96*4882a593Smuzhiyun         FatalError("Failed to make EGL context current\n");
97*4882a593Smuzhiyun     }
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun static int
glamor_get_flink_name(int fd,int handle,int * name)101*4882a593Smuzhiyun glamor_get_flink_name(int fd, int handle, int *name)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun     struct drm_gem_flink flink;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     flink.handle = handle;
106*4882a593Smuzhiyun     if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	/*
109*4882a593Smuzhiyun 	 * Assume non-GEM kernels have names identical to the handle
110*4882a593Smuzhiyun 	 */
111*4882a593Smuzhiyun 	if (errno == ENODEV) {
112*4882a593Smuzhiyun 	    *name = handle;
113*4882a593Smuzhiyun 	    return TRUE;
114*4882a593Smuzhiyun 	} else {
115*4882a593Smuzhiyun 	    return FALSE;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun     }
118*4882a593Smuzhiyun     *name = flink.name;
119*4882a593Smuzhiyun     return TRUE;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun static Bool
glamor_create_texture_from_image(ScreenPtr screen,EGLImageKHR image,GLuint * texture)123*4882a593Smuzhiyun glamor_create_texture_from_image(ScreenPtr screen,
124*4882a593Smuzhiyun                                  EGLImageKHR image, GLuint * texture)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun     struct glamor_screen_private *glamor_priv =
127*4882a593Smuzhiyun         glamor_get_screen_private(screen);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun     glamor_make_current(glamor_priv);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     glGenTextures(1, texture);
132*4882a593Smuzhiyun     glBindTexture(GL_TEXTURE_2D, *texture);
133*4882a593Smuzhiyun     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
134*4882a593Smuzhiyun     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
137*4882a593Smuzhiyun     glBindTexture(GL_TEXTURE_2D, 0);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun     return TRUE;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun struct gbm_device *
glamor_egl_get_gbm_device(ScreenPtr screen)143*4882a593Smuzhiyun glamor_egl_get_gbm_device(ScreenPtr screen)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl =
146*4882a593Smuzhiyun         glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
147*4882a593Smuzhiyun     return glamor_egl->gbm;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun Bool
glamor_egl_create_textured_screen(ScreenPtr screen,int handle,int stride)151*4882a593Smuzhiyun glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
154*4882a593Smuzhiyun     PixmapPtr screen_pixmap;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun     screen_pixmap = screen->GetScreenPixmap(screen);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun     if (!glamor_egl_create_textured_pixmap(screen_pixmap, handle, stride)) {
159*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
160*4882a593Smuzhiyun                    "Failed to create textured screen.");
161*4882a593Smuzhiyun         return FALSE;
162*4882a593Smuzhiyun     }
163*4882a593Smuzhiyun     return TRUE;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun static void
glamor_egl_set_pixmap_bo(PixmapPtr pixmap,struct gbm_bo * bo,Bool used_modifiers)167*4882a593Smuzhiyun glamor_egl_set_pixmap_bo(PixmapPtr pixmap, struct gbm_bo *bo,
168*4882a593Smuzhiyun                          Bool used_modifiers)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun     struct glamor_pixmap_private *pixmap_priv =
171*4882a593Smuzhiyun         glamor_get_pixmap_private(pixmap);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun     glamor_finish_access_pixmap(pixmap, TRUE);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun     if (pixmap_priv->bo && pixmap_priv->owned_bo)
176*4882a593Smuzhiyun         gbm_bo_destroy(pixmap_priv->bo);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun     pixmap_priv->bo = bo;
179*4882a593Smuzhiyun     pixmap_priv->owned_bo = TRUE;
180*4882a593Smuzhiyun     pixmap_priv->used_modifiers = used_modifiers;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun Bool
glamor_egl_create_textured_pixmap(PixmapPtr pixmap,int handle,int stride)184*4882a593Smuzhiyun glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun     ScreenPtr screen = pixmap->drawable.pScreen;
187*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
188*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl =
189*4882a593Smuzhiyun         glamor_egl_get_screen_private(scrn);
190*4882a593Smuzhiyun     int ret, fd;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun     /* GBM doesn't have an import path from handles, so we make a
193*4882a593Smuzhiyun      * dma-buf fd from it and then go through that.
194*4882a593Smuzhiyun      */
195*4882a593Smuzhiyun     ret = drmPrimeHandleToFD(glamor_egl->fd, handle, O_CLOEXEC, &fd);
196*4882a593Smuzhiyun     if (ret) {
197*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
198*4882a593Smuzhiyun                    "Failed to make prime FD for handle: %d\n", errno);
199*4882a593Smuzhiyun         return FALSE;
200*4882a593Smuzhiyun     }
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     if (!glamor_back_pixmap_from_fd(pixmap, fd,
203*4882a593Smuzhiyun                                     pixmap->drawable.width,
204*4882a593Smuzhiyun                                     pixmap->drawable.height,
205*4882a593Smuzhiyun                                     stride,
206*4882a593Smuzhiyun                                     pixmap->drawable.depth,
207*4882a593Smuzhiyun                                     pixmap->drawable.bitsPerPixel)) {
208*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
209*4882a593Smuzhiyun                    "Failed to make import prime FD as pixmap: %d\n", errno);
210*4882a593Smuzhiyun         close(fd);
211*4882a593Smuzhiyun         return FALSE;
212*4882a593Smuzhiyun     }
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun     close(fd);
215*4882a593Smuzhiyun     return TRUE;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun Bool
glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,struct gbm_bo * bo,Bool used_modifiers)219*4882a593Smuzhiyun glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
220*4882a593Smuzhiyun                                               struct gbm_bo *bo,
221*4882a593Smuzhiyun                                               Bool used_modifiers)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun     ScreenPtr screen = pixmap->drawable.pScreen;
224*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
225*4882a593Smuzhiyun     struct glamor_screen_private *glamor_priv =
226*4882a593Smuzhiyun         glamor_get_screen_private(screen);
227*4882a593Smuzhiyun     struct glamor_pixmap_private *pixmap_priv =
228*4882a593Smuzhiyun         glamor_get_pixmap_private(pixmap);
229*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
230*4882a593Smuzhiyun     EGLImageKHR image;
231*4882a593Smuzhiyun     GLuint texture;
232*4882a593Smuzhiyun     Bool ret = FALSE;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(scrn);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     glamor_make_current(glamor_priv);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun     image = eglCreateImageKHR(glamor_egl->display,
239*4882a593Smuzhiyun                               EGL_NO_CONTEXT,
240*4882a593Smuzhiyun                               EGL_NATIVE_PIXMAP_KHR, bo, NULL);
241*4882a593Smuzhiyun     if (image == EGL_NO_IMAGE_KHR) {
242*4882a593Smuzhiyun         glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY);
243*4882a593Smuzhiyun         goto done;
244*4882a593Smuzhiyun     }
245*4882a593Smuzhiyun     glamor_create_texture_from_image(screen, image, &texture);
246*4882a593Smuzhiyun     eglDestroyImage(glamor_egl->display, image);
247*4882a593Smuzhiyun     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
248*4882a593Smuzhiyun     glamor_set_pixmap_texture(pixmap, texture);
249*4882a593Smuzhiyun     glamor_egl_set_pixmap_bo(pixmap, bo, used_modifiers);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun     /* HACK: At least for mali DDK, the bo is owned by texture */
252*4882a593Smuzhiyun     pixmap_priv->owned_bo = FALSE;
253*4882a593Smuzhiyun     ret = TRUE;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun  done:
256*4882a593Smuzhiyun     return ret;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun static void
glamor_get_name_from_bo(int gbm_fd,struct gbm_bo * bo,int * name)260*4882a593Smuzhiyun glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun     union gbm_bo_handle handle;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun     handle = gbm_bo_get_handle(bo);
265*4882a593Smuzhiyun     if (!glamor_get_flink_name(gbm_fd, handle.u32, name))
266*4882a593Smuzhiyun         *name = -1;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun static Bool
glamor_make_pixmap_exportable(PixmapPtr pixmap,Bool modifiers_ok)270*4882a593Smuzhiyun glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun     ScreenPtr screen = pixmap->drawable.pScreen;
273*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
274*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl =
275*4882a593Smuzhiyun         glamor_egl_get_screen_private(scrn);
276*4882a593Smuzhiyun     struct glamor_pixmap_private *pixmap_priv =
277*4882a593Smuzhiyun         glamor_get_pixmap_private(pixmap);
278*4882a593Smuzhiyun     unsigned width = pixmap->drawable.width;
279*4882a593Smuzhiyun     unsigned height = pixmap->drawable.height;
280*4882a593Smuzhiyun     uint32_t format;
281*4882a593Smuzhiyun     struct gbm_bo *bo = NULL;
282*4882a593Smuzhiyun     Bool used_modifiers = FALSE;
283*4882a593Smuzhiyun     PixmapPtr exported;
284*4882a593Smuzhiyun     GCPtr scratch_gc;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     if (pixmap_priv->bo &&
287*4882a593Smuzhiyun         (modifiers_ok || !pixmap_priv->used_modifiers))
288*4882a593Smuzhiyun         return TRUE;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     /* HACK: Mali doesn't support depth 8 */
291*4882a593Smuzhiyun     if (pixmap->drawable.depth == 8)
292*4882a593Smuzhiyun         return FALSE;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun     switch (pixmap->drawable.depth) {
295*4882a593Smuzhiyun     case 30:
296*4882a593Smuzhiyun         format = GBM_FORMAT_ARGB2101010;
297*4882a593Smuzhiyun         break;
298*4882a593Smuzhiyun     case 32:
299*4882a593Smuzhiyun     case 24:
300*4882a593Smuzhiyun         format = GBM_FORMAT_ARGB8888;
301*4882a593Smuzhiyun         break;
302*4882a593Smuzhiyun     case 16:
303*4882a593Smuzhiyun         format = GBM_FORMAT_RGB565;
304*4882a593Smuzhiyun         break;
305*4882a593Smuzhiyun     case 15:
306*4882a593Smuzhiyun         format = GBM_FORMAT_ARGB1555;
307*4882a593Smuzhiyun         break;
308*4882a593Smuzhiyun     case 8:
309*4882a593Smuzhiyun         format = GBM_FORMAT_R8;
310*4882a593Smuzhiyun         break;
311*4882a593Smuzhiyun     default:
312*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
313*4882a593Smuzhiyun                    "Failed to make %d depth, %dbpp pixmap exportable\n",
314*4882a593Smuzhiyun                    pixmap->drawable.depth, pixmap->drawable.bitsPerPixel);
315*4882a593Smuzhiyun         return FALSE;
316*4882a593Smuzhiyun     }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
319*4882a593Smuzhiyun     if (modifiers_ok && glamor_egl->dmabuf_capable) {
320*4882a593Smuzhiyun         uint32_t num_modifiers;
321*4882a593Smuzhiyun         uint64_t *modifiers = NULL;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun         glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun         bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height,
326*4882a593Smuzhiyun                                           format, modifiers, num_modifiers);
327*4882a593Smuzhiyun         if (bo)
328*4882a593Smuzhiyun             used_modifiers = TRUE;
329*4882a593Smuzhiyun         free(modifiers);
330*4882a593Smuzhiyun     }
331*4882a593Smuzhiyun #endif
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun     if (!bo)
334*4882a593Smuzhiyun     {
335*4882a593Smuzhiyun         bo = gbm_bo_create(glamor_egl->gbm, width, height, format,
336*4882a593Smuzhiyun #ifdef GLAMOR_HAS_GBM_LINEAR
337*4882a593Smuzhiyun                 (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ?
338*4882a593Smuzhiyun                  GBM_BO_USE_LINEAR : 0) |
339*4882a593Smuzhiyun #endif
340*4882a593Smuzhiyun                 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
341*4882a593Smuzhiyun     }
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun     if (!bo) {
344*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
345*4882a593Smuzhiyun                    "Failed to make %dx%dx%dbpp GBM bo\n",
346*4882a593Smuzhiyun                    width, height, pixmap->drawable.bitsPerPixel);
347*4882a593Smuzhiyun         return FALSE;
348*4882a593Smuzhiyun     }
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun     exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0);
351*4882a593Smuzhiyun     screen->ModifyPixmapHeader(exported, width, height, 0, 0,
352*4882a593Smuzhiyun                                gbm_bo_get_stride(bo), NULL);
353*4882a593Smuzhiyun     if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo,
354*4882a593Smuzhiyun                                                        used_modifiers)) {
355*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
356*4882a593Smuzhiyun                    "Failed to make %dx%dx%dbpp pixmap from GBM bo\n",
357*4882a593Smuzhiyun                    width, height, pixmap->drawable.bitsPerPixel);
358*4882a593Smuzhiyun         screen->DestroyPixmap(exported);
359*4882a593Smuzhiyun         gbm_bo_destroy(bo);
360*4882a593Smuzhiyun         return FALSE;
361*4882a593Smuzhiyun     }
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun     scratch_gc = GetScratchGC(pixmap->drawable.depth, screen);
364*4882a593Smuzhiyun     ValidateGC(&pixmap->drawable, scratch_gc);
365*4882a593Smuzhiyun     pixmap_priv->exporting = TRUE;
366*4882a593Smuzhiyun     scratch_gc->ops->CopyArea(&pixmap->drawable, &exported->drawable,
367*4882a593Smuzhiyun                               scratch_gc,
368*4882a593Smuzhiyun                               0, 0, width, height, 0, 0);
369*4882a593Smuzhiyun     pixmap_priv->exporting = FALSE;
370*4882a593Smuzhiyun     FreeScratchGC(scratch_gc);
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun     /* Now, swap the tex/gbm/EGLImage/etc. of the exported pixmap into
373*4882a593Smuzhiyun      * the original pixmap struct.
374*4882a593Smuzhiyun      */
375*4882a593Smuzhiyun     glamor_egl_exchange_buffers(pixmap, exported);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     /* Swap the devKind into the original pixmap, reflecting the bo's stride */
378*4882a593Smuzhiyun     screen->ModifyPixmapHeader(pixmap, 0, 0, 0, 0, exported->devKind, NULL);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun     screen->DestroyPixmap(exported);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun     return TRUE;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun static struct gbm_bo *
glamor_gbm_bo_from_pixmap_internal(ScreenPtr screen,PixmapPtr pixmap)386*4882a593Smuzhiyun glamor_gbm_bo_from_pixmap_internal(ScreenPtr screen, PixmapPtr pixmap)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun     struct glamor_pixmap_private *pixmap_priv =
389*4882a593Smuzhiyun         glamor_get_pixmap_private(pixmap);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     if (!pixmap_priv->bo)
392*4882a593Smuzhiyun         return NULL;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun     return pixmap_priv->bo;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun struct gbm_bo *
glamor_gbm_bo_from_pixmap(ScreenPtr screen,PixmapPtr pixmap)398*4882a593Smuzhiyun glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun     if (!glamor_make_pixmap_exportable(pixmap, TRUE))
401*4882a593Smuzhiyun         return NULL;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun     return glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun int
glamor_egl_fds_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,int * fds,uint32_t * strides,uint32_t * offsets,uint64_t * modifier)407*4882a593Smuzhiyun glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
408*4882a593Smuzhiyun                            uint32_t *strides, uint32_t *offsets,
409*4882a593Smuzhiyun                            uint64_t *modifier)
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun #ifdef GLAMOR_HAS_GBM
412*4882a593Smuzhiyun     struct gbm_bo *bo;
413*4882a593Smuzhiyun     int num_fds;
414*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
415*4882a593Smuzhiyun     int i;
416*4882a593Smuzhiyun #endif
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun     if (!glamor_make_pixmap_exportable(pixmap, TRUE))
419*4882a593Smuzhiyun         return 0;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun     bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
422*4882a593Smuzhiyun     if (!bo)
423*4882a593Smuzhiyun         return 0;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
426*4882a593Smuzhiyun     num_fds = gbm_bo_get_plane_count(bo);
427*4882a593Smuzhiyun     for (i = 0; i < num_fds; i++) {
428*4882a593Smuzhiyun         fds[i] = gbm_bo_get_fd(bo);
429*4882a593Smuzhiyun         strides[i] = gbm_bo_get_stride_for_plane(bo, i);
430*4882a593Smuzhiyun         offsets[i] = gbm_bo_get_offset(bo, i);
431*4882a593Smuzhiyun     }
432*4882a593Smuzhiyun     *modifier = gbm_bo_get_modifier(bo);
433*4882a593Smuzhiyun #else
434*4882a593Smuzhiyun     num_fds = 1;
435*4882a593Smuzhiyun     fds[0] = gbm_bo_get_fd(bo);
436*4882a593Smuzhiyun     strides[0] = gbm_bo_get_stride(bo);
437*4882a593Smuzhiyun     offsets[0] = 0;
438*4882a593Smuzhiyun     *modifier = DRM_FORMAT_MOD_INVALID;
439*4882a593Smuzhiyun #endif
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun     return num_fds;
442*4882a593Smuzhiyun #else
443*4882a593Smuzhiyun     return 0;
444*4882a593Smuzhiyun #endif
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun _X_EXPORT int
glamor_egl_fd_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)448*4882a593Smuzhiyun glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
449*4882a593Smuzhiyun                           CARD16 *stride, CARD32 *size)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun #ifdef GLAMOR_HAS_GBM
452*4882a593Smuzhiyun     struct gbm_bo *bo;
453*4882a593Smuzhiyun     int fd;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun     if (!glamor_make_pixmap_exportable(pixmap, FALSE))
456*4882a593Smuzhiyun         return -1;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun     bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
459*4882a593Smuzhiyun     if (!bo)
460*4882a593Smuzhiyun         return -1;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun     fd = gbm_bo_get_fd(bo);
463*4882a593Smuzhiyun     *stride = gbm_bo_get_stride(bo);
464*4882a593Smuzhiyun     *size = *stride * gbm_bo_get_height(bo);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun     return fd;
467*4882a593Smuzhiyun #else
468*4882a593Smuzhiyun     return -1;
469*4882a593Smuzhiyun #endif
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun int
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)473*4882a593Smuzhiyun glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
474*4882a593Smuzhiyun                                PixmapPtr pixmap,
475*4882a593Smuzhiyun                                CARD16 *stride, CARD32 *size)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
478*4882a593Smuzhiyun     struct gbm_bo *bo;
479*4882a593Smuzhiyun     int fd = -1;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun     if (!glamor_make_pixmap_exportable(pixmap, FALSE))
484*4882a593Smuzhiyun         goto failure;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun     bo = glamor_gbm_bo_from_pixmap_internal(screen, pixmap);
487*4882a593Smuzhiyun     if (!bo)
488*4882a593Smuzhiyun         goto failure;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun     pixmap->devKind = gbm_bo_get_stride(bo);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun     glamor_get_name_from_bo(glamor_egl->fd, bo, &fd);
493*4882a593Smuzhiyun     *stride = pixmap->devKind;
494*4882a593Smuzhiyun     *size = pixmap->devKind * gbm_bo_get_height(bo);
495*4882a593Smuzhiyun  failure:
496*4882a593Smuzhiyun     return fd;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun _X_EXPORT Bool
glamor_back_pixmap_from_fd(PixmapPtr pixmap,int fd,CARD16 width,CARD16 height,CARD16 stride,CARD8 depth,CARD8 bpp)500*4882a593Smuzhiyun glamor_back_pixmap_from_fd(PixmapPtr pixmap,
501*4882a593Smuzhiyun                            int fd,
502*4882a593Smuzhiyun                            CARD16 width,
503*4882a593Smuzhiyun                            CARD16 height,
504*4882a593Smuzhiyun                            CARD16 stride, CARD8 depth, CARD8 bpp)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun     ScreenPtr screen = pixmap->drawable.pScreen;
507*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
508*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
509*4882a593Smuzhiyun     struct gbm_bo *bo;
510*4882a593Smuzhiyun     struct gbm_import_fd_data import_data = { 0 };
511*4882a593Smuzhiyun     Bool ret;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(scrn);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     if (bpp != 32 || !(depth == 24 || depth == 32 || depth == 30) || width == 0 || height == 0)
516*4882a593Smuzhiyun         return FALSE;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun     import_data.fd = fd;
519*4882a593Smuzhiyun     import_data.width = width;
520*4882a593Smuzhiyun     import_data.height = height;
521*4882a593Smuzhiyun     import_data.stride = stride;
522*4882a593Smuzhiyun     if (depth == 30)
523*4882a593Smuzhiyun         import_data.format = GBM_FORMAT_ARGB2101010;
524*4882a593Smuzhiyun     else
525*4882a593Smuzhiyun         import_data.format = GBM_FORMAT_ARGB8888;
526*4882a593Smuzhiyun     bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, 0);
527*4882a593Smuzhiyun     if (!bo)
528*4882a593Smuzhiyun         return FALSE;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun     screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun     ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, FALSE);
533*4882a593Smuzhiyun     if (!ret)
534*4882a593Smuzhiyun         gbm_bo_destroy(bo);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun     return ret;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun static uint32_t
gbm_format_for_depth(CARD8 depth)540*4882a593Smuzhiyun gbm_format_for_depth(CARD8 depth)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun     switch (depth) {
543*4882a593Smuzhiyun     case 16:
544*4882a593Smuzhiyun         return GBM_FORMAT_RGB565;
545*4882a593Smuzhiyun     case 24:
546*4882a593Smuzhiyun         return GBM_FORMAT_XRGB8888;
547*4882a593Smuzhiyun     case 30:
548*4882a593Smuzhiyun         return GBM_FORMAT_ARGB2101010;
549*4882a593Smuzhiyun     default:
550*4882a593Smuzhiyun         ErrorF("unexpected depth: %d\n", depth);
551*4882a593Smuzhiyun     case 32:
552*4882a593Smuzhiyun         return GBM_FORMAT_ARGB8888;
553*4882a593Smuzhiyun     }
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*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)557*4882a593Smuzhiyun glamor_pixmap_from_fds(ScreenPtr screen,
558*4882a593Smuzhiyun                        CARD8 num_fds, const int *fds,
559*4882a593Smuzhiyun                        CARD16 width, CARD16 height,
560*4882a593Smuzhiyun                        const CARD32 *strides, const CARD32 *offsets,
561*4882a593Smuzhiyun                        CARD8 depth, CARD8 bpp,
562*4882a593Smuzhiyun                        uint64_t modifier)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun     PixmapPtr pixmap;
565*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
566*4882a593Smuzhiyun     Bool ret = FALSE;
567*4882a593Smuzhiyun     int i;
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun     pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
574*4882a593Smuzhiyun     if (glamor_egl->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) {
575*4882a593Smuzhiyun         struct gbm_import_fd_modifier_data import_data = { 0 };
576*4882a593Smuzhiyun         struct gbm_bo *bo;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun         import_data.width = width;
579*4882a593Smuzhiyun         import_data.height = height;
580*4882a593Smuzhiyun         import_data.num_fds = num_fds;
581*4882a593Smuzhiyun         import_data.modifier = modifier;
582*4882a593Smuzhiyun         for (i = 0; i < num_fds; i++) {
583*4882a593Smuzhiyun             import_data.fds[i] = fds[i];
584*4882a593Smuzhiyun             import_data.strides[i] = strides[i];
585*4882a593Smuzhiyun             import_data.offsets[i] = offsets[i];
586*4882a593Smuzhiyun         }
587*4882a593Smuzhiyun         import_data.format = gbm_format_for_depth(depth);
588*4882a593Smuzhiyun         bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0);
589*4882a593Smuzhiyun         if (bo) {
590*4882a593Smuzhiyun             screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL);
591*4882a593Smuzhiyun             ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, TRUE);
592*4882a593Smuzhiyun             if (!ret)
593*4882a593Smuzhiyun                 gbm_bo_destroy(bo);
594*4882a593Smuzhiyun         }
595*4882a593Smuzhiyun     } else
596*4882a593Smuzhiyun #endif
597*4882a593Smuzhiyun     {
598*4882a593Smuzhiyun         if (num_fds == 1) {
599*4882a593Smuzhiyun             ret = glamor_back_pixmap_from_fd(pixmap, fds[0], width, height,
600*4882a593Smuzhiyun                                              strides[0], depth, bpp);
601*4882a593Smuzhiyun         }
602*4882a593Smuzhiyun     }
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun     if (ret == FALSE) {
605*4882a593Smuzhiyun         screen->DestroyPixmap(pixmap);
606*4882a593Smuzhiyun         return NULL;
607*4882a593Smuzhiyun     }
608*4882a593Smuzhiyun     return pixmap;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun _X_EXPORT PixmapPtr
glamor_pixmap_from_fd(ScreenPtr screen,int fd,CARD16 width,CARD16 height,CARD16 stride,CARD8 depth,CARD8 bpp)612*4882a593Smuzhiyun glamor_pixmap_from_fd(ScreenPtr screen,
613*4882a593Smuzhiyun                       int fd,
614*4882a593Smuzhiyun                       CARD16 width,
615*4882a593Smuzhiyun                       CARD16 height,
616*4882a593Smuzhiyun                       CARD16 stride, CARD8 depth, CARD8 bpp)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun     PixmapPtr pixmap;
619*4882a593Smuzhiyun     Bool ret;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun     pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun     ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height,
624*4882a593Smuzhiyun                                      stride, depth, bpp);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun     if (ret == FALSE) {
627*4882a593Smuzhiyun         screen->DestroyPixmap(pixmap);
628*4882a593Smuzhiyun         return NULL;
629*4882a593Smuzhiyun     }
630*4882a593Smuzhiyun     return pixmap;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun _X_EXPORT Bool
glamor_get_formats(ScreenPtr screen,CARD32 * num_formats,CARD32 ** formats)634*4882a593Smuzhiyun glamor_get_formats(ScreenPtr screen,
635*4882a593Smuzhiyun                    CARD32 *num_formats, CARD32 **formats)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun #ifdef GLAMOR_HAS_EGL_QUERY_DMABUF
638*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
639*4882a593Smuzhiyun     EGLint num;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun     /* Explicitly zero the count as the caller may ignore the return value */
642*4882a593Smuzhiyun     *num_formats = 0;
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun     if (!glamor_egl->dmabuf_capable)
647*4882a593Smuzhiyun         return TRUE;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun     if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, 0, NULL, &num))
650*4882a593Smuzhiyun         return FALSE;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     if (num == 0)
653*4882a593Smuzhiyun         return TRUE;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun     *formats = calloc(num, sizeof(CARD32));
656*4882a593Smuzhiyun     if (*formats == NULL)
657*4882a593Smuzhiyun         return FALSE;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun     if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num,
660*4882a593Smuzhiyun                                   (EGLint *) *formats, &num)) {
661*4882a593Smuzhiyun         free(*formats);
662*4882a593Smuzhiyun         return FALSE;
663*4882a593Smuzhiyun     }
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun     *num_formats = num;
666*4882a593Smuzhiyun     return TRUE;
667*4882a593Smuzhiyun #else
668*4882a593Smuzhiyun     *num_formats = 0;
669*4882a593Smuzhiyun     return TRUE;
670*4882a593Smuzhiyun #endif
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun _X_EXPORT Bool
glamor_get_modifiers(ScreenPtr screen,uint32_t format,uint32_t * num_modifiers,uint64_t ** modifiers)674*4882a593Smuzhiyun glamor_get_modifiers(ScreenPtr screen, uint32_t format,
675*4882a593Smuzhiyun                      uint32_t *num_modifiers, uint64_t **modifiers)
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun #ifdef GLAMOR_HAS_EGL_QUERY_DMABUF
678*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
679*4882a593Smuzhiyun     EGLint num;
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun     /* Explicitly zero the count as the caller may ignore the return value */
682*4882a593Smuzhiyun     *num_modifiers = 0;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun     if (!glamor_egl->dmabuf_capable)
687*4882a593Smuzhiyun         return FALSE;
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun     if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, 0, NULL,
690*4882a593Smuzhiyun                                     NULL, &num))
691*4882a593Smuzhiyun         return FALSE;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun     if (num == 0)
694*4882a593Smuzhiyun         return TRUE;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun     *modifiers = calloc(num, sizeof(uint64_t));
697*4882a593Smuzhiyun     if (*modifiers == NULL)
698*4882a593Smuzhiyun         return FALSE;
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun     if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, num,
701*4882a593Smuzhiyun                                     (EGLuint64KHR *) *modifiers, NULL, &num)) {
702*4882a593Smuzhiyun         free(*modifiers);
703*4882a593Smuzhiyun         return FALSE;
704*4882a593Smuzhiyun     }
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun     *num_modifiers = num;
707*4882a593Smuzhiyun     return TRUE;
708*4882a593Smuzhiyun #else
709*4882a593Smuzhiyun     *num_modifiers = 0;
710*4882a593Smuzhiyun     return TRUE;
711*4882a593Smuzhiyun #endif
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun _X_EXPORT const char *
glamor_egl_get_driver_name(ScreenPtr screen)715*4882a593Smuzhiyun glamor_egl_get_driver_name(ScreenPtr screen)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun #ifdef GLAMOR_HAS_EGL_QUERY_DRIVER
718*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun     if (epoxy_has_egl_extension(glamor_egl->display, "EGL_MESA_query_driver"))
723*4882a593Smuzhiyun         return eglGetDisplayDriverName(glamor_egl->display);
724*4882a593Smuzhiyun #endif
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun     return NULL;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun static Bool
glamor_egl_destroy_pixmap(PixmapPtr pixmap)731*4882a593Smuzhiyun glamor_egl_destroy_pixmap(PixmapPtr pixmap)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun     ScreenPtr screen = pixmap->drawable.pScreen;
734*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
735*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl =
736*4882a593Smuzhiyun         glamor_egl_get_screen_private(scrn);
737*4882a593Smuzhiyun     Bool ret;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun     if (pixmap->refcnt == 1) {
740*4882a593Smuzhiyun         struct glamor_pixmap_private *pixmap_priv =
741*4882a593Smuzhiyun             glamor_get_pixmap_private(pixmap);
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun         glamor_egl_set_pixmap_bo(pixmap, NULL, pixmap_priv->used_modifiers);
744*4882a593Smuzhiyun     }
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun     screen->DestroyPixmap = glamor_egl->saved_destroy_pixmap;
747*4882a593Smuzhiyun     ret = screen->DestroyPixmap(pixmap);
748*4882a593Smuzhiyun     glamor_egl->saved_destroy_pixmap = screen->DestroyPixmap;
749*4882a593Smuzhiyun     screen->DestroyPixmap = glamor_egl_destroy_pixmap;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun     return ret;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun _X_EXPORT void
glamor_egl_exchange_buffers(PixmapPtr front,PixmapPtr back)755*4882a593Smuzhiyun glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun #define GLAMOR_EXCHANGE(a, b) \
758*4882a593Smuzhiyun     { typeof(a) __tmp; __tmp = a; a = b; b = __tmp; }
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun     struct glamor_pixmap_private *front_priv =
761*4882a593Smuzhiyun         glamor_get_pixmap_private(front);
762*4882a593Smuzhiyun     struct glamor_pixmap_private *back_priv =
763*4882a593Smuzhiyun         glamor_get_pixmap_private(back);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun     glamor_pixmap_exchange_fbos(front, back);
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun     glamor_finish_access_pixmap(front, FALSE);
768*4882a593Smuzhiyun     glamor_finish_access_pixmap(back, FALSE);
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun     /* Swap all buffer related members */
771*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back_priv->bo, front_priv->bo);
772*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back_priv->owned_bo, front_priv->owned_bo);
773*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back_priv->used_modifiers, front_priv->used_modifiers);
774*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back_priv->bo_mapped, front_priv->bo_mapped);
775*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back_priv->map_data, front_priv->map_data);
776*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back_priv->gl_synced, front_priv->gl_synced);
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back->devPrivate.ptr, front->devPrivate.ptr);
779*4882a593Smuzhiyun     GLAMOR_EXCHANGE(back->devKind, front->devKind);
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun     glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
782*4882a593Smuzhiyun     glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun static Bool
glamor_egl_close_screen(ScreenPtr screen)786*4882a593Smuzhiyun glamor_egl_close_screen(ScreenPtr screen)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun     ScrnInfoPtr scrn;
789*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
790*4882a593Smuzhiyun     struct glamor_pixmap_private *pixmap_priv;
791*4882a593Smuzhiyun     PixmapPtr screen_pixmap;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun     scrn = xf86ScreenToScrn(screen);
794*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(scrn);
795*4882a593Smuzhiyun     screen_pixmap = screen->GetScreenPixmap(screen);
796*4882a593Smuzhiyun     pixmap_priv = glamor_get_pixmap_private(screen_pixmap);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun     glamor_egl_set_pixmap_bo(screen_pixmap, NULL, pixmap_priv->used_modifiers);
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun     if (glamor_egl->device_path) {
801*4882a593Smuzhiyun         free(glamor_egl->device_path);
802*4882a593Smuzhiyun         glamor_egl->device_path = NULL;
803*4882a593Smuzhiyun     }
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun     screen->CloseScreen = glamor_egl->saved_close_screen;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun     return screen->CloseScreen(screen);
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun #ifdef DRI3
811*4882a593Smuzhiyun static int
glamor_dri3_open_client(ClientPtr client,ScreenPtr screen,RRProviderPtr provider,int * fdp)812*4882a593Smuzhiyun glamor_dri3_open_client(ClientPtr client,
813*4882a593Smuzhiyun                         ScreenPtr screen,
814*4882a593Smuzhiyun                         RRProviderPtr provider,
815*4882a593Smuzhiyun                         int *fdp)
816*4882a593Smuzhiyun {
817*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
818*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl =
819*4882a593Smuzhiyun         glamor_egl_get_screen_private(scrn);
820*4882a593Smuzhiyun     int fd;
821*4882a593Smuzhiyun     drm_magic_t magic;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun     fd = open(glamor_egl->device_path, O_RDWR|O_CLOEXEC);
824*4882a593Smuzhiyun     if (fd < 0)
825*4882a593Smuzhiyun         return BadAlloc;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun     /* Before FD passing in the X protocol with DRI3 (and increased
828*4882a593Smuzhiyun      * security of rendering with per-process address spaces on the
829*4882a593Smuzhiyun      * GPU), the kernel had to come up with a way to have the server
830*4882a593Smuzhiyun      * decide which clients got to access the GPU, which was done by
831*4882a593Smuzhiyun      * each client getting a unique (magic) number from the kernel,
832*4882a593Smuzhiyun      * passing it to the server, and the server then telling the
833*4882a593Smuzhiyun      * kernel which clients were authenticated for using the device.
834*4882a593Smuzhiyun      *
835*4882a593Smuzhiyun      * Now that we have FD passing, the server can just set up the
836*4882a593Smuzhiyun      * authentication on its own and hand the prepared FD off to the
837*4882a593Smuzhiyun      * client.
838*4882a593Smuzhiyun      */
839*4882a593Smuzhiyun     if (drmGetMagic(fd, &magic) < 0) {
840*4882a593Smuzhiyun         if (errno == EACCES) {
841*4882a593Smuzhiyun             /* Assume that we're on a render node, and the fd is
842*4882a593Smuzhiyun              * already as authenticated as it should be.
843*4882a593Smuzhiyun              */
844*4882a593Smuzhiyun             *fdp = fd;
845*4882a593Smuzhiyun             return Success;
846*4882a593Smuzhiyun         } else {
847*4882a593Smuzhiyun             close(fd);
848*4882a593Smuzhiyun             return BadMatch;
849*4882a593Smuzhiyun         }
850*4882a593Smuzhiyun     }
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun     if (drmAuthMagic(glamor_egl->fd, magic) < 0) {
853*4882a593Smuzhiyun         close(fd);
854*4882a593Smuzhiyun         return BadMatch;
855*4882a593Smuzhiyun     }
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun     *fdp = fd;
858*4882a593Smuzhiyun     return Success;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun static const dri3_screen_info_rec glamor_dri3_info = {
862*4882a593Smuzhiyun     .version = 2,
863*4882a593Smuzhiyun     .open_client = glamor_dri3_open_client,
864*4882a593Smuzhiyun     .pixmap_from_fds = glamor_pixmap_from_fds,
865*4882a593Smuzhiyun     .fd_from_pixmap = glamor_egl_fd_from_pixmap,
866*4882a593Smuzhiyun     .fds_from_pixmap = glamor_egl_fds_from_pixmap,
867*4882a593Smuzhiyun     .get_formats = glamor_get_formats,
868*4882a593Smuzhiyun     .get_modifiers = glamor_get_modifiers,
869*4882a593Smuzhiyun     .get_drawable_modifiers = glamor_get_drawable_modifiers,
870*4882a593Smuzhiyun };
871*4882a593Smuzhiyun #endif /* DRI3 */
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun void
glamor_egl_screen_init(ScreenPtr screen,struct glamor_context * glamor_ctx)874*4882a593Smuzhiyun glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
877*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl =
878*4882a593Smuzhiyun         glamor_egl_get_screen_private(scrn);
879*4882a593Smuzhiyun #ifdef DRI3
880*4882a593Smuzhiyun     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
881*4882a593Smuzhiyun #endif
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun     glamor_egl->saved_close_screen = screen->CloseScreen;
884*4882a593Smuzhiyun     screen->CloseScreen = glamor_egl_close_screen;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun     glamor_egl->saved_destroy_pixmap = screen->DestroyPixmap;
887*4882a593Smuzhiyun     screen->DestroyPixmap = glamor_egl_destroy_pixmap;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun     glamor_ctx->ctx = glamor_egl->context;
890*4882a593Smuzhiyun     glamor_ctx->display = glamor_egl->display;
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun     glamor_ctx->make_current = glamor_egl_make_current;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun #ifdef DRI3
895*4882a593Smuzhiyun     /* Tell the core that we have the interfaces for import/export
896*4882a593Smuzhiyun      * of pixmaps.
897*4882a593Smuzhiyun      */
898*4882a593Smuzhiyun     glamor_enable_dri3(screen);
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun     /* If the driver wants to do its own auth dance (e.g. Xwayland
901*4882a593Smuzhiyun      * on pre-3.15 kernels that don't have render nodes and thus
902*4882a593Smuzhiyun      * has the wayland compositor as a master), then it needs us
903*4882a593Smuzhiyun      * to stay out of the way and let it init DRI3 on its own.
904*4882a593Smuzhiyun      */
905*4882a593Smuzhiyun     if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) {
906*4882a593Smuzhiyun         /* To do DRI3 device FD generation, we need to open a new fd
907*4882a593Smuzhiyun          * to the same device we were handed in originally.
908*4882a593Smuzhiyun          */
909*4882a593Smuzhiyun         glamor_egl->device_path = drmGetDeviceNameFromFd2(glamor_egl->fd);
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun         if (!dri3_screen_init(screen, &glamor_dri3_info)) {
912*4882a593Smuzhiyun             xf86DrvMsg(scrn->scrnIndex, X_ERROR,
913*4882a593Smuzhiyun                        "Failed to initialize DRI3.\n");
914*4882a593Smuzhiyun         }
915*4882a593Smuzhiyun     }
916*4882a593Smuzhiyun #endif
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun 
glamor_egl_cleanup(struct glamor_egl_screen_private * glamor_egl)919*4882a593Smuzhiyun static void glamor_egl_cleanup(struct glamor_egl_screen_private *glamor_egl)
920*4882a593Smuzhiyun {
921*4882a593Smuzhiyun     if (glamor_egl->display != EGL_NO_DISPLAY) {
922*4882a593Smuzhiyun         eglMakeCurrent(glamor_egl->display,
923*4882a593Smuzhiyun                        EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
924*4882a593Smuzhiyun         /*
925*4882a593Smuzhiyun          * Force the next glamor_make_current call to update the context
926*4882a593Smuzhiyun          * (on hot unplug another GPU may still be using glamor)
927*4882a593Smuzhiyun          */
928*4882a593Smuzhiyun         lastGLContext = NULL;
929*4882a593Smuzhiyun         eglTerminate(glamor_egl->display);
930*4882a593Smuzhiyun     }
931*4882a593Smuzhiyun     if (glamor_egl->gbm)
932*4882a593Smuzhiyun         gbm_device_destroy(glamor_egl->gbm);
933*4882a593Smuzhiyun     free(glamor_egl);
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun static void
glamor_egl_free_screen(ScrnInfoPtr scrn)937*4882a593Smuzhiyun glamor_egl_free_screen(ScrnInfoPtr scrn)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun     glamor_egl = glamor_egl_get_screen_private(scrn);
942*4882a593Smuzhiyun     if (glamor_egl != NULL) {
943*4882a593Smuzhiyun         scrn->FreeScreen = glamor_egl->saved_free_screen;
944*4882a593Smuzhiyun         glamor_egl_cleanup(glamor_egl);
945*4882a593Smuzhiyun         scrn->FreeScreen(scrn);
946*4882a593Smuzhiyun     }
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun Bool
glamor_egl_init(ScrnInfoPtr scrn,int fd)950*4882a593Smuzhiyun glamor_egl_init(ScrnInfoPtr scrn, int fd)
951*4882a593Smuzhiyun {
952*4882a593Smuzhiyun     struct glamor_egl_screen_private *glamor_egl;
953*4882a593Smuzhiyun     const GLubyte *renderer;
954*4882a593Smuzhiyun     EGLConfig egl_config;
955*4882a593Smuzhiyun     int n;
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun     glamor_egl = calloc(sizeof(*glamor_egl), 1);
958*4882a593Smuzhiyun     if (glamor_egl == NULL)
959*4882a593Smuzhiyun         return FALSE;
960*4882a593Smuzhiyun     if (xf86GlamorEGLPrivateIndex == -1)
961*4882a593Smuzhiyun         xf86GlamorEGLPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun     scrn->privates[xf86GlamorEGLPrivateIndex].ptr = glamor_egl;
964*4882a593Smuzhiyun     glamor_egl->fd = fd;
965*4882a593Smuzhiyun     glamor_egl->gbm = gbm_create_device(glamor_egl->fd);
966*4882a593Smuzhiyun     if (glamor_egl->gbm == NULL) {
967*4882a593Smuzhiyun         ErrorF("couldn't get display device\n");
968*4882a593Smuzhiyun         goto error;
969*4882a593Smuzhiyun     }
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun     glamor_egl->display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA,
972*4882a593Smuzhiyun                                                  glamor_egl->gbm);
973*4882a593Smuzhiyun     if (!glamor_egl->display) {
974*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetDisplay() failed\n");
975*4882a593Smuzhiyun         goto error;
976*4882a593Smuzhiyun     }
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun     if (!eglInitialize(glamor_egl->display, NULL, NULL)) {
979*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglInitialize() failed\n");
980*4882a593Smuzhiyun         glamor_egl->display = EGL_NO_DISPLAY;
981*4882a593Smuzhiyun         goto error;
982*4882a593Smuzhiyun     }
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun #define GLAMOR_CHECK_EGL_EXTENSION(EXT)  \
985*4882a593Smuzhiyun 	if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT)) {  \
986*4882a593Smuzhiyun 		ErrorF("EGL_" #EXT " required.\n");  \
987*4882a593Smuzhiyun 		goto error;  \
988*4882a593Smuzhiyun 	}
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun #define GLAMOR_CHECK_EGL_EXTENSIONS(EXT1, EXT2)	 \
991*4882a593Smuzhiyun 	if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT1) &&  \
992*4882a593Smuzhiyun 	    !epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT2)) {  \
993*4882a593Smuzhiyun 		ErrorF("EGL_" #EXT1 " or EGL_" #EXT2 " required.\n");  \
994*4882a593Smuzhiyun 		goto error;  \
995*4882a593Smuzhiyun 	}
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun     GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_context);
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun     if (eglBindAPI(EGL_OPENGL_API)) {
1000*4882a593Smuzhiyun         static const EGLint config_attribs_core[] = {
1001*4882a593Smuzhiyun             EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
1002*4882a593Smuzhiyun             EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
1003*4882a593Smuzhiyun             EGL_CONTEXT_MAJOR_VERSION_KHR,
1004*4882a593Smuzhiyun             GLAMOR_GL_CORE_VER_MAJOR,
1005*4882a593Smuzhiyun             EGL_CONTEXT_MINOR_VERSION_KHR,
1006*4882a593Smuzhiyun             GLAMOR_GL_CORE_VER_MINOR,
1007*4882a593Smuzhiyun             EGL_NONE
1008*4882a593Smuzhiyun         };
1009*4882a593Smuzhiyun         static const EGLint config_attribs[] = {
1010*4882a593Smuzhiyun             EGL_NONE
1011*4882a593Smuzhiyun         };
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun         glamor_egl->context = eglCreateContext(glamor_egl->display,
1014*4882a593Smuzhiyun                                                NULL, EGL_NO_CONTEXT,
1015*4882a593Smuzhiyun                                                config_attribs_core);
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun         if (glamor_egl->context == EGL_NO_CONTEXT)
1018*4882a593Smuzhiyun             glamor_egl->context = eglCreateContext(glamor_egl->display,
1019*4882a593Smuzhiyun                                                    NULL, EGL_NO_CONTEXT,
1020*4882a593Smuzhiyun                                                    config_attribs);
1021*4882a593Smuzhiyun     }
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun     if (glamor_egl->context == EGL_NO_CONTEXT) {
1024*4882a593Smuzhiyun         static const EGLint config_attribs[] = {
1025*4882a593Smuzhiyun             EGL_CONTEXT_CLIENT_VERSION, 2,
1026*4882a593Smuzhiyun             EGL_NONE
1027*4882a593Smuzhiyun         };
1028*4882a593Smuzhiyun         if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1029*4882a593Smuzhiyun             xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1030*4882a593Smuzhiyun                        "glamor: Failed to bind either GL or GLES APIs.\n");
1031*4882a593Smuzhiyun             goto error;
1032*4882a593Smuzhiyun         }
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun         if (!eglChooseConfig(glamor_egl->display, NULL, &egl_config, 1, &n)) {
1035*4882a593Smuzhiyun             xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1036*4882a593Smuzhiyun                        "glamor: No acceptable EGL configs found\n");
1037*4882a593Smuzhiyun             goto error;
1038*4882a593Smuzhiyun         }
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun         glamor_egl->context = eglCreateContext(glamor_egl->display,
1041*4882a593Smuzhiyun                                                egl_config, EGL_NO_CONTEXT,
1042*4882a593Smuzhiyun                                                config_attribs);
1043*4882a593Smuzhiyun     }
1044*4882a593Smuzhiyun     if (glamor_egl->context == EGL_NO_CONTEXT) {
1045*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1046*4882a593Smuzhiyun                    "glamor: Failed to create GL or GLES2 contexts\n");
1047*4882a593Smuzhiyun         goto error;
1048*4882a593Smuzhiyun     }
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun     if (!eglMakeCurrent(glamor_egl->display,
1051*4882a593Smuzhiyun                         EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_egl->context)) {
1052*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1053*4882a593Smuzhiyun                    "Failed to make EGL context current\n");
1054*4882a593Smuzhiyun         goto error;
1055*4882a593Smuzhiyun     }
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun     renderer = glGetString(GL_RENDERER);
1058*4882a593Smuzhiyun     if (!renderer) {
1059*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1060*4882a593Smuzhiyun                    "glGetString() returned NULL, your GL is broken\n");
1061*4882a593Smuzhiyun         goto error;
1062*4882a593Smuzhiyun     }
1063*4882a593Smuzhiyun     if (strstr((const char *)renderer, "llvmpipe")) {
1064*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_INFO,
1065*4882a593Smuzhiyun                    "Refusing to try glamor on llvmpipe\n");
1066*4882a593Smuzhiyun         goto error;
1067*4882a593Smuzhiyun     }
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun     /*
1070*4882a593Smuzhiyun      * Force the next glamor_make_current call to set the right context
1071*4882a593Smuzhiyun      * (in case of multiple GPUs using glamor)
1072*4882a593Smuzhiyun      */
1073*4882a593Smuzhiyun     lastGLContext = NULL;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun     if (!epoxy_has_gl_extension("GL_OES_EGL_image")) {
1076*4882a593Smuzhiyun         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1077*4882a593Smuzhiyun                    "glamor acceleration requires GL_OES_EGL_image\n");
1078*4882a593Smuzhiyun         goto error;
1079*4882a593Smuzhiyun     }
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun     xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor X acceleration enabled on %s\n",
1082*4882a593Smuzhiyun                renderer);
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun #ifdef GBM_BO_WITH_MODIFIERS
1085*4882a593Smuzhiyun     if (epoxy_has_egl_extension(glamor_egl->display,
1086*4882a593Smuzhiyun                                 "EGL_EXT_image_dma_buf_import") &&
1087*4882a593Smuzhiyun         epoxy_has_egl_extension(glamor_egl->display,
1088*4882a593Smuzhiyun                                 "EGL_EXT_image_dma_buf_import_modifiers")) {
1089*4882a593Smuzhiyun        if (xf86Info.debug != NULL)
1090*4882a593Smuzhiyun            glamor_egl->dmabuf_capable = !!strstr(xf86Info.debug,
1091*4882a593Smuzhiyun                                                 "dmabuf_capable");
1092*4882a593Smuzhiyun        else
1093*4882a593Smuzhiyun            glamor_egl->dmabuf_capable = TRUE;
1094*4882a593Smuzhiyun     }
1095*4882a593Smuzhiyun #endif
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun     glamor_egl->saved_free_screen = scrn->FreeScreen;
1098*4882a593Smuzhiyun     scrn->FreeScreen = glamor_egl_free_screen;
1099*4882a593Smuzhiyun     return TRUE;
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun error:
1102*4882a593Smuzhiyun     glamor_egl_cleanup(glamor_egl);
1103*4882a593Smuzhiyun     return FALSE;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun /** Stub to retain compatibility with pre-server-1.16 ABI. */
1107*4882a593Smuzhiyun Bool
glamor_egl_init_textured_pixmap(ScreenPtr screen)1108*4882a593Smuzhiyun glamor_egl_init_textured_pixmap(ScreenPtr screen)
1109*4882a593Smuzhiyun {
1110*4882a593Smuzhiyun     return TRUE;
1111*4882a593Smuzhiyun }
1112