blob: b1df71a5b5377fbe9c13c225540ea052e44e0916 [file] [log] [blame]
#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);
}