xref: /OK3568_Linux_fs/external/xserver/hw/xwayland/xwayland-glamor.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright © 2011-2014 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of the
9  * copyright holders not be used in advertising or publicity
10  * pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no
12  * representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  */
25 
26 #include "xwayland.h"
27 
28 #define MESA_EGL_NO_X11_HEADERS
29 #define EGL_NO_X11
30 #include <glamor_egl.h>
31 
32 #include <glamor.h>
33 #include <glamor_context.h>
34 
35 static void
glamor_egl_make_current(struct glamor_context * glamor_ctx)36 glamor_egl_make_current(struct glamor_context *glamor_ctx)
37 {
38     eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
39                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
40     if (!eglMakeCurrent(glamor_ctx->display,
41                         EGL_NO_SURFACE, EGL_NO_SURFACE,
42                         glamor_ctx->ctx))
43         FatalError("Failed to make EGL context current\n");
44 }
45 
46 void
xwl_glamor_egl_make_current(struct xwl_screen * xwl_screen)47 xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen)
48 {
49     if (lastGLContext == xwl_screen->glamor_ctx)
50         return;
51 
52     lastGLContext = xwl_screen->glamor_ctx;
53     xwl_screen->glamor_ctx->make_current(xwl_screen->glamor_ctx);
54 }
55 
56 void
glamor_egl_screen_init(ScreenPtr screen,struct glamor_context * glamor_ctx)57 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
58 {
59     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
60 
61     glamor_enable_dri3(screen);
62     glamor_ctx->ctx = xwl_screen->egl_context;
63     glamor_ctx->display = xwl_screen->egl_display;
64 
65     glamor_ctx->make_current = glamor_egl_make_current;
66 
67     xwl_screen->glamor_ctx = glamor_ctx;
68 }
69 
70 void
xwl_glamor_init_wl_registry(struct xwl_screen * xwl_screen,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)71 xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
72                             struct wl_registry *registry,
73                             uint32_t id, const char *interface,
74                             uint32_t version)
75 {
76     if (xwl_screen->gbm_backend.is_available &&
77         xwl_screen->gbm_backend.init_wl_registry(xwl_screen,
78                                                  registry,
79                                                  id,
80                                                  interface,
81                                                  version)); /* no-op */
82     else if (xwl_screen->eglstream_backend.is_available &&
83              xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
84                                                             registry,
85                                                             id,
86                                                             interface,
87                                                             version)); /* no-op */
88 }
89 
90 Bool
xwl_glamor_has_wl_interfaces(struct xwl_screen * xwl_screen,struct xwl_egl_backend * xwl_egl_backend)91 xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen,
92                             struct xwl_egl_backend *xwl_egl_backend)
93 {
94     return xwl_egl_backend->has_wl_interfaces(xwl_screen);
95 }
96 
97 struct wl_buffer *
xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,Bool * created)98 xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
99                                 Bool *created)
100 {
101     struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
102 
103     if (xwl_screen->egl_backend->get_wl_buffer_for_pixmap)
104         return xwl_screen->egl_backend->get_wl_buffer_for_pixmap(pixmap,
105                                                                  created);
106 
107     return NULL;
108 }
109 
110 void
xwl_glamor_post_damage(struct xwl_window * xwl_window,PixmapPtr pixmap,RegionPtr region)111 xwl_glamor_post_damage(struct xwl_window *xwl_window,
112                        PixmapPtr pixmap, RegionPtr region)
113 {
114     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
115 
116     if (xwl_screen->egl_backend->post_damage)
117         xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
118 }
119 
120 Bool
xwl_glamor_allow_commits(struct xwl_window * xwl_window)121 xwl_glamor_allow_commits(struct xwl_window *xwl_window)
122 {
123     struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
124 
125     if (xwl_screen->egl_backend->allow_commits)
126         return xwl_screen->egl_backend->allow_commits(xwl_window);
127     else
128         return TRUE;
129 }
130 
131 static Bool
xwl_glamor_create_screen_resources(ScreenPtr screen)132 xwl_glamor_create_screen_resources(ScreenPtr screen)
133 {
134     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
135     int ret;
136 
137     screen->CreateScreenResources = xwl_screen->CreateScreenResources;
138     ret = (*screen->CreateScreenResources) (screen);
139     xwl_screen->CreateScreenResources = screen->CreateScreenResources;
140     screen->CreateScreenResources = xwl_glamor_create_screen_resources;
141 
142     if (!ret)
143         return ret;
144 
145     if (xwl_screen->rootless) {
146         screen->devPrivate =
147             fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
148     }
149     else {
150         screen->devPrivate = screen->CreatePixmap(
151             screen, screen->width, screen->height, screen->rootDepth,
152             CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
153     }
154 
155     SetRootClip(screen, xwl_screen->root_clip_mode);
156 
157     return screen->devPrivate != NULL;
158 }
159 
160 int
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)161 glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
162                                PixmapPtr pixmap,
163                                CARD16 *stride, CARD32 *size)
164 {
165     return 0;
166 }
167 
168 void
xwl_glamor_init_backends(struct xwl_screen * xwl_screen,Bool use_eglstream)169 xwl_glamor_init_backends(struct xwl_screen *xwl_screen, Bool use_eglstream)
170 {
171 #ifdef GLAMOR_HAS_GBM
172     xwl_glamor_init_gbm(xwl_screen);
173     if (!xwl_screen->gbm_backend.is_available && !use_eglstream)
174         ErrorF("xwayland glamor: GBM backend (default) is not available\n");
175 #endif
176 #ifdef XWL_HAS_EGLSTREAM
177     xwl_glamor_init_eglstream(xwl_screen);
178     if (!xwl_screen->eglstream_backend.is_available && use_eglstream)
179         ErrorF("xwayland glamor: EGLStream backend requested but not available\n");
180 #endif
181 }
182 
183 static Bool
xwl_glamor_select_gbm_backend(struct xwl_screen * xwl_screen)184 xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
185 {
186 #ifdef GLAMOR_HAS_GBM
187     if (xwl_screen->gbm_backend.is_available &&
188         xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->gbm_backend)) {
189         xwl_screen->egl_backend = &xwl_screen->gbm_backend;
190         return TRUE;
191     }
192     else
193         ErrorF("Missing Wayland requirements for glamor GBM backend\n");
194 #endif
195 
196     return FALSE;
197 }
198 
199 static Bool
xwl_glamor_select_eglstream_backend(struct xwl_screen * xwl_screen)200 xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
201 {
202 #ifdef XWL_HAS_EGLSTREAM
203     if (xwl_screen->eglstream_backend.is_available &&
204         xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
205         ErrorF("glamor: Using nvidia's EGLStream interface, direct rendering impossible.\n");
206         ErrorF("glamor: Performance may be affected. Ask your vendor to support GBM!\n");
207         xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
208         return TRUE;
209     }
210     else
211         ErrorF("Missing Wayland requirements for glamor EGLStream backend\n");
212 #endif
213 
214     return FALSE;
215 }
216 
217 void
xwl_glamor_select_backend(struct xwl_screen * xwl_screen,Bool use_eglstream)218 xwl_glamor_select_backend(struct xwl_screen *xwl_screen, Bool use_eglstream)
219 {
220     if (use_eglstream) {
221         if (!xwl_glamor_select_eglstream_backend(xwl_screen))
222             xwl_glamor_select_gbm_backend(xwl_screen);
223     }
224     else {
225         if (!xwl_glamor_select_gbm_backend(xwl_screen))
226             xwl_glamor_select_eglstream_backend(xwl_screen);
227     }
228 }
229 
230 Bool
xwl_glamor_init(struct xwl_screen * xwl_screen)231 xwl_glamor_init(struct xwl_screen *xwl_screen)
232 {
233     ScreenPtr screen = xwl_screen->screen;
234     const char *no_glamor_env;
235 
236     no_glamor_env = getenv("XWAYLAND_NO_GLAMOR");
237     if (no_glamor_env && *no_glamor_env != '0') {
238         ErrorF("Disabling glamor and dri3 support, XWAYLAND_NO_GLAMOR is set\n");
239         return FALSE;
240     }
241 
242     if (!xwl_screen->egl_backend->init_egl(xwl_screen)) {
243         ErrorF("EGL setup failed, disabling glamor\n");
244         return FALSE;
245     }
246 
247     if (!glamor_init(xwl_screen->screen, GLAMOR_USE_EGL_SCREEN)) {
248         ErrorF("Failed to initialize glamor\n");
249         return FALSE;
250     }
251 
252     if (!xwl_screen->egl_backend->init_screen(xwl_screen)) {
253         ErrorF("EGL backend init_screen() failed, disabling glamor\n");
254         return FALSE;
255     }
256 
257     xwl_screen->CreateScreenResources = screen->CreateScreenResources;
258     screen->CreateScreenResources = xwl_glamor_create_screen_resources;
259 
260 #ifdef XV
261     if (!xwl_glamor_xv_init(screen))
262         ErrorF("Failed to initialize glamor Xv extension\n");
263 #endif
264 
265     return TRUE;
266 }
267