[virglrenderer-devel] [PATCH 1/4] Add a GLX backend

marcandre.lureau at redhat.com marcandre.lureau at redhat.com
Fri Jun 10 17:25:00 UTC 2016


From: Marc-André Lureau <marcandre.lureau at redhat.com>

apitrace & epoxy with EGL don't work nicely together, using glx works
around this issue for now (disabled by default).

Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
---
 configure.ac            |  22 ++++++++++
 src/Makefile.am         |  10 ++++-
 src/virgl_glx.h         |  38 +++++++++++++++++
 src/virgl_glx_context.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/virglrenderer.c     |  57 +++++++++++++++++++++----
 src/virglrenderer.h     |   1 +
 6 files changed, 228 insertions(+), 9 deletions(-)
 create mode 100644 src/virgl_glx.h
 create mode 100644 src/virgl_glx_context.c

diff --git a/configure.ac b/configure.ac
index 3f25f06..1256eb9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,13 @@ fi
 
 PKG_CHECK_MODULES([EPOXY], [epoxy])
 
+AC_ARG_WITH([glx], AS_HELP_STRING([--with-glx], [Build with the x11/glx backend]))
+AS_IF([test "x$with_glx" = "xyes"], [
+  PKG_CHECK_MODULES([X11], [x11])
+  AC_CHECK_HEADER([epoxy/glx.h])
+])
+AM_CONDITIONAL([WITH_GLX], [test "x$with_glx" = "xyes"])
+
 AC_SUBST([DEFINES])
 AC_CONFIG_FILES([
 		virglrenderer.pc
@@ -112,3 +119,18 @@ AC_CONFIG_FILES([
 		tests/Makefile
 ])
 AC_OUTPUT
+
+AC_MSG_NOTICE([
+
+      virgl $VERSION
+      ==============
+
+      prefix:                   $prefix
+      c compiler:               $CC
+      win32:                    $os_win32
+
+      glx:                      $with_glx
+      debug:                    $enable_debug
+      tests:                    $build_tests
+
+])
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b564f2..3ec8358 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,6 +2,7 @@ SUBDIRS := gallium/auxiliary
 AM_LDFLAGS = -lm \
 	$(GBM_LIBS) \
 	$(EPOXY_LIBS) \
+	$(X11_LIBS) \
 	$(CODE_COVERAGE_LDFLAGS)
 
 AM_CFLAGS = \
@@ -12,6 +13,7 @@ AM_CFLAGS = \
 	$(LIBDRM_CFLAGS) \
 	$(GBM_CFLAGS) \
 	$(EPOXY_CFLAGS) \
+	$(X11_CFLAGS) \
 	$(VISIBILITY_CFLAGS) \
 	$(CODE_COVERAGE_CFLAGS)
 
@@ -37,6 +39,12 @@ libvrend_la_SOURCES += \
         virgl_egl_context.c
 endif
 
+if WITH_GLX
+libvrend_la_SOURCES += \
+	virgl_glx.h \
+	virgl_glx_context.c
+endif
+
 lib_LTLIBRARIES = libvirglrenderer.la
 noinst_LTLIBRARIES = libvrend.la
 
@@ -45,7 +53,7 @@ GM_LDFLAGS = -Wl,-Bsymbolic -version-number 0:2 -no-undefined
 libvirglrenderer_la_SOURCES = virglrenderer.c
 libvirglrenderer_ladir = $(libdir)
 libvirglrenderer_la_LIBADD = libvrend.la gallium/auxiliary/libgallium.la
-libvirglrenderer_la_LDFLAGS = $(GM_LDFLAGS) $(EPOXY_LDFLAGS)
+libvirglrenderer_la_LDFLAGS = $(GM_LDFLAGS) $(EPOXY_LDFLAGS) $(X11_LDFLAGS)
 
 libvirglrendererincludedir = ${includedir}/virgl
 libvirglrendererinclude_HEADERS = virglrenderer.h
diff --git a/src/virgl_glx.h b/src/virgl_glx.h
new file mode 100644
index 0000000..50c0bdd
--- /dev/null
+++ b/src/virgl_glx.h
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2016 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 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.
+ *
+ **************************************************************************/
+#ifndef VIRGL_GLX_H
+#define VIRGL_GLX_H
+
+#include "vrend_renderer.h"
+struct virgl_glx;
+
+struct virgl_glx *virgl_glx_init(void);
+void virgl_glx_destroy(struct virgl_glx *ve);
+
+virgl_renderer_gl_context virgl_glx_create_context(struct virgl_glx *ve, struct virgl_gl_ctx_param *vparams);
+void virgl_glx_destroy_context(struct virgl_glx *ve, virgl_renderer_gl_context virglctx);
+int virgl_glx_make_context_current(struct virgl_glx *ve, virgl_renderer_gl_context virglctx);
+virgl_renderer_gl_context virgl_glx_get_current_context(struct virgl_glx *ve);
+
+#endif
diff --git a/src/virgl_glx_context.c b/src/virgl_glx_context.c
new file mode 100644
index 0000000..4bc98dc
--- /dev/null
+++ b/src/virgl_glx_context.c
@@ -0,0 +1,109 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2016 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 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.
+ *
+ **************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <epoxy/glx.h>
+#include "virglrenderer.h"
+#include "virgl_glx.h"
+
+struct virgl_glx {
+   Display *display;
+   GLXFBConfig* fbConfigs;
+   GLXPbuffer pbuffer;
+};
+
+struct virgl_glx *virgl_glx_init(void)
+{
+   struct virgl_glx *d;
+
+   d = malloc(sizeof(struct virgl_glx));
+   if (!d)
+      return NULL;
+
+   d->display = XOpenDisplay(NULL);
+
+   if (!d->display) {
+      free(d);
+      return NULL;
+   }
+
+   int visualAttribs[] = { None };
+   int numberOfFramebufferConfigurations = 0;
+
+   d->fbConfigs = glXChooseFBConfig(d->display, DefaultScreen(d->display),
+                                    visualAttribs, &numberOfFramebufferConfigurations);
+
+   int pbufferAttribs[] = {
+      GLX_PBUFFER_WIDTH,  32,
+      GLX_PBUFFER_HEIGHT, 32,
+      None
+   };
+   d->pbuffer = glXCreatePbuffer(d->display, d->fbConfigs[0], pbufferAttribs);
+
+   return d;
+}
+
+void virgl_glx_destroy(struct virgl_glx *d)
+{
+   XFree(d->fbConfigs);
+   glXDestroyPbuffer(d->display,d->pbuffer);
+   XCloseDisplay(d->display);
+   free(d);
+}
+
+virgl_renderer_gl_context virgl_glx_create_context(struct virgl_glx *d, struct virgl_gl_ctx_param *vparams)
+{
+   int context_attribs[] = {
+      GLX_CONTEXT_MAJOR_VERSION_ARB, vparams->major_ver,
+      GLX_CONTEXT_MINOR_VERSION_ARB, vparams->minor_ver,
+      None
+   };
+
+   GLXContext ctx =
+      glXCreateContextAttribsARB(d->display, d->fbConfigs[0],
+                                 vparams->shared ? glXGetCurrentContext() : NULL,
+                                 True, context_attribs);
+   return (virgl_renderer_gl_context)ctx;
+}
+
+void virgl_glx_destroy_context(struct virgl_glx *d, virgl_renderer_gl_context virglctx)
+{
+   GLXContext ctx = (GLXContext)virglctx;
+
+   glXDestroyContext(d->display,ctx);
+}
+
+int virgl_glx_make_context_current(struct virgl_glx *d, virgl_renderer_gl_context virglctx)
+{
+   return glXMakeContextCurrent(d->display, d->pbuffer, d->pbuffer, virglctx);
+}
+
+virgl_renderer_gl_context virgl_glx_get_current_context(struct virgl_glx *d)
+{
+   return glXGetCurrentContext();
+}
diff --git a/src/virglrenderer.c b/src/virglrenderer.c
index 2801c7f..c89cb60 100644
--- a/src/virglrenderer.c
+++ b/src/virglrenderer.c
@@ -41,9 +41,21 @@
 #ifdef HAVE_EPOXY_EGL_H
 #include "virgl_egl.h"
 static struct virgl_egl *egl_info;
-static int use_egl_context;
 #endif
 
+#ifdef HAVE_EPOXY_GLX_H
+#include "virgl_glx.h"
+static struct virgl_glx *glx_info;
+#endif
+
+enum {
+   CONTEXT_NONE,
+   CONTEXT_EGL,
+   CONTEXT_GLX
+};
+
+static int use_context = CONTEXT_NONE;
+
 /* new API - just wrap internal API for now */
 
 int virgl_renderer_resource_create(struct virgl_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs)
@@ -163,7 +175,7 @@ int virgl_renderer_resource_get_info(int res_handle,
    int ret;
    ret = vrend_renderer_resource_get_info(res_handle, (struct vrend_renderer_resource_info *)info);
 #ifdef HAVE_EPOXY_EGL_H
-   if (ret == 0 && use_egl_context)
+   if (ret == 0 && use_context == CONTEXT_EGL)
       return virgl_egl_get_fourcc_for_texture(egl_info, info->tex_id, info->virgl_format, &info->drm_fourcc);
 #endif
 
@@ -199,9 +211,13 @@ static virgl_renderer_gl_context create_gl_context(int scanout_idx, struct virgl
    struct virgl_renderer_gl_ctx_param vparam;
 
 #ifdef HAVE_EPOXY_EGL_H
-   if (use_egl_context)
+   if (use_context == CONTEXT_EGL)
       return virgl_egl_create_context(egl_info, param);
 #endif
+#ifdef HAVE_EPOXY_GLX_H
+   if (use_context == CONTEXT_GLX)
+      return virgl_glx_create_context(glx_info, param);
+#endif
    vparam.version = 1;
    vparam.shared = param->shared;
    vparam.major_ver = param->major_ver;
@@ -212,18 +228,26 @@ static virgl_renderer_gl_context create_gl_context(int scanout_idx, struct virgl
 static void destroy_gl_context(virgl_renderer_gl_context ctx)
 {
 #ifdef HAVE_EPOXY_EGL_H
-   if (use_egl_context)
+   if (use_context == CONTEXT_EGL)
       return virgl_egl_destroy_context(egl_info, ctx);
 #endif
+#ifdef HAVE_EPOXY_GLX_H
+   if (use_context == CONTEXT_GLX)
+      return virgl_glx_destroy_context(glx_info, ctx);
+#endif
    return rcbs->destroy_gl_context(dev_cookie, ctx);
 }
 
 static int make_current(int scanout_idx, virgl_renderer_gl_context ctx)
 {
 #ifdef HAVE_EPOXY_EGL_H
-   if (use_egl_context)
+   if (use_context == CONTEXT_EGL)
       return virgl_egl_make_context_current(egl_info, ctx);
 #endif
+#ifdef HAVE_EPOXY_GLX_H
+   if (use_context == CONTEXT_GLX)
+      return virgl_glx_make_context_current(glx_info, ctx);
+#endif
    return rcbs->make_current(dev_cookie, scanout_idx, ctx);
 }
 
@@ -249,10 +273,17 @@ void virgl_renderer_cleanup(void *cookie)
 {
    vrend_renderer_fini();
 #ifdef HAVE_EPOXY_EGL_H
-   if (use_egl_context) {
+   if (use_context == CONTEXT_EGL) {
       virgl_egl_destroy(egl_info);
       egl_info = NULL;
-      use_egl_context = 0;
+      use_context = CONTEXT_NONE;
+   }
+#endif
+#ifdef HAVE_EPOXY_GLX_H
+   if (use_context == CONTEXT_GLX) {
+      virgl_glx_destroy(glx_info);
+      glx_info = NULL;
+      use_context = CONTEXT_NONE;
    }
 #endif
 }
@@ -274,11 +305,21 @@ int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks
       egl_info = virgl_egl_init();
       if (!egl_info)
          return -1;
-      use_egl_context = 1;
+      use_context = CONTEXT_EGL;
 #else
       fprintf(stderr, "EGL is not supported on this platform\n");
       return -1;
 #endif
+   } else if (flags & VIRGL_RENDERER_USE_GLX) {
+#ifdef HAVE_EPOXY_GLX_H
+      glx_info = virgl_glx_init();
+      if (!glx_info)
+         return -1;
+      use_context = CONTEXT_GLX;
+#else
+      fprintf(stderr, "GLX is not supported on this platform\n");
+      return -1;
+#endif
    }
 
    if (flags & VIRGL_RENDERER_THREAD_SYNC)
diff --git a/src/virglrenderer.h b/src/virglrenderer.h
index c6dc055..6eb7bdb 100644
--- a/src/virglrenderer.h
+++ b/src/virglrenderer.h
@@ -61,6 +61,7 @@ struct virgl_renderer_callbacks {
  * need to use virgl_renderer_get_poll_fd to know if this feature is in effect.
  */
 #define VIRGL_RENDERER_THREAD_SYNC 2
+#define VIRGL_RENDERER_USE_GLX (1 << 2)
 
 VIRGL_EXPORT int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cb);
 VIRGL_EXPORT void virgl_renderer_poll(void); /* force fences */
-- 
2.7.4



More information about the virglrenderer-devel mailing list