// // Lol Engine // // Copyright: (c) 2010-2011 Sam Hocevar // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See // http://sam.zoy.org/projects/COPYING.WTFPL for more details. // #if defined HAVE_CONFIG_H # include "config.h" #endif #if defined USE_EGL # include # include # include # include #endif #include "core.h" #include "lolgl.h" #include "eglapp.h" namespace lol { /* * EGL App implementation class */ class EglAppData { friend class EglApp; private: #if defined USE_EGL Display *dpy; Window win; EGLDisplay egl_dpy; EGLContext egl_ctx; EGLSurface egl_surf; #endif }; /* * Public EglApp class */ EglApp::EglApp(char const *title, ivec2 res, float fps) : data(new EglAppData()) { #if defined USE_EGL data->dpy = XOpenDisplay(NULL); if (data->dpy == NULL) { Log::Error("cannot connect to X server\n"); exit(EXIT_FAILURE); } Window root = DefaultRootWindow(data->dpy); XSetWindowAttributes swa; swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; data->win = XCreateWindow(data->dpy, root, 0, 0, res.x, res.y, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &swa); XSetWindowAttributes xattr; xattr.override_redirect = False; XChangeWindowAttributes(data->dpy, data->win, CWOverrideRedirect, &xattr); XWMHints hints; hints.flags = InputHint; hints.input = True; XSetWMHints(data->dpy, data->win, &hints); XMapWindow(data->dpy, data->win); XStoreName(data->dpy, data->win, title); data->egl_dpy = eglGetDisplay((EGLNativeDisplayType)data->dpy); if (data->egl_dpy == EGL_NO_DISPLAY) { Log::Error("cannot get EGL display\n"); exit(EXIT_FAILURE); } if (!eglInitialize(data->egl_dpy, NULL, NULL)) { Log::Error("cannot initialize EGL\n"); exit(EXIT_FAILURE); } EGLint attr[] = { EGL_BUFFER_SIZE, 16, EGL_RENDERABLE_TYPE, #if defined HAVE_GLES_2X EGL_OPENGL_ES2_BIT, #endif EGL_NONE }; EGLConfig ecfg; EGLint num_config; if (!eglChooseConfig(data->egl_dpy, attr, &ecfg, 1, &num_config)) { Log::Error("cannot choose EGL config (%i)\n", eglGetError()); exit(EXIT_FAILURE); } if (num_config != 1) { Log::Error("cannot choose between %i EGL configs\n", num_config); exit(EXIT_FAILURE); } data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg, data->win, NULL); if (data->egl_surf == EGL_NO_SURFACE) { Log::Error("cannot create EGL surface (%i)\n", eglGetError()); exit(EXIT_FAILURE); } EGLint ctxattr[] = { #if defined HAVE_GLES_2X EGL_CONTEXT_CLIENT_VERSION, 2, #endif EGL_NONE }; data->egl_ctx = eglCreateContext(data->egl_dpy, ecfg, EGL_NO_CONTEXT, ctxattr); if (data->egl_ctx == EGL_NO_CONTEXT) { Log::Error("cannot create EGL context (%i)\n", eglGetError()); exit(EXIT_FAILURE); } eglMakeCurrent(data->egl_dpy, data->egl_surf, data->egl_surf, data->egl_ctx); XWindowAttributes gwa; XGetWindowAttributes(data->dpy, data->win, &gwa); /* Initialise everything */ Ticker::Setup(fps); Video::Setup(ivec2(gwa.width, gwa.height)); Audio::Setup(2); #endif } void EglApp::Run() { while (!Ticker::Finished()) { /* Tick the game */ Ticker::TickGame(); /* Tick the renderer, show the frame and clamp to desired framerate. */ Ticker::TickDraw(); #if defined USE_EGL eglSwapBuffers(data->egl_dpy, data->egl_surf); #endif Ticker::ClampFps(); } } EglApp::~EglApp() { #if defined USE_EGL eglDestroyContext(data->egl_dpy, data->egl_ctx); eglDestroySurface(data->egl_dpy, data->egl_surf); eglTerminate(data->egl_dpy); XDestroyWindow(data->dpy, data->win); XCloseDisplay(data->dpy); #endif delete data; } } /* namespace lol */