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