diff options
author | Adam Jackson <ajax@redhat.com> | 2017-06-29 09:16:51 -0400 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2017-07-14 14:35:13 -0400 |
commit | 130bd1e499153984b602af2b0555d764b59a3097 (patch) | |
tree | 8f089b4841d04f5e9730b1c60abc5737fec90083 | |
parent | 91ad98c950411ae03d1a3d05f9363749bf13b340 (diff) |
xwayland: Add glamor-egl backed GLX provider
Signed-off-by: Adam Jackson <ajax@redhat.com>
-rw-r--r-- | glamor/glamor_glx_provider.c | 353 | ||||
-rw-r--r-- | glamor/meson.build | 10 | ||||
-rw-r--r-- | hw/xwayland/meson.build | 3 | ||||
-rw-r--r-- | hw/xwayland/xwayland.c | 8 |
4 files changed, 372 insertions, 2 deletions
diff --git a/glamor/glamor_glx_provider.c b/glamor/glamor_glx_provider.c new file mode 100644 index 000000000..3fefe22a7 --- /dev/null +++ b/glamor/glamor_glx_provider.c @@ -0,0 +1,353 @@ +/* + * Copyright © 2017 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> + */ + +/* + * GLX on EGL + * + * TODO: + * + * - make pbuffers actually work + * - EXT_texture_from_pixmap + * - MESA_copy_sub_buffer + * - swap interval + * - ARB_create_context + */ + +#define MESA_EGL_NO_X11_HEADERS +#include <dix-config.h> +#include "glxserver.h" +#include <epoxy/egl.h> +#include "glxutil.h" + +/* Can't get these from <epoxy/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_TRUE_COLOR 0x8002 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 + +struct egl_config { + __GLXconfig base; + EGLConfig config; +}; + +struct egl_context { + __GLXcontext base; + EGLContext ctx; + + /* what this context previously thought was current */ + __GLXdrawable *draw; + __GLXdrawable *read; +}; + +struct egl_drawable { + __GLXdrawable base; + EGLSurface draw; +}; + +struct egl_screen { + __GLXscreen base; + EGLDisplay display; + EGLConfig *configs; +}; + +static void +egl_screen_destroy(__GLXscreen *screen) +{ +} + +static void +egl_destroy_context(__GLXcontext *ctx) +{ +} + +static int +egl_make_current(__GLXcontext *current) +{ + return TRUE; +} + +static int +egl_lose_current(__GLXcontext *current) +{ + return TRUE; +} + +static __GLXcontext * +egl_screen_create_context(__GLXscreen *_screen, __GLXconfig *_cfg, + __GLXcontext *_share, unsigned num_attribs, + const uint32_t *attribs, int *error) +{ + __GLXcontext *ctx; + + if (!(ctx = calloc(1, sizeof(__GLXcontext)))) { + *error = BadAlloc; + return NULL; + } + + ctx->destroy = egl_destroy_context; + ctx->makeCurrent = egl_make_current; + ctx->loseCurrent = egl_lose_current; + + return ctx; +} + +static void +egl_drawable_destroy(__GLXdrawable *_draw) +{ +} + +static GLboolean +egl_swap_buffers(ClientPtr client, __GLXdrawable *_draw) +{ + /* + * technically this can be hit for the stupid sgi compat case of + * SwapBuffers without a context, the assumption is that the + * server knows how to do it. and when you make an assumption, you + * make an ass out of u and mption. + */ + return FALSE; +} + +static __GLXdrawable * +egl_screen_create_drawable(ClientPtr client, __GLXscreen *gs, + DrawablePtr pDraw, XID drawId, int type, + XID glxDrawId, __GLXconfig *config) +{ + struct egl_drawable *draw = NULL; + + if (!(draw = calloc(1, sizeof *draw))) + return NULL; + + /* XXX probably need to do more, yeah? */ + + __glXDrawableInit(&draw->base, gs, pDraw, type, glxDrawId, config); + + draw->base.destroy = egl_drawable_destroy; + draw->base.swapBuffers = egl_swap_buffers; + /* copySubBuffer */ + + return &draw->base; +} + +static __GLXconfig * +egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen) +{ + int i, nconfigs; + struct egl_config *c, *configs = NULL; + EGLConfig *host_configs = NULL; + + eglGetConfigs(screen->display, NULL, 0, &nconfigs); + if (!(host_configs = calloc(nconfigs, sizeof *host_configs))) + goto bail; + + if (!(configs = calloc(nconfigs, sizeof *configs))) + goto bail; + + eglGetConfigs(screen->display, host_configs, nconfigs, &nconfigs); + + /* translate from EGL config attrib to GLX fbconfig attrib */ + for (i = 0; i < nconfigs; i++) { + EGLConfig hc = host_configs[i]; + EGLint value; + + /* XXX skip EGL_LUMINANCE_BUFFER? */ + + if (i > 0) + configs[i-1].base.next = &configs[i].base; + c = &configs[i]; + + /* constants. changing these requires (at least) new EGL extensions */ + c->base.doubleBufferMode = GL_TRUE; + c->base.stereoMode = GL_FALSE; + c->base.numAuxBuffers = 0; + c->base.level = 0; + c->base.transparentAlpha = 0; + c->base.transparentIndex = 0; + c->base.visualSelectGroup = 0; + c->base.indexBits = 0; + c->base.renderType = GLX_RGBA_BIT; + c->base.optimalPbufferWidth = 0; + c->base.optimalPbufferHeight = 0; + /* + * EGL has this as a property of context, in EGL_KHR_gl_colorspace. + * Let's just say we can't for now. + */ + c->base.sRGBCapable = 0; + + /* these are potentially variable, depending on the ddx */ + c->base.drawableType = GLX_WINDOW_BIT | + GLX_PIXMAP_BIT | + GLX_PBUFFER_BIT; + c->base.yInverted = 0; + c->base.visualType = GLX_TRUE_COLOR; + + /* + * 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 requres + * that an accum buffer _exist_, not a minimum bitness. + * + * future glx specs make accumulation buffers optional so yay. + */ + c->base.accumRedBits = 0; + c->base.accumGreenBits = 0; + c->base.accumBlueBits = 0; + c->base.accumAlphaBits = 0; + + /* stuff that directly translates */ +#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); + } + + /* + * These aren't really properties of the config, but of our + * implementation. Here I'm just hardcoding what's correct + * for Mesa. + */ +#if 0 + GET(EGL_BIND_TO_TEXTURE_RGB, bindToTextureRgb); + GET(EGL_BIND_TO_TEXTURE_RGBA, bindToTextureRgba); +#endif + c->base.bindToTextureRgb = GL_TRUE; + c->base.bindToTextureRgba = GL_TRUE; + c->base.bindToMipmapTexture = GL_FALSE; + c->base.bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT; +#undef GET + + /* derived state */ + 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; + /* XXX else scream */ + + // GET(GLX_CONFIG_CAVEAT, visualRating); + // GET(GLX_SWAP_METHOD_OML, swapMethod); + + /* map to the backend's config */ + c->config = hc; + + /* + * XXX do something less ugly. probably we should look at the + * existing visual and copy that. + */ + if (1) { + 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; + } + } + + screen->configs = host_configs; + return &configs->base; + +bail: + free(configs); + free(host_configs); + return NULL; +} + +static __GLXscreen * +egl_screen_probe(ScreenPtr pScreen) +{ + struct egl_screen *screen; + EGLDisplay dpy; + + if (!(screen = calloc(1, sizeof *screen))) + return NULL; + + screen->base.destroy = egl_screen_destroy; + screen->base.createContext = egl_screen_create_context; + screen->base.createDrawable = egl_screen_create_drawable; + /* screen->base.swapInterval = NULL; */ + + __glXInitExtensionEnableBits(screen->base.glx_enable_bits); + + dpy = screen->display = eglGetCurrentDisplay(); /* XXX */ + + screen->base.fbconfigs = egl_mirror_configs(pScreen, screen); + if (!screen->base.fbconfigs) { + free(screen); + return NULL; + } + + /* extension setup */ +#if 0 + if (epoxy_has_egl_extension(dpy, "EGL_KHR_create_context")) { + __glXEnableExtension(screen->glx_enable_bits, + "GLX_ARB_create_context"); + /* XXX check client APIs */ + __glXEnableExtension(screen->glx_enable_bits, + "GLX_ARB_create_context_profile"); + __glXEnableExtension(screen->glx_enable_bits, + "GLX_EXT_create_context_es_profile"); + __glXEnableExtension(screen->glx_enable_bits, + "GLX_EXT_create_context_es2_profile"); + } +#endif + + __glXScreenInit(&screen->base, pScreen); + + return &screen->base; +} + +__GLXprovider glamor_glx_provider = { + egl_screen_probe, + "EGL", + NULL +}; diff --git a/glamor/meson.build b/glamor/meson.build index 0b963275e..6699527df 100644 --- a/glamor/meson.build +++ b/glamor/meson.build @@ -47,6 +47,16 @@ glamor = static_library('glamor', ], ) +glamor_glx_provider = static_library('glamor_glx_provider', + 'glamor_glx_provider.c', + include_directories: [ inc, glx_inc ], + dependencies: [ + common_dep, + dependency('epoxy'), + ], + pic: true, +) + glamor_egl_stubs = static_library('glamor_egl_stubs', 'glamor_egl_stubs.c', include_directories: inc, diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build index d2791fe14..99256d852 100644 --- a/hw/xwayland/meson.build +++ b/hw/xwayland/meson.build @@ -50,7 +50,7 @@ endif executable( 'Xwayland', srcs, - include_directories: inc, + include_directories: [ inc, glx_inc ], dependencies: [ common_dep, xwayland_dep, @@ -58,6 +58,7 @@ executable( link_with: [ libxserver_main, xwayland_glamor, + glamor_glx_provider, libxserver_fb, libxserver, libxserver_xext_vidmode, diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 551443f93..fc2393245 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -36,6 +36,7 @@ #include <os.h> #include <xserver_poll.h> #include <propertyst.h> +#include "glxserver.h" #ifdef XF86VIDMODE #include <X11/extensions/xf86vmproto.h> @@ -1044,9 +1045,14 @@ InitOutput(ScreenInfo * screen_info, int argc, char **argv) screen_info->bitmapBitOrder = BITMAP_BIT_ORDER; screen_info->numPixmapFormats = ARRAY_SIZE(depths); - if (serverGeneration == 1) + if (serverGeneration == 1) { +#if defined(GLXEXT) && defined(GLAMOR) + extern __GLXprovider glamor_glx_provider; + GlxPushProvider(&glamor_glx_provider); +#endif LoadExtensionList(xwayland_extensions, ARRAY_SIZE(xwayland_extensions), FALSE); + } /* Cast away warning from missing printf annotation for * wl_log_func_t. Wayland 1.5 will have the annotation, so we can |