/* * Copyright © 2011-2014 Intel Corporation * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of the * copyright holders not be used in advertising or publicity * pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include #include #include "compositeext_priv.h" #define MESA_EGL_NO_X11_HEADERS #define EGL_NO_X11 #include #include #include #include #ifdef GLXEXT #include "glx_extinit.h" #endif #include "drm-client-protocol.h" #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "xwayland-dmabuf.h" #include "xwayland-glamor.h" #include "xwayland-glamor-gbm.h" #include "xwayland-screen.h" #include "xwayland-window.h" #include "xwayland-window-buffers.h" #include static void glamor_egl_make_current(struct glamor_context *glamor_ctx) { eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE, glamor_ctx->ctx)) FatalError("Failed to make EGL context current\n"); } void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen) { EGLContext ctx = xwl_screen->glamor_ctx->ctx; if (lastGLContext == ctx) return; lastGLContext = ctx; xwl_screen->glamor_ctx->make_current(xwl_screen->glamor_ctx); } void glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) { struct xwl_screen *xwl_screen = xwl_screen_get(screen); glamor_set_glvnd_vendor(screen, xwl_screen->glvnd_vendor); glamor_enable_dri3(screen); glamor_ctx->ctx = xwl_screen->egl_context; glamor_ctx->display = xwl_screen->egl_display; glamor_ctx->make_current = glamor_egl_make_current; xwl_screen->glamor_ctx = glamor_ctx; } Bool xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap) { ScreenPtr screen = pixmap->drawable.pScreen; PixmapPtr backing_pixmap = screen->GetWindowPixmap(present_window); if (pixmap->drawable.depth != backing_pixmap->drawable.depth) return FALSE; return TRUE; } void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { if (strcmp(interface, wl_drm_interface.name) == 0) xwl_screen_set_drm_interface(xwl_screen, id, version); else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) xwl_screen_set_dmabuf_interface(xwl_screen, id, version); } static Bool xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen) { if (!xwl_glamor_has_wl_drm(xwl_screen) && xwl_screen->dmabuf_protocol_version < 4) { LogMessageVerb(X_INFO, 3, "glamor: 'wl_drm' not supported and linux-dmabuf v4 not supported\n"); return FALSE; } return TRUE; } static void xwl_avoid_implicit_redirect(WindowPtr window) { ScreenPtr screen = window->drawable.pScreen; WindowOptPtr parent_optional; VisualPtr parent_visual = NULL; VisualPtr window_visual = NULL; DepthPtr depth32 = NULL; int i; if (!window->optional) return; parent_optional = FindWindowWithOptional(window)->optional; if (window->optional == parent_optional || window->optional->visual == parent_optional->visual || CompositeIsImplicitRedirectException(screen, parent_optional->visual, window->optional->visual)) return; for (i = 0; i < screen->numDepths; i++) { if (screen->allowedDepths[i].depth == 32) { depth32 = &screen->allowedDepths[i]; break; } } if (!depth32) return; for (i = 0; i < depth32->numVids; i++) { XID argb_vid = depth32->vids[i]; if (argb_vid != parent_optional->visual) continue; if (!compIsAlternateVisual(screen, argb_vid)) break; for (i = 0; i < screen->numVisuals; i++) { if (screen->visuals[i].vid == argb_vid) { parent_visual = &screen->visuals[i]; break; } } } if (!parent_visual) return; for (i = 0; i < screen->numVisuals; i++) { if (screen->visuals[i].vid == window->optional->visual) { window_visual = &screen->visuals[i]; break; } } if ((window_visual->class != TrueColor && window_visual->class != DirectColor) || window_visual->redMask != parent_visual->redMask || window_visual->greenMask != parent_visual->greenMask || window_visual->blueMask != parent_visual->blueMask || window_visual->offsetRed != parent_visual->offsetRed || window_visual->offsetGreen != parent_visual->offsetGreen || window_visual->offsetBlue != parent_visual->offsetBlue) return; CompositeRegisterImplicitRedirectionException(screen, parent_visual->vid, window_visual->vid); } static Bool xwl_glamor_create_window(WindowPtr window) { ScreenPtr screen = window->drawable.pScreen; struct xwl_screen *xwl_screen = xwl_screen_get(screen); Bool ret; if (window->parent) xwl_avoid_implicit_redirect(window); screen->CreateWindow = xwl_screen->CreateWindow; ret = (*screen->CreateWindow) (window); xwl_screen->CreateWindow = screen->CreateWindow; screen->CreateWindow = xwl_glamor_create_window; return ret; } static void xwl_glamor_reparent_window(WindowPtr window, WindowPtr old_parent) { ScreenPtr screen = window->drawable.pScreen; struct xwl_screen *xwl_screen = xwl_screen_get(screen); xwl_avoid_implicit_redirect(window); screen->ReparentWindow = xwl_screen->ReparentWindow; (*screen->ReparentWindow) (window, old_parent); xwl_screen->ReparentWindow = screen->ReparentWindow; screen->ReparentWindow = xwl_glamor_reparent_window; } static Bool xwl_glamor_create_screen_resources(ScreenPtr screen) { struct xwl_screen *xwl_screen = xwl_screen_get(screen); int ret; screen->CreateScreenResources = xwl_screen->CreateScreenResources; ret = (*screen->CreateScreenResources) (screen); xwl_screen->CreateScreenResources = screen->CreateScreenResources; screen->CreateScreenResources = xwl_glamor_create_screen_resources; if (!ret) return ret; xwl_screen->CreateWindow = screen->CreateWindow; screen->CreateWindow = xwl_glamor_create_window; xwl_screen->ReparentWindow = screen->ReparentWindow; screen->ReparentWindow = xwl_glamor_reparent_window; if (xwl_screen->rootless) { screen->devPrivate = fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0); } else { screen->devPrivate = screen->CreatePixmap( screen, screen->width, screen->height, screen->rootDepth, CREATE_PIXMAP_USAGE_BACKING_PIXMAP); } SetRootClip(screen, xwl_screen->root_clip_mode); return screen->devPrivate != NULL; } int glamor_egl_fd_name_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) { return 0; } int xwl_glamor_get_fence(struct xwl_screen *xwl_screen) { EGLint attribs[3]; EGLSyncKHR sync; int fence_fd = -1; if (!xwl_screen->glamor) return -1; xwl_glamor_egl_make_current(xwl_screen); attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; attribs[1] = EGL_NO_NATIVE_FENCE_FD_ANDROID; attribs[2] = EGL_NONE; sync = eglCreateSyncKHR(xwl_screen->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (sync != EGL_NO_SYNC_KHR) { fence_fd = eglDupNativeFenceFDANDROID(xwl_screen->egl_display, sync); eglDestroySyncKHR(xwl_screen->egl_display, sync); } return fence_fd; } Bool xwl_glamor_init(struct xwl_screen *xwl_screen) { ScreenPtr screen = xwl_screen->screen; const char *no_glamor_env; no_glamor_env = getenv("XWAYLAND_NO_GLAMOR"); if (no_glamor_env && *no_glamor_env != '0') { ErrorF("Disabling glamor and dri3 support, XWAYLAND_NO_GLAMOR is set\n"); return FALSE; } if (!xwl_glamor_has_wl_interfaces(xwl_screen)) { ErrorF("Xwayland glamor: GBM Wayland interfaces not available\n"); return FALSE; } if (!xwl_glamor_gbm_init_egl(xwl_screen)) { ErrorF("EGL setup failed, disabling glamor\n"); return FALSE; } if (!glamor_init(xwl_screen->screen, GLAMOR_USE_EGL_SCREEN)) { ErrorF("Failed to initialize glamor\n"); return FALSE; } if (!xwl_glamor_gbm_init_screen(xwl_screen)) { ErrorF("EGL backend init_screen() failed, disabling glamor\n"); return FALSE; } xwl_screen->CreateScreenResources = screen->CreateScreenResources; screen->CreateScreenResources = xwl_glamor_create_screen_resources; #ifdef XV if (!xwl_glamor_xv_init(screen)) ErrorF("Failed to initialize glamor Xv extension\n"); #endif #ifdef GLXEXT GlxPushProvider(&glamor_provider); #endif return TRUE; }