#include #include #include #include #include #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); }