diff options
author | Dave Airlie <airlied@redhat.com> | 2014-03-04 13:00:15 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-03-04 13:00:15 +1000 |
commit | 5c0a57ee7b793dd21f38770c49cac50665e0ccc6 (patch) | |
tree | 469382e771a70857c6cf880b963c9f6331c76af5 | |
parent | 599782b545167e77eb8b6716ab1ccf239e36ecc9 (diff) |
virgl_egl: start adding initial rendernode/egl code
-rw-r--r-- | src/gallium/renderer/Makefile.am | 3 | ||||
-rw-r--r-- | src/gallium/renderer/graw_virtio_lib_renderer.c | 13 | ||||
-rw-r--r-- | src/gallium/renderer/virgl_egl.h | 14 | ||||
-rw-r--r-- | src/gallium/renderer/virgl_egl_context.c | 180 |
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; +} |