summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-03-04 13:00:15 +1000
committerDave Airlie <airlied@redhat.com>2014-03-04 13:00:15 +1000
commit5c0a57ee7b793dd21f38770c49cac50665e0ccc6 (patch)
tree469382e771a70857c6cf880b963c9f6331c76af5
parent599782b545167e77eb8b6716ab1ccf239e36ecc9 (diff)
virgl_egl: start adding initial rendernode/egl code
-rw-r--r--src/gallium/renderer/Makefile.am3
-rw-r--r--src/gallium/renderer/graw_virtio_lib_renderer.c13
-rw-r--r--src/gallium/renderer/virgl_egl.h14
-rw-r--r--src/gallium/renderer/virgl_egl_context.c180
4 files changed, 207 insertions, 3 deletions
diff --git a/src/gallium/renderer/Makefile.am b/src/gallium/renderer/Makefile.am
index 0a64becd4b3..afc58e73a56 100644
--- a/src/gallium/renderer/Makefile.am
+++ b/src/gallium/renderer/Makefile.am
@@ -31,7 +31,8 @@ libgrend_la_SOURCES = \
graw_cursor.c \
graw_formats.c \
iov.c \
- graw_renderer_helper.c
+ graw_renderer_helper.c \
+ virgl_egl_context.c
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = virglrenderer.pc
diff --git a/src/gallium/renderer/graw_virtio_lib_renderer.c b/src/gallium/renderer/graw_virtio_lib_renderer.c
index 5720d5e33fb..2cc143eceac 100644
--- a/src/gallium/renderer/graw_virtio_lib_renderer.c
+++ b/src/gallium/renderer/graw_virtio_lib_renderer.c
@@ -20,11 +20,14 @@
#include "graw_renderer.h"
#include "virglrenderer.h"
+#include "virgl_egl.h"
+
static struct virgl_renderer_callbacks *rcbs;
static void *dev_cookie;
extern int localrender;
-
+extern int use_egl_context;
+struct virgl_egl *egl_info;
static struct grend_if_cbs virgl_cbs;
static int graw_process_cmd(struct virtgpu_command *cmd, struct virgl_iovec *iov,
@@ -321,16 +324,22 @@ static void virgl_write_fence(uint32_t fence_id)
static virgl_gl_context create_gl_context(int scanout_idx)
{
- return rcbs->create_gl_context(dev_cookie, scanout_idx);
+ if (use_egl_context)
+ return virgl_egl_create_context(egl_info);
+ return rcbs->create_gl_context(dev_cookie, scanout_idx);
}
static void destroy_gl_context(virgl_gl_context ctx)
{
+ if (use_egl_context)
+ return virgl_egl_destroy_context(egl_info, ctx);
return rcbs->destroy_gl_context(dev_cookie, ctx);
}
static int make_current(int scanout_idx, virgl_gl_context ctx)
{
+ if (use_egl_context)
+ return virgl_egl_make_context_current(egl_info, ctx);
return rcbs->make_current(dev_cookie, scanout_idx, ctx);
}
diff --git a/src/gallium/renderer/virgl_egl.h b/src/gallium/renderer/virgl_egl.h
new file mode 100644
index 00000000000..048ae122754
--- /dev/null
+++ b/src/gallium/renderer/virgl_egl.h
@@ -0,0 +1,14 @@
+#ifndef VIRGL_EGL_H
+#define VIRGL_EGL_H
+
+struct virgl_egl;
+
+struct virgl_egl *virgl_egl_init(void);
+void virgl_egl_destroy(struct virgl_egl *ve);
+
+virgl_gl_context virgl_egl_create_context(struct virgl_egl *ve);
+void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_gl_context virglctx);
+int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglctx);
+virgl_gl_context virgl_egl_get_current_context(struct virgl_egl *ve);
+
+#endif
diff --git a/src/gallium/renderer/virgl_egl_context.c b/src/gallium/renderer/virgl_egl_context.c
new file mode 100644
index 00000000000..f604800111e
--- /dev/null
+++ b/src/gallium/renderer/virgl_egl_context.c
@@ -0,0 +1,180 @@
+/* create our own EGL offscreen rendering context via gbm and rendernodes */
+
+/* if we are using EGL and rendernodes then we talk via file descriptors to the remote
+ node */
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <gbm.h>
+
+#include "virglrenderer.h"
+#include "virgl_egl.h"
+
+struct virgl_egl {
+ int fd;
+ struct gbm_device *gbm_dev;
+ EGLDisplay egl_display;
+ EGLConfig egl_conf;
+ EGLContext egl_ctx;
+};
+
+static int egl_rendernode_open(void)
+{
+ DIR *dir;
+ struct dirent *e;
+ int r, fd;
+ char *p;
+ dir = opendir("/dev/dri");
+ if (!dir)
+ return -1;
+
+ fd = -1;
+ while ((e = readdir(dir))) {
+ if (e->d_type != DT_CHR)
+ continue;
+
+ if (strncmp(e->d_name, "renderD", 7))
+ continue;
+
+ r = asprintf(&p, "/dev/dri/%s", e->d_name);
+ if (r < 0)
+ return -1;
+
+ r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
+ if (r < 0){
+ free(p);
+ continue;
+ }
+ fd = r;
+ fprintf(stderr, "using render node %s\n", p);
+ free(p);
+ break;
+ }
+
+ if (fd < 0)
+ return -1;
+ return fd;
+}
+
+struct virgl_egl *virgl_egl_init(void)
+{
+ static const EGLint conf_att[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, 0,
+ EGL_NONE,
+ };
+ static const EGLint ctx_att[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+ EGLBoolean b;
+ EGLenum api;
+ EGLint major, minor, n;
+ struct virgl_egl *d;
+
+ d = malloc(sizeof(struct virgl_egl));
+ if (!d)
+ return NULL;
+
+ d->fd = egl_rendernode_open();
+ d->gbm_dev = gbm_create_device(d->fd);
+ if (!d->gbm_dev)
+ goto fail;
+
+ d->egl_display = eglGetDisplay((EGLNativeDisplayType)d->gbm_dev);
+ if (!d->egl_display)
+ goto fail;
+
+ b = eglInitialize(d->egl_display, &major, &minor);
+ if (!b)
+ goto fail;
+
+ fprintf(stderr, "EGL major/minor: %d.%d\n", major, minor);
+ fprintf(stderr, "EGL version: %s\n",
+ eglQueryString(d->egl_display, EGL_VERSION));
+ fprintf(stderr, "EGL vendor: %s\n",
+ eglQueryString(d->egl_display, EGL_VENDOR));
+ fprintf(stderr, "EGL extensions: %s\n",
+ eglQueryString(d->egl_display, EGL_EXTENSIONS));
+
+ api = EGL_OPENGL_API;
+ b = eglBindAPI(api);
+ if (!b)
+ goto fail;
+
+ b = eglChooseConfig(d->egl_display, conf_att, &d->egl_conf,
+ 1, &n);
+
+ if (!b || n != 1)
+ goto fail;
+
+ d->egl_ctx = eglCreateContext(d->egl_display,
+ d->egl_conf,
+ EGL_NO_CONTEXT,
+ ctx_att);
+ if (!d->egl_ctx)
+ goto fail;
+
+
+ eglMakeCurrent(d->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ d->egl_ctx);
+ return d;
+ fail:
+ free(d);
+ return NULL;
+}
+
+void virgl_egl_destroy(struct virgl_egl *d)
+{
+ eglMakeCurrent(d->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglDestroyContext(d->egl_display, d->egl_ctx);
+ eglTerminate(d->egl_display);
+ gbm_device_destroy(d->gbm_dev);
+ close(d->fd);
+ free(d);
+}
+
+virgl_gl_context virgl_egl_create_context(struct virgl_egl *ve)
+{
+ EGLContext eglctx;
+ static const EGLint ctx_att[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+ eglctx = eglCreateContext(ve->egl_display,
+ ve->egl_conf,
+ EGL_NO_CONTEXT,
+ ctx_att);
+ return (virgl_gl_context)eglctx;
+}
+
+void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_gl_context virglctx)
+{
+ EGLContext eglctx = (EGLContext)virglctx;
+ eglDestroyContext(ve->egl_display, eglctx);
+}
+
+int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglctx)
+{
+ EGLContext eglctx = (EGLContext)virglctx;
+
+ return eglMakeCurrent(ve->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ eglctx);
+}
+
+virgl_gl_context virgl_egl_get_current_context(struct virgl_egl *ve)
+{
+ EGLContext eglctx = eglGetCurrentContext();
+ return (virgl_gl_context)eglctx;
+}