xserver: Branch 'master'

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu May 23 16:46:15 UTC 2019


 hw/xwayland/Makefile.am       |    4 
 hw/xwayland/meson.build       |   10 +
 hw/xwayland/xwayland-glamor.c |    7 
 hw/xwayland/xwayland-glx.c    |  344 ++++++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland.h        |    5 
 5 files changed, 369 insertions(+), 1 deletion(-)

New commits:
commit 8469241592b94b002a975274a596ca0dcdd9563f
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed May 8 14:09:00 2019 -0400

    xwayland: Add EGL-backed GLX provider
    
    Without this we're using driswrast to set up GLX visuals. This is
    unfortunate because llvmpipe does not expose multisample configs, so
    various apps that expect them will fail. With this we just query the
    capabilities of the EGL that's backing glamor, and reflect that to the
    GLX clients. This also paves the way for xserver to stop being a DRI
    driver loader, which is nice.
    
    Fixes: xorg/xserver#640
    Fixes: xorg/xserver#643
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=98272
    Reviewed-by: Olivier Fourdan <ofourdan at redhat.com>
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 502879e2a..282da58f9 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -22,6 +22,10 @@ Xwayland_SOURCES =				\
 	$(top_srcdir)/mi/miinitext.c
 
 if GLX
+Xwayland_SOURCES += 				\
+	xwayland-glx.c
+Xwayland_CFLAGS +=				\
+	-I$(top_srcdir)/glx
 GLXVND_LIB = $(top_builddir)/glx/libglxvnd.la
 endif
 
diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
index 36bf2133a..c8746e591 100644
--- a/hw/xwayland/meson.build
+++ b/hw/xwayland/meson.build
@@ -54,6 +54,9 @@ xwayland_glamor = []
 eglstream_srcs = []
 if build_glamor
     srcs += 'xwayland-glamor.c'
+    if build_glx
+        srcs += 'xwayland-glx.c'
+    endif
     if gbm_dep.found()
         srcs += 'xwayland-glamor-gbm.c'
     endif
@@ -80,10 +83,15 @@ if build_glamor
     xwayland_glamor += glamor
 endif
 
+wayland_inc = [ inc, ]
+if build_glx
+    wayland_inc += glx_inc
+endif
+
 executable(
     'Xwayland',
     srcs,
-    include_directories: inc,
+    include_directories: wayland_inc,
     dependencies: [
         common_dep,
         xwayland_dep,
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index f4bd561ea..dc07f7933 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -30,6 +30,9 @@
 
 #include <glamor.h>
 #include <glamor_context.h>
+#ifdef GLXEXT
+#include "glx_extinit.h"
+#endif
 
 static void
 glamor_egl_make_current(struct glamor_context *glamor_ctx)
@@ -264,5 +267,9 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
         ErrorF("Failed to initialize glamor Xv extension\n");
 #endif
 
+#ifdef GLXEXT
+    GlxPushProvider(&glamor_provider);
+#endif
+
     return TRUE;
 }
diff --git a/hw/xwayland/xwayland-glx.c b/hw/xwayland/xwayland-glx.c
new file mode 100644
index 000000000..71c9aad23
--- /dev/null
+++ b/hw/xwayland/xwayland-glx.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Adam Jackson <ajax at redhat.com>
+ */
+
+/*
+ * Sets up GLX capabilities based on the EGL capabilities of the glamor
+ * renderer for the screen. Without this you will get whatever swrast
+ * can do, which often does not include things like multisample visuals.
+ */
+
+#include <xwayland-config.h>
+#include "xwayland.h"
+#define MESA_EGL_NO_X11_HEADERS
+// #include <EGL/egl.h>
+#include <epoxy/egl.h>
+#include "glxserver.h"
+#include "glxutil.h"
+#include "compint.h"
+#include <X11/extensions/composite.h>
+#include "glamor_context.h"
+#include "glamor.h"
+
+/* Can't get these from <GL/glx.h> since it pulls in client headers */
+#define GLX_RGBA_BIT		0x00000001
+#define GLX_WINDOW_BIT		0x00000001
+#define GLX_PIXMAP_BIT		0x00000002
+#define GLX_PBUFFER_BIT		0x00000004
+#define GLX_NONE                0x8000
+#define GLX_SLOW_CONFIG         0x8001
+#define GLX_TRUE_COLOR		0x8002
+#define GLX_DIRECT_COLOR	0x8003
+#define GLX_NON_CONFORMANT_CONFIG 0x800D
+#define GLX_DONT_CARE           0xFFFFFFFF
+#define GLX_RGBA_FLOAT_BIT_ARB  0x00000004
+#define GLX_SWAP_UNDEFINED_OML  0x8063
+
+struct egl_config {
+    __GLXconfig base;
+    EGLConfig config;
+};
+
+struct egl_screen {
+    __GLXscreen base;
+    EGLDisplay display;
+    EGLConfig *configs;
+};
+
+static void
+egl_screen_destroy(__GLXscreen *_screen)
+{
+    struct egl_screen *screen = (struct egl_screen *)_screen;
+
+    /* XXX do we leak the fbconfig list? */
+
+    free(screen->configs);
+    __glXScreenDestroy(_screen);
+    free(_screen);
+}
+
+static void
+egl_drawable_destroy(__GLXdrawable *draw)
+{
+    free(draw);
+}
+
+static GLboolean
+egl_drawable_swap_buffers(ClientPtr client, __GLXdrawable *draw)
+{
+    return GL_FALSE;
+}
+
+static void
+egl_drawable_copy_sub_buffer(__GLXdrawable *draw, int x, int y, int w, int h)
+{
+}
+
+static void
+egl_drawable_wait_x(__GLXdrawable *draw)
+{
+    glamor_block_handler(draw->pDraw->pScreen);
+}
+
+static void
+egl_drawable_wait_gl(__GLXdrawable *draw)
+{
+}
+
+static __GLXdrawable *
+egl_create_glx_drawable(ClientPtr client, __GLXscreen *screen,
+                        DrawablePtr draw, XID drawid, int type,
+                        XID glxdrawid, __GLXconfig *modes)
+{
+    __GLXdrawable *ret;
+
+    ret = calloc(1, sizeof *ret);
+    if (!ret)
+        return NULL;
+
+    if (!__glXDrawableInit(ret, screen, draw, type, glxdrawid, modes)) {
+        free(ret);
+        return NULL;
+    }
+
+    ret->destroy = egl_drawable_destroy;
+    ret->swapBuffers = egl_drawable_swap_buffers;
+    ret->copySubBuffer = egl_drawable_copy_sub_buffer;
+    ret->waitX = egl_drawable_wait_x;
+    ret->waitGL = egl_drawable_wait_gl;
+
+    return ret;
+}
+
+/*
+ * TODO:
+ *
+ * - figure out sRGB
+ * - bindToTextureTargets is suspicious
+ * - better channel mask setup
+ * - drawable type masks is suspicious
+ */
+static struct egl_config *
+translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
+                    struct egl_config *chain, Bool direct_color,
+                    Bool double_buffer)
+{
+    EGLint value;
+    struct egl_config *c = calloc(1, sizeof *c);
+
+    if (!c)
+        return chain;
+
+    /* constants.  changing these requires (at least) new EGL extensions */
+    c->base.stereoMode = GL_FALSE;
+    c->base.numAuxBuffers = 0;
+    c->base.level = 0;
+    c->base.transparentAlpha = 0;
+    c->base.transparentIndex = 0;
+    c->base.transparentPixel = GLX_NONE;
+    c->base.visualSelectGroup = 0;
+    c->base.indexBits = 0;
+    c->base.optimalPbufferWidth = 0;
+    c->base.optimalPbufferHeight = 0;
+    c->base.bindToMipmapTexture = 0;
+    c->base.bindToTextureTargets = GLX_DONT_CARE;
+    c->base.sRGBCapable = 0;
+    c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
+
+    /* this is... suspect */
+    c->base.drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+
+    /* hmm */
+    c->base.bindToTextureRgb = GL_TRUE;
+    c->base.bindToTextureRgba = GL_TRUE;
+
+    /*
+     * glx conformance failure: there's no such thing as accumulation
+     * buffers in EGL.  they should be emulable with shaders and fbos,
+     * but i'm pretty sure nobody's using this feature since it's
+     * entirely software.  note that glx conformance merely requires
+     * that an accum buffer _exist_, not a minimum bitness.
+     */
+    c->base.accumRedBits = 0;
+    c->base.accumGreenBits = 0;
+    c->base.accumBlueBits = 0;
+    c->base.accumAlphaBits = 0;
+
+    /* parametric state */
+    if (direct_color)
+        c->base.visualType = GLX_DIRECT_COLOR;
+    else
+        c->base.visualType = GLX_TRUE_COLOR;
+
+    if (double_buffer)
+        c->base.doubleBufferMode = GL_TRUE;
+    else
+        c->base.doubleBufferMode = GL_FALSE;
+
+    /* direct-mapped state */
+#define GET(attr, slot) \
+    eglGetConfigAttrib(screen->display, hc, attr, &c->base.slot)
+    GET(EGL_RED_SIZE, redBits);
+    GET(EGL_GREEN_SIZE, greenBits);
+    GET(EGL_BLUE_SIZE, blueBits);
+    GET(EGL_ALPHA_SIZE, alphaBits);
+    GET(EGL_BUFFER_SIZE, rgbBits);
+    GET(EGL_DEPTH_SIZE, depthBits);
+    GET(EGL_STENCIL_SIZE, stencilBits);
+    GET(EGL_TRANSPARENT_RED_VALUE, transparentRed);
+    GET(EGL_TRANSPARENT_GREEN_VALUE, transparentGreen);
+    GET(EGL_TRANSPARENT_BLUE_VALUE, transparentBlue);
+    GET(EGL_SAMPLE_BUFFERS, sampleBuffers);
+    GET(EGL_SAMPLES, samples);
+    if (c->base.renderType & GLX_PBUFFER_BIT) {
+        GET(EGL_MAX_PBUFFER_WIDTH, maxPbufferWidth);
+        GET(EGL_MAX_PBUFFER_HEIGHT, maxPbufferHeight);
+        GET(EGL_MAX_PBUFFER_PIXELS, maxPbufferPixels);
+    }
+#undef GET
+
+    /* derived state: config caveats */
+    eglGetConfigAttrib(screen->display, hc, EGL_CONFIG_CAVEAT, &value);
+    if (value == EGL_NONE)
+        c->base.visualRating = GLX_NONE;
+    else if (value == EGL_SLOW_CONFIG)
+        c->base.visualRating = GLX_SLOW_CONFIG;
+    else if (value == EGL_NON_CONFORMANT_CONFIG)
+        c->base.visualRating = GLX_NON_CONFORMANT_CONFIG;
+    /* else panic */
+
+    /* derived state: float configs */
+    c->base.renderType = GLX_RGBA_BIT;
+    if (eglGetConfigAttrib(screen->display, hc, EGL_COLOR_COMPONENT_TYPE_EXT,
+                           &value) == EGL_TRUE) {
+        if (value == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) {
+            c->base.renderType = GLX_RGBA_FLOAT_BIT_ARB;
+        }
+        /* else panic */
+    }
+
+    /* map to the backend's config */
+    c->config = hc;
+
+    /*
+     * XXX do something less ugly
+     */
+    if (c->base.renderType == GLX_RGBA_BIT) {
+        if (c->base.rgbBits == 24 || c->base.rgbBits == 32) {
+            c->base.redMask = 0xff0000;
+            c->base.greenMask = 0x00ff00;
+            c->base.blueMask = 0x0000ff;
+            if (c->base.alphaBits)
+                /* assume all remaining bits are alpha */
+                c->base.alphaMask = 0xff000000;
+        }
+    }
+
+    c->base.next = chain ? &chain->base : NULL;
+    return c;
+}
+
+static __GLXconfig *
+egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen)
+{
+    int i, j, k, nconfigs;
+    struct egl_config *c = NULL;
+    EGLConfig *host_configs = NULL;
+    Bool offon[] = { FALSE, TRUE };
+
+    eglGetConfigs(screen->display, NULL, 0, &nconfigs);
+    if (!(host_configs = calloc(nconfigs, sizeof *host_configs)))
+        return NULL;
+
+    eglGetConfigs(screen->display, host_configs, nconfigs, &nconfigs);
+
+    /* We walk the EGL configs backwards to make building the
+     * ->next chain easier.
+     */
+    for (i = nconfigs - 1; i > 0; i--)
+        for (j = 0; j < 2; j++) /* direct_color */
+            for (k = 0; k < 2; k++) /* direct_color */
+                c = translate_eglconfig(screen, host_configs[i], c,
+                                        /* direct_color */ offon[j],
+                                        /* double_buffer */ offon[k]
+                                        );
+
+    screen->configs = host_configs;
+    return c ? &c->base : NULL;
+}
+
+static __GLXscreen *
+egl_screen_probe(ScreenPtr pScreen)
+{
+    struct egl_screen *screen;
+    struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
+    __GLXscreen *base;
+
+    if (enableIndirectGLX)
+        return NULL; /* not implemented */
+
+    if (!(screen = calloc(1, sizeof *screen)))
+        return NULL;
+
+    base = &screen->base;
+    base->destroy = egl_screen_destroy;
+    base->createDrawable = egl_create_glx_drawable;
+    /* base.swapInterval = NULL; */
+
+    screen->display = xwl_screen->glamor_ctx->display;
+
+    __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
+    __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_context_flush_control");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_no_error");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_profile");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_robustness");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_ARB_fbconfig_float");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_create_context_es2_profile");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_create_context_es_profile");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_fbconfig_packed_float");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_framebuffer_sRGB");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_no_config_context");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_EXT_texture_from_pixmap");
+    __glXEnableExtension(base->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
+    // __glXEnableExtension(base->glx_enable_bits, "GLX_SGI_swap_control");
+
+    base->fbconfigs = egl_mirror_configs(pScreen, screen);
+    if (!base->fbconfigs) {
+        free(screen);
+        return NULL;
+    }
+
+    __glXScreenInit(base, pScreen);
+    __glXsetGetProcAddress(eglGetProcAddress);
+
+    return base;
+}
+
+__GLXprovider glamor_provider = {
+    egl_screen_probe,
+    "glamor",
+    NULL
+};
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 92664e812..85691d9d4 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -485,4 +485,9 @@ static inline void xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
 }
 #endif
 
+#ifdef GLXEXT
+#include "glx_extinit.h"
+extern __GLXprovider glamor_provider;
+#endif
+
 #endif


More information about the xorg-commit mailing list