xwayland: refactor EGL backends for wayland registry
To be able to check for availability of the Wayland interfaces required to run a given EGL backend (either GBM or EGLStream for now), we need to have each backend structures and vfuncs in place before we enter the Wayland registry dance. That basically means that we should init all backends at first, connect to the Wayland compositor and query the available interfaces and then decide which backend is available and should be used (or none if either the Wayland interfaces or the EGL extensions are not available). For this purpose, hold an egl_backend struct for each backend we are to consider prior to connect to the Wayland display so that, when we get to query the Wayland interfaces, everything is in place for each backend to handle the various Wayland interfaces. Eventually, when we need to chose which EGL backend to use for glamor, the available Wayland interfaces and EGL extensions available are all known to Xwayland. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
This commit is contained in:
parent
48f037a27c
commit
d7185a84b6
|
@ -638,7 +638,7 @@ const struct wl_eglstream_display_listener eglstream_display_listener = {
|
|||
.swapinterval_override = xwl_eglstream_display_handle_swapinterval_override,
|
||||
};
|
||||
|
||||
static void
|
||||
static Bool
|
||||
xwl_glamor_eglstream_init_wl_registry(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t id, const char *name,
|
||||
|
@ -654,10 +654,15 @@ xwl_glamor_eglstream_init_wl_registry(struct xwl_screen *xwl_screen,
|
|||
wl_eglstream_display_add_listener(xwl_eglstream->display,
|
||||
&eglstream_display_listener,
|
||||
xwl_screen);
|
||||
return TRUE;
|
||||
} else if (strcmp(name, "wl_eglstream_controller") == 0) {
|
||||
xwl_eglstream->controller = wl_registry_bind(
|
||||
wl_registry, id, &wl_eglstream_controller_interface, version);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* no match */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
|
@ -882,23 +887,24 @@ out:
|
|||
return device;
|
||||
}
|
||||
|
||||
Bool
|
||||
void
|
||||
xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_eglstream_private *xwl_eglstream;
|
||||
EGLDeviceEXT egl_device;
|
||||
|
||||
xwl_screen->eglstream_backend.is_available = FALSE;
|
||||
egl_device = xwl_eglstream_get_device(xwl_screen);
|
||||
if (egl_device == EGL_NO_DEVICE_EXT)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_eglstream_private_key, PRIVATE_SCREEN, 0))
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
xwl_eglstream = calloc(sizeof(*xwl_eglstream), 1);
|
||||
if (!xwl_eglstream) {
|
||||
ErrorF("Failed to allocate memory required to init eglstream support\n");
|
||||
return FALSE;
|
||||
ErrorF("Failed to allocate memory required to init EGLStream support\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dixSetPrivate(&xwl_screen->screen->devPrivates,
|
||||
|
@ -907,15 +913,12 @@ xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
|||
xwl_eglstream->egl_device = egl_device;
|
||||
xorg_list_init(&xwl_eglstream->pending_streams);
|
||||
|
||||
xwl_screen->egl_backend.init_egl = xwl_glamor_eglstream_init_egl;
|
||||
xwl_screen->egl_backend.init_wl_registry = xwl_glamor_eglstream_init_wl_registry;
|
||||
xwl_screen->egl_backend.has_wl_interfaces = xwl_glamor_eglstream_has_wl_interfaces;
|
||||
xwl_screen->egl_backend.init_screen = xwl_glamor_eglstream_init_screen;
|
||||
xwl_screen->egl_backend.get_wl_buffer_for_pixmap = xwl_glamor_eglstream_get_wl_buffer_for_pixmap;
|
||||
xwl_screen->egl_backend.post_damage = xwl_glamor_eglstream_post_damage;
|
||||
xwl_screen->egl_backend.allow_commits = xwl_glamor_eglstream_allow_commits;
|
||||
|
||||
ErrorF("glamor: Using nvidia's eglstream interface, direct rendering impossible.\n");
|
||||
ErrorF("glamor: Performance may be affected. Ask your vendor to support GBM!\n");
|
||||
return TRUE;
|
||||
xwl_screen->eglstream_backend.init_egl = xwl_glamor_eglstream_init_egl;
|
||||
xwl_screen->eglstream_backend.init_wl_registry = xwl_glamor_eglstream_init_wl_registry;
|
||||
xwl_screen->eglstream_backend.has_wl_interfaces = xwl_glamor_eglstream_has_wl_interfaces;
|
||||
xwl_screen->eglstream_backend.init_screen = xwl_glamor_eglstream_init_screen;
|
||||
xwl_screen->eglstream_backend.get_wl_buffer_for_pixmap = xwl_glamor_eglstream_get_wl_buffer_for_pixmap;
|
||||
xwl_screen->eglstream_backend.post_damage = xwl_glamor_eglstream_post_damage;
|
||||
xwl_screen->eglstream_backend.allow_commits = xwl_glamor_eglstream_allow_commits;
|
||||
xwl_screen->eglstream_backend.is_available = TRUE;
|
||||
}
|
||||
|
|
|
@ -734,16 +734,29 @@ xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
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)
|
||||
{
|
||||
if (strcmp(name, "wl_drm") == 0)
|
||||
if (strcmp(name, "wl_drm") == 0) {
|
||||
xwl_screen_set_drm_interface(xwl_screen, id, version);
|
||||
else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0)
|
||||
return TRUE;
|
||||
} else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0) {
|
||||
xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* no match */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_gbm_has_egl_extension(void)
|
||||
{
|
||||
return (epoxy_has_egl_extension(NULL, "EGL_MESA_platform_gbm") ||
|
||||
epoxy_has_egl_extension(NULL, "EGL_KHR_platform_gbm"));
|
||||
}
|
||||
|
||||
static Bool
|
||||
|
@ -882,28 +895,32 @@ error:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
Bool
|
||||
void
|
||||
xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_gbm_private *xwl_gbm;
|
||||
|
||||
xwl_screen->gbm_backend.is_available = FALSE;
|
||||
|
||||
if (!xwl_glamor_gbm_has_egl_extension())
|
||||
return;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_gbm_private_key, PRIVATE_SCREEN, 0))
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
xwl_gbm = calloc(sizeof(*xwl_gbm), 1);
|
||||
if (!xwl_gbm) {
|
||||
ErrorF("glamor: Not enough memory to setup GBM, disabling\n");
|
||||
return FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
dixSetPrivate(&xwl_screen->screen->devPrivates, &xwl_gbm_private_key,
|
||||
xwl_gbm);
|
||||
|
||||
xwl_screen->egl_backend.init_wl_registry = xwl_glamor_gbm_init_wl_registry;
|
||||
xwl_screen->egl_backend.has_wl_interfaces = xwl_glamor_gbm_has_wl_interfaces;
|
||||
xwl_screen->egl_backend.init_egl = xwl_glamor_gbm_init_egl;
|
||||
xwl_screen->egl_backend.init_screen = xwl_glamor_gbm_init_screen;
|
||||
xwl_screen->egl_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
|
||||
|
||||
return TRUE;
|
||||
xwl_screen->gbm_backend.init_wl_registry = xwl_glamor_gbm_init_wl_registry;
|
||||
xwl_screen->gbm_backend.has_wl_interfaces = xwl_glamor_gbm_has_wl_interfaces;
|
||||
xwl_screen->gbm_backend.init_egl = xwl_glamor_gbm_init_egl;
|
||||
xwl_screen->gbm_backend.init_screen = xwl_glamor_gbm_init_screen;
|
||||
xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
|
||||
xwl_screen->gbm_backend.is_available = TRUE;
|
||||
}
|
||||
|
|
|
@ -71,9 +71,20 @@ xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
|
|||
uint32_t id, const char *interface,
|
||||
uint32_t version)
|
||||
{
|
||||
if (xwl_screen->egl_backend.init_wl_registry)
|
||||
xwl_screen->egl_backend.init_wl_registry(xwl_screen, registry,
|
||||
id, interface, version);
|
||||
if (xwl_screen->gbm_backend.is_available &&
|
||||
xwl_screen->gbm_backend.init_wl_registry &&
|
||||
xwl_screen->gbm_backend.init_wl_registry(xwl_screen,
|
||||
registry,
|
||||
id,
|
||||
interface,
|
||||
version)); /* no-op */
|
||||
else if (xwl_screen->eglstream_backend.is_available &&
|
||||
xwl_screen->eglstream_backend.init_wl_registry &&
|
||||
xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
|
||||
registry,
|
||||
id,
|
||||
interface,
|
||||
version)); /* no-op */
|
||||
}
|
||||
|
||||
Bool
|
||||
|
@ -95,8 +106,8 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
|
|||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
||||
|
||||
if (xwl_screen->egl_backend.get_wl_buffer_for_pixmap)
|
||||
return xwl_screen->egl_backend.get_wl_buffer_for_pixmap(pixmap,
|
||||
if (xwl_screen->egl_backend->get_wl_buffer_for_pixmap)
|
||||
return xwl_screen->egl_backend->get_wl_buffer_for_pixmap(pixmap,
|
||||
width,
|
||||
height,
|
||||
created);
|
||||
|
@ -110,8 +121,8 @@ xwl_glamor_post_damage(struct xwl_window *xwl_window,
|
|||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
|
||||
if (xwl_screen->egl_backend.post_damage)
|
||||
xwl_screen->egl_backend.post_damage(xwl_window, pixmap, region);
|
||||
if (xwl_screen->egl_backend->post_damage)
|
||||
xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
|
||||
}
|
||||
|
||||
Bool
|
||||
|
@ -119,8 +130,8 @@ xwl_glamor_allow_commits(struct xwl_window *xwl_window)
|
|||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
|
||||
if (xwl_screen->egl_backend.allow_commits)
|
||||
return xwl_screen->egl_backend.allow_commits(xwl_window);
|
||||
if (xwl_screen->egl_backend->allow_commits)
|
||||
return xwl_screen->egl_backend->allow_commits(xwl_window);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -165,17 +176,62 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
|||
void
|
||||
xwl_glamor_init_backends(struct xwl_screen *xwl_screen, Bool use_eglstream)
|
||||
{
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
if (use_eglstream) {
|
||||
if (!xwl_glamor_init_eglstream(xwl_screen)) {
|
||||
ErrorF("xwayland glamor: failed to setup EGLStream backend\n");
|
||||
use_eglstream = FALSE;
|
||||
}
|
||||
}
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
xwl_glamor_init_gbm(xwl_screen);
|
||||
if (!xwl_screen->gbm_backend.is_available && !use_eglstream)
|
||||
ErrorF("xwayland glamor: GBM backend (default) is not available\n");
|
||||
#endif
|
||||
if (!use_eglstream && !xwl_glamor_init_gbm(xwl_screen)) {
|
||||
ErrorF("xwayland glamor: failed to setup GBM backend, falling back to sw accel\n");
|
||||
xwl_screen->glamor = 0;
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
xwl_glamor_init_eglstream(xwl_screen);
|
||||
if (!xwl_screen->eglstream_backend.is_available && use_eglstream)
|
||||
ErrorF("xwayland glamor: EGLStream backend requested but not available\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_screen->gbm_backend.is_available &&
|
||||
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->gbm_backend)) {
|
||||
xwl_screen->egl_backend = &xwl_screen->gbm_backend;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
ErrorF("Missing Wayland requirements for glamor GBM backend\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
if (xwl_screen->eglstream_backend.is_available &&
|
||||
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
|
||||
ErrorF("glamor: Using nvidia's EGLStream interface, direct rendering impossible.\n");
|
||||
ErrorF("glamor: Performance may be affected. Ask your vendor to support GBM!\n");
|
||||
xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
ErrorF("Missing Wayland requirements for glamor EGLStream backend\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_glamor_select_backend(struct xwl_screen *xwl_screen, Bool use_eglstream)
|
||||
{
|
||||
if (use_eglstream) {
|
||||
if (!xwl_glamor_select_eglstream_backend(xwl_screen))
|
||||
xwl_glamor_select_gbm_backend(xwl_screen);
|
||||
}
|
||||
else {
|
||||
if (!xwl_glamor_select_gbm_backend(xwl_screen))
|
||||
xwl_glamor_select_eglstream_backend(xwl_screen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +247,7 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!xwl_screen->egl_backend.init_egl(xwl_screen)) {
|
||||
if (!xwl_screen->egl_backend->init_egl(xwl_screen)) {
|
||||
ErrorF("EGL setup failed, disabling glamor\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -201,7 +257,7 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!xwl_screen->egl_backend.init_screen(xwl_screen)) {
|
||||
if (!xwl_screen->egl_backend->init_screen(xwl_screen)) {
|
||||
ErrorF("EGL backend init_screen() failed, disabling glamor\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -549,7 +549,7 @@ xwl_present_init(ScreenPtr screen)
|
|||
* doesn't work with the streams backend. we don't have an explicit
|
||||
* boolean for that, but we do know gbm doesn't fill in this hook...
|
||||
*/
|
||||
if (xwl_screen->egl_backend.post_damage != NULL)
|
||||
if (xwl_screen->egl_backend->post_damage != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0))
|
||||
|
|
|
@ -737,7 +737,7 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)
|
|||
continue;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (!xwl_glamor_allow_commits(xwl_window))
|
||||
if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
|
@ -1079,9 +1079,13 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
return FALSE;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor && !xwl_glamor_init(xwl_screen)) {
|
||||
ErrorF("Failed to initialize glamor, falling back to sw\n");
|
||||
xwl_screen->glamor = 0;
|
||||
if (xwl_screen->glamor) {
|
||||
xwl_glamor_select_backend(xwl_screen, use_eglstreams);
|
||||
|
||||
if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
|
||||
ErrorF("Failed to initialize glamor, falling back to sw\n");
|
||||
xwl_screen->glamor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_screen->glamor && xwl_screen->rootless)
|
||||
|
|
|
@ -60,11 +60,14 @@ struct xwl_window;
|
|||
struct xwl_screen;
|
||||
|
||||
struct xwl_egl_backend {
|
||||
/* Set by the backend if available */
|
||||
Bool is_available;
|
||||
|
||||
/* Called once for each interface in the global registry. Backends
|
||||
* should use this to bind to any wayland interfaces they need. This
|
||||
* callback is optional.
|
||||
*/
|
||||
void (*init_wl_registry)(struct xwl_screen *xwl_screen,
|
||||
Bool (*init_wl_registry)(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t id, const char *name,
|
||||
uint32_t version);
|
||||
|
@ -164,8 +167,10 @@ struct xwl_screen {
|
|||
struct xwl_format *formats;
|
||||
void *egl_display, *egl_context;
|
||||
|
||||
/* the current backend for creating pixmaps on wayland */
|
||||
struct xwl_egl_backend egl_backend;
|
||||
struct xwl_egl_backend gbm_backend;
|
||||
struct xwl_egl_backend eglstream_backend;
|
||||
/* pointer to the current backend for creating pixmaps on wayland */
|
||||
struct xwl_egl_backend *egl_backend;
|
||||
|
||||
struct glamor_context *glamor_ctx;
|
||||
|
||||
|
@ -425,6 +430,8 @@ struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
|
|||
#ifdef XWL_HAS_GLAMOR
|
||||
void xwl_glamor_init_backends(struct xwl_screen *xwl_screen,
|
||||
Bool use_eglstream);
|
||||
void xwl_glamor_select_backend(struct xwl_screen *xwl_screen,
|
||||
Bool use_eglstream);
|
||||
Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
|
||||
|
||||
Bool xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
|
||||
|
@ -467,20 +474,18 @@ void xwlVidModeExtensionInit(void);
|
|||
#endif
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
Bool xwl_glamor_init_gbm(struct xwl_screen *xwl_screen);
|
||||
void xwl_glamor_init_gbm(struct xwl_screen *xwl_screen);
|
||||
#else
|
||||
static inline Bool xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
|
||||
static inline void xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
Bool xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen);
|
||||
void xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen);
|
||||
#else
|
||||
static inline Bool xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
||||
static inline void xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user