how-lix-os-pkgs/xorg-server/default/alpine-patches/xwayland-glx.patch

420 lines
13 KiB
Diff

diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
index 36bf213..c8746e5 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 48e330a..dcfc7f1 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -31,6 +31,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)
@@ -262,5 +265,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 0000000..71c9aad
--- /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@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 0854df4..a4804fe 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -488,4 +488,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