diff options
author | Dave Airlie <airlied@redhat.com> | 2013-12-17 11:33:24 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-12-17 11:33:24 +1000 |
commit | 829e3cc6da0ecc9ff48cf6c876166c4591b118fa (patch) | |
tree | 1e219ad781d1b606684fd2026d202481aded9ed9 | |
parent | 193c8e8f84f4a6e7b6536c7633bcaf1342297ae6 (diff) |
initial import
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | server_egl.c | 270 |
2 files changed, 283 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9dbc61a --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +CFLAGS=-g -Wall +LIBS=-lEGL -lGL -lgbm -lGLEW + +all: server_egl + + +server_egl.o: server_egl.c + +server_egl: server_egl.o + $(CC) $(CFLAGS) -o server_egl server_egl.o $(LIBS) + +clean: + rm -f server_egl server_egl.o diff --git a/server_egl.c b/server_egl.c new file mode 100644 index 0000000..1e315ae --- /dev/null +++ b/server_egl.c @@ -0,0 +1,270 @@ +#define EGL_EGLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dirent.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <GL/gl.h> +#include <GL/glext.h>/* display objects */ + +#include <errno.h> +#include <error.h> +#include <gbm.h> + +PFNGLGENTEXTURESEXTPROC my_glGenTextures; +PFNGLGENFRAMEBUFFERSPROC my_glGenFramebuffers; +GLuint tex_ids[4]; +GLuint fb_id; +struct rnode_display { + int fd; + struct gbm_device *gbm_dev; + EGLDisplay egl_display; + EGLConfig egl_conf; + EGLContext egl_ctx; +}; + +struct rnode_window { + struct gbm_surface *gbm_surface; + EGLSurface egl_surface; +}; + +struct window { + struct display *display; + int width, height; + struct rnode_window rnode; +}; + +struct display { + struct rnode_display rnode; +}; + +static int rnode_open(void) +{ + DIR *dir; + struct dirent *e; + int r, fd; + char *p; + + dir = opendir("/dev/dri/"); + if (!dir) + error(1, errno, "cannot open /dev/dri/"); + + 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) + error(1, errno, "cannot allocate pathname"); + + r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK); + if (r < 0){ + free(p); + error(0, errno, "cannot open %s", p); + continue; + } + fd = r; + fprintf(stderr, "using render node %s\n", p); + free(p); + break; + } + + if (fd < 0) + error(1, 0, "cannot open any render-node in /dev/dri"); + return fd; +} + +static void rnode_init(struct display *d) +{ + 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; + + d->rnode.fd = rnode_open(); + d->rnode.gbm_dev = gbm_create_device(d->rnode.fd); + if (!d->rnode.gbm_dev) + error(1, errno, "cannot create gbm device"); + + d->rnode.egl_display = eglGetDisplay((EGLNativeDisplayType)d->rnode.gbm_dev); + if (!d->rnode.egl_display) + error(1, errno, "cannot create EGL display"); + + b = eglInitialize(d->rnode.egl_display, &major, &minor); + if (!b) + error(1, errno, "Cannot initialise EGL"); + + fprintf(stderr, "EGL major/minor: %d.%d\n", major, minor); + fprintf(stderr, "EGL version: %s\n", + eglQueryString(d->rnode.egl_display, EGL_VERSION)); + fprintf(stderr, "EGL vendor: %s\n", + eglQueryString(d->rnode.egl_display, EGL_VENDOR)); + fprintf(stderr, "EGL extensions: %s\n", + eglQueryString(d->rnode.egl_display, EGL_EXTENSIONS)); + + api = EGL_OPENGL_API; + b = eglBindAPI(api); + if (!b) + error(1, errno, "cannot bind OpenGLES API"); + + b = eglChooseConfig(d->rnode.egl_display, conf_att, &d->rnode.egl_conf, + 1, &n); + + if (!b || n != 1) + error(1, errno, "cannot find suitable EGL config"); + + d->rnode.egl_ctx = eglCreateContext(d->rnode.egl_display, + d->rnode.egl_conf, + EGL_NO_CONTEXT, + ctx_att); + if (!d->rnode.egl_ctx) + error(1, errno, "cannot create EGL context"); + + eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); +} + +static void rnode_destroy(struct display *d) +{ + eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglDestroyContext(d->rnode.egl_display, d->rnode.egl_ctx); + eglTerminate(d->rnode.egl_display); + gbm_device_destroy(d->rnode.gbm_dev); + close(d->rnode.fd); +} + +static struct display *display_create(void) +{ + struct display *display = calloc(1, sizeof(*display)); + if (!display) + error(1, ENOMEM, "cannot allocate display"); + + rnode_init(display); + return display; +} + +static void display_destroy(struct display *display) +{ + rnode_destroy(display); + free(display); +} + +static void rnode_window_create(struct window *w) +{ + struct display *d = w->display; + EGLBoolean b; + + w->rnode.gbm_surface = gbm_surface_create(d->rnode.gbm_dev, + w->width, w->height, + GBM_FORMAT_XRGB8888, + GBM_BO_USE_RENDERING); + if (!w->rnode.gbm_surface) + error(1, errno, "cannot create gbm surface"); + + w->rnode.egl_surface = eglCreateWindowSurface(d->rnode.egl_display, + d->rnode.egl_conf, + (EGLNativeWindowType)w->rnode.gbm_surface, NULL); + if (!w->rnode.egl_surface) + error(1, errno, "Cannot create EGL surface"); + + b = eglMakeCurrent(d->rnode.egl_display, + w->rnode.egl_surface, + w->rnode.egl_surface, + d->rnode.egl_ctx); + if (!b) + error(1, errno, "Cannot activate EGL context"); +} + +static void rnode_window_destroy(struct window *w) +{ + struct display *d = w->display; + + eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglDestroySurface(d->rnode.egl_display, w->rnode.egl_surface); + gbm_surface_destroy(w->rnode.gbm_surface); +} + +static struct window *window_create(struct display *display) +{ + struct window *window = calloc(1, sizeof(*window)); + if (!window) + error(1, errno, "cannot allocate window"); + + window->display = display; + window->width = 100; + window->height = 100; + + rnode_window_create(window); + return window; +} + +static void window_destroy(struct window *window) +{ + rnode_window_destroy(window); + free(window); +} + +static void init_fns(void) +{ + my_glGenTextures = (void *)eglGetProcAddress("glGenTextures"); + my_glGenFramebuffers = (void *)eglGetProcAddress("glGenFramebuffers"); +} + +int main(void) +{ + EGLImageKHR image; + struct display *display; + struct window *window; + + display = display_create(); + window = window_create(display); + init_fns(); + + /* create some textures */ + (*my_glGenTextures)(4, &tex_ids[0]); + + glBindTexture(GL_TEXTURE_2D, tex_ids[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 480, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + (*my_glGenFramebuffers)(1, &fb_id); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex_ids[0], 0); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_id); + + glClearColor(1.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* create an EGL image from that texture */ + image = eglCreateImageKHR(display->rnode.egl_display, display->rnode.egl_ctx, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(unsigned long)tex_ids[0], NULL); + + fprintf(stderr,"got image %p\n", image); + eglDestroyImageKHR(display->rnode.egl_display, image); + + window_destroy(window); + display_destroy(display); + return 0; +} |