diff options
-rw-r--r-- | progs/egl/segl/Makefile | 21 | ||||
-rw-r--r-- | progs/egl/segl/segl.c | 167 | ||||
-rw-r--r-- | progs/egl/segl/segl.h | 60 | ||||
-rw-r--r-- | progs/egl/segl/segl_kms.c | 59 | ||||
-rw-r--r-- | progs/egl/segl/segl_x11.c | 117 |
5 files changed, 424 insertions, 0 deletions
diff --git a/progs/egl/segl/Makefile b/progs/egl/segl/Makefile new file mode 100644 index 0000000000..c5f13f69c1 --- /dev/null +++ b/progs/egl/segl/Makefile @@ -0,0 +1,21 @@ +# progs/egl/segl/Makefile + +TOP = ../../.. +include $(TOP)/configs/current + +SEGL_LIBS := $(foreach dpy, $(EGL_DISPLAYS), libsegl-$(dpy).a) + +all: $(SEGL_LIBS) + +x11_OBJECTS := segl.o segl_x11.o +kms_OBJECTS := segl.o segl_kms.o + +libsegl-x11.a: $(x11_OBJECTS) + $(MKLIB) -o segl-x11 -static $(x11_OBJECTS) + +libsegl-kms.a: $(kms_OBJECTS) + $(MKLIB) -o segl-kms -static $(kms_OBJECTS) + +clean: + rm -f $(sort $(x11_OBJECTS) $(kms_OBJECTS)) + rm -f $(SEGL_LIBS) diff --git a/progs/egl/segl/segl.c b/progs/egl/segl/segl.c new file mode 100644 index 0000000000..b1df71a5b5 --- /dev/null +++ b/progs/egl/segl/segl.c @@ -0,0 +1,167 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <EGL/egl.h> + +#include "segl.h" + +static void +segl_log(struct segl *segl, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + if (segl->winsys->vlog) + segl->winsys->vlog(segl->winsys, format, ap); + else + vfprintf(stdout, format, ap); + + va_end(ap); +} + +static EGLBoolean +segl_init_egl(struct segl *segl, const EGLint *attribs) +{ + EGLint num_conf; + + segl->dpy = eglGetDisplay(segl->winsys->dpy); + if (!segl->dpy) + return EGL_FALSE; + + if (!eglInitialize(segl->dpy, &segl->major, &segl->minor)) + return EGL_FALSE; + + if (segl->verbose) { + const char *ver = eglQueryString(segl->dpy, EGL_VERSION); + segl_log(segl, "EGL_VERSION = %s\n", ver); + } + + if (!eglChooseConfig(segl->dpy, attribs, &segl->conf, 1, &num_conf) || + !num_conf) { + segl_log(segl, "failed to choose a config\n"); + eglTerminate(segl->dpy); + return EGL_FALSE; + } + + return EGL_TRUE; +} + +struct segl * +segl_new(struct segl_winsys *winsys, const EGLint *attribs) +{ + struct segl *segl; + + segl = calloc(1, sizeof(*segl)); + if (segl) { + segl->verbose = EGL_TRUE; + segl->winsys = winsys; + + if (!segl_init_egl(segl, attribs)) { + free(segl); + return NULL; + } + } + + return segl; +} + +void +segl_destroy(struct segl *segl) +{ + free(segl); +} + +EGLBoolean +segl_create_window(struct segl *segl, const char *name, + EGLint width, EGLint height, const EGLint *attribs, + EGLNativeWindowType *win_ret, EGLSurface *surf_ret) +{ + EGLNativeWindowType win; + EGLSurface surf; + EGLint visual; + + if (!win_ret) { + if (surf_ret) + *surf_ret = EGL_NO_SURFACE; + return EGL_TRUE; + } + + if (!eglGetConfigAttrib(segl->dpy, segl->conf, EGL_NATIVE_VISUAL_ID, &visual)) + return EGL_FALSE; + + win = segl->winsys->create_window(segl->winsys, + name, width, height, visual); + if (surf_ret) { + surf = eglCreateWindowSurface(segl->dpy, segl->conf, win, attribs); + if (!surf) { + segl_log(segl, "failed to create a window surface\n"); + segl->winsys->destroy_window(segl->winsys, win); + return EGL_FALSE; + } + + *surf_ret = surf; + } + + *win_ret = win; + + return EGL_TRUE; +} + +EGLBoolean +segl_create_pixmap(struct segl *segl, + EGLint width, EGLint height, const EGLint *attribs, + EGLNativePixmapType *pix_ret, EGLSurface *surf_ret) +{ + EGLNativePixmapType pix; + EGLSurface surf; + EGLint depth; + + if (!pix_ret) { + if (surf_ret) + *surf_ret = EGL_NO_SURFACE; + return EGL_TRUE; + } + + if (!eglGetConfigAttrib(segl->dpy, segl->conf, EGL_BUFFER_SIZE, &depth)) + return EGL_FALSE; + + pix = segl->winsys->create_pixmap(segl->winsys, width, height, depth); + if (surf_ret) { + surf = eglCreatePixmapSurface(segl->dpy, segl->conf, pix, attribs); + if (!surf) { + segl_log(segl, "failed to create a pixmap surface\n"); + segl->winsys->destroy_pixmap(segl->winsys, pix); + return EGL_FALSE; + } + + *surf_ret = surf; + } + + *pix_ret = pix; + + return EGL_TRUE; +} + +void +segl_benchmark(struct segl *segl, double seconds, + void (*draw_frame)(void *), void *draw_data) +{ + double begin, end, last_frame, duration; + EGLint num_frames = 0; + + begin = segl->winsys->now(segl->winsys); + end = begin + seconds; + + last_frame = begin; + while (last_frame < end) { + draw_frame(draw_data); + last_frame = segl->winsys->now(segl->winsys); + num_frames++; + } + + duration = last_frame - begin; + segl_log(segl, "%d frames in %3.1f seconds = %6.3f FPS\n", + num_frames, duration, (double) num_frames / duration); +} diff --git a/progs/egl/segl/segl.h b/progs/egl/segl/segl.h new file mode 100644 index 0000000000..20faf6ef02 --- /dev/null +++ b/progs/egl/segl/segl.h @@ -0,0 +1,60 @@ +#ifndef _SEGL_H_ +#define _SEGL_H_ + +#include <stdarg.h> +#include <EGL/egl.h> + +struct segl_winsys { + EGLNativeDisplayType dpy; + + EGLNativeWindowType (*create_window)(struct segl_winsys *winsys, + const char *name, + EGLint width, EGLint height, + EGLint visual); + void (*destroy_window)(struct segl_winsys *winsys, EGLNativeWindowType win); + + EGLNativePixmapType (*create_pixmap)(struct segl_winsys *winsys, + EGLint width, EGLint height, + EGLint depth); + void (*destroy_pixmap)(struct segl_winsys *winsys, EGLNativePixmapType pix); + + /* get current time in seconds */ + double (*now)(struct segl_winsys *winsys); + /* log a message. OPTIONAL */ + void (*vlog)(struct segl_winsys *winsys, const char *format, va_list ap); +}; + +struct segl { + EGLBoolean verbose; + + struct segl_winsys *winsys; + + EGLint major, minor; + EGLDisplay dpy; + EGLConfig conf; +}; + +struct segl_winsys * +segl_get_winsys(EGLNativeDisplayType dpy); + +struct segl * +segl_new(struct segl_winsys *winsys, const EGLint *attribs); + +void +segl_destroy(struct segl *segl); + +EGLBoolean +segl_create_window(struct segl *segl, const char *name, + EGLint width, EGLint height, const EGLint *attribs, + EGLNativeWindowType *win_ret, EGLSurface *surf_ret); + +EGLBoolean +segl_create_pixmap(struct segl *segl, + EGLint width, EGLint height, const EGLint *attribs, + EGLNativePixmapType *pix_ret, EGLSurface *surf_ret); + +void +segl_benchmark(struct segl *segl, double seconds, + void (*draw_frame)(void *), void *draw_data); + +#endif /* _SEGL_H_ */ diff --git a/progs/egl/segl/segl_kms.c b/progs/egl/segl/segl_kms.c new file mode 100644 index 0000000000..bb4fcfca65 --- /dev/null +++ b/progs/egl/segl/segl_kms.c @@ -0,0 +1,59 @@ +#include <stdlib.h> +#include <sys/time.h> + +#include "segl.h" + +static EGLNativeWindowType +kms_create_window(struct segl_winsys *winsys, const char *name, + EGLint width, EGLint height, EGLint visual) +{ + return 0; +} + +static void +kms_destroy_window(struct segl_winsys *winsys, EGLNativeWindowType win) +{ +} + + +static EGLNativePixmapType +kms_create_pixmap(struct segl_winsys *winsys, EGLint width, EGLint height, + EGLint depth) +{ + return 0; +} + +static void +kms_destroy_pixmap(struct segl_winsys *winsys, EGLNativePixmapType pix) +{ +} + +static double +kms_now(struct segl_winsys *winsys) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return (double) tv.tv_sec + tv.tv_usec / 1000000.0; +} + +struct segl_winsys * +segl_get_winsys(EGLNativeDisplayType dpy) +{ + struct segl_winsys *winsys; + + winsys = calloc(1, sizeof(*winsys)); + if (winsys) { + winsys->dpy = dpy; + + winsys->create_window = kms_create_window; + winsys->destroy_window = kms_destroy_window; + winsys->create_pixmap = kms_create_pixmap; + winsys->destroy_pixmap = kms_destroy_pixmap; + + winsys->now = kms_now; + } + + return winsys; +} diff --git a/progs/egl/segl/segl_x11.c b/progs/egl/segl/segl_x11.c new file mode 100644 index 0000000000..7b26917460 --- /dev/null +++ b/progs/egl/segl/segl_x11.c @@ -0,0 +1,117 @@ +#include <stdlib.h> +#include <sys/time.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "segl.h" + +static Window +x11_create_window(struct segl_winsys *winsys, const char *name, + EGLint width, EGLint height, EGLint visual) +{ + XVisualInfo vinfo_template, *vinfo = NULL; + EGLint val, num_vinfo; + Window root, win; + XSetWindowAttributes attrs; + unsigned long mask; + EGLint x = 0, y = 0; + + vinfo_template.visualid = (VisualID) val; + vinfo = XGetVisualInfo(winsys->dpy, VisualIDMask, &vinfo_template, &num_vinfo); + if (!num_vinfo) { + if (vinfo) + XFree(vinfo); + return None; + } + + root = DefaultRootWindow(winsys->dpy); + + /* window attributes */ + attrs.background_pixel = 0; + attrs.border_pixel = 0; + attrs.colormap = XCreateColormap(winsys->dpy, root, vinfo->visual, AllocNone); + attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + attrs.override_redirect = False; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; + + win = XCreateWindow(winsys->dpy, root, x, y, width, height, 0, + vinfo->depth, InputOutput, vinfo->visual, mask, &attrs); + XFree(vinfo); + + if (!win) + return None; + + /* set hints and properties */ + { + XSizeHints sizehints; + sizehints.x = x; + sizehints.y = y; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + XSetNormalHints(winsys->dpy, win, &sizehints); + XSetStandardProperties(winsys->dpy, win, name, name, + None, (char **)NULL, 0, &sizehints); + } + + XMapWindow(winsys->dpy, win); + + return win; +} + +static void +x11_destroy_window(struct segl_winsys *winsys, Window win) +{ + if (win) + XDestroyWindow(winsys->dpy, win); +} + + +static Pixmap +x11_create_pixmap(struct segl_winsys *winsys, EGLint width, EGLint height, + EGLint depth) +{ + Window root = DefaultRootWindow(winsys->dpy); + Pixmap pix; + + pix = XCreatePixmap(winsys->dpy, (Drawable) root, width, height, depth); + + return pix; +} + +static void +x11_destroy_pixmap(struct segl_winsys *winsys, Pixmap pix) +{ + if (pix) + XFreePixmap(winsys->dpy, pix); +} + +static double +x11_now(struct segl_winsys *winsys) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return (double) tv.tv_sec + tv.tv_usec / 1000000.0; +} + +struct segl_winsys * +segl_get_winsys(EGLNativeDisplayType dpy) +{ + struct segl_winsys *winsys; + + winsys = calloc(1, sizeof(*winsys)); + if (winsys) { + winsys->dpy = dpy; + + winsys->create_window = x11_create_window; + winsys->destroy_window = x11_destroy_window; + winsys->create_pixmap = x11_create_pixmap; + winsys->destroy_pixmap = x11_destroy_pixmap; + + winsys->now = x11_now; + } + + return winsys; +} |