diff --git a/configure.ac b/configure.ac index 9697eebe..8dc10ea4 100644 --- a/configure.ac +++ b/configure.ac @@ -130,6 +130,16 @@ fi AM_CONDITIONAL(USE_SDL, test "${ac_cv_my_have_sdl}" = "yes") +dnl Use EGL? +ac_cv_my_have_egl="no" +PKG_CHECK_MODULES(EGL, egl, [ac_cv_my_have_egl="yes"], [:]) +if test "${ac_cv_my_have_egl}" != "no"; then + AC_DEFINE(USE_EGL, 1, Define to 1 to use libegl) + EGL_LIBS="${EGL_LIBS} -lX11" +fi +AM_CONDITIONAL(USE_EGL, test "${ac_cv_my_have_egl}" != "no") + + dnl Use libcaca? (required for font generation) ac_cv_my_have_caca="no" PKG_CHECK_MODULES(CACA, caca >= 0.99.beta17, [ac_cv_my_have_caca="yes"], [:]) @@ -164,8 +174,8 @@ AM_CONDITIONAL(USE_CPPUNIT, test "$CPPUNIT" = "yes") # How to use the Lol Engine inside this tree -LOL_CFLAGS="$LOL_CFLAGS -I \$(top_srcdir)/src $SDL_CFLAGS" -LOL_LIBS="$LOL_LIBS $SDL_LIBS" +LOL_CFLAGS="$LOL_CFLAGS -I \$(top_srcdir)/src $SDL_CFLAGS $EGL_CFLAGS" +LOL_LIBS="$LOL_LIBS $SDL_LIBS $EGL_LIBS" AC_SUBST(MATH_LIBS) AC_SUBST(LOL_CFLAGS) diff --git a/src/Makefile.am b/src/Makefile.am index eac6f83c..02940ee0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,8 @@ liblol_a_SOURCES = \ \ sdlapp.cpp sdlapp.h sdlinput.cpp sdlinput.h \ \ + eglapp.cpp eglapp.h \ + \ debugfps.cpp debugfps.h debugsphere.cpp debugsphere.h \ debugrecord.cpp debugrecord.h debugstats.cpp debugstats.h liblol_a_CPPFLAGS = @LOL_CFLAGS@ diff --git a/src/eglapp.cpp b/src/eglapp.cpp new file mode 100644 index 00000000..94a3b404 --- /dev/null +++ b/src/eglapp.cpp @@ -0,0 +1,190 @@ +// +// 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 + +#include + +#if defined USE_EGL +# define Font Font_Diverted +# include +# include +# include +# undef Font +# include +#endif + +#include "core.h" +#include "eglapp.h" + +/* + * 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, vec2i res, float fps) : + data(new EglAppData()) +{ +#if defined USE_EGL + data->dpy = XOpenDisplay(NULL); + if (data->dpy == NULL) + { + fprintf(stderr, "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) + { + fprintf(stderr, "Cannot get EGL display\n"); + exit(EXIT_FAILURE); + } + + if (!eglInitialize(data->egl_dpy, NULL, NULL)) + { + fprintf(stderr, "Cannot initialize EGL\n"); + exit(EXIT_FAILURE); + } + + EGLint attr[] = + { + EGL_BUFFER_SIZE, 16, + EGL_RENDERABLE_TYPE, +#if defined HAVE_GLES_1X + EGL_OPENGL_ES_BIT, +#elif 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)) + { + fprintf(stderr, "Cannot choose EGL config (%i)\n", eglGetError()); + exit(EXIT_FAILURE); + } + + if (num_config != 1) + { + fprintf(stderr, "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) + { + fprintf(stderr, "Cannot create EGL surface (%i)\n", eglGetError()); + exit(EXIT_FAILURE); + } + + EGLint ctxattr[] = + { +#if defined HAVE_GLES_1X + EGL_CONTEXT_CLIENT_VERSION, 1, +#elif 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) + { + fprintf(stderr, "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(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 + + free(data); +} + diff --git a/src/eglapp.h b/src/eglapp.h new file mode 100644 index 00000000..542b6834 --- /dev/null +++ b/src/eglapp.h @@ -0,0 +1,36 @@ +// +// 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. +// + +// +// The EglApp class +// ---------------- +// + +#if !defined __DH_EGLAPP_H__ +#define __DH_EGLAPP_H__ + +#include "matrix.h" + +class EglAppData; + +class EglApp +{ +public: + EglApp(char const *title, vec2i res, float fps); + virtual ~EglApp(); + + void Run(); + +private: + EglAppData *data; +}; + +#endif // __DH_EGLAPP_H__ + diff --git a/src/video.cpp b/src/video.cpp index ca526058..e11a56d9 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -30,11 +30,17 @@ mat4 proj_matrix, view_matrix, model_matrix; #if defined HAVE_GL_2X || defined HAVE_GLES_2X static char const *vertexshader = +#if defined HAVE_GLES_2X + "attribute vec3 in_Position;\n" + "attribute vec2 in_TexCoord;\n" + "varying vec2 pass_TexCoord;\n" +#else "#version 130\n" "\n" "in vec3 in_Position;\n" - //"in vec3 in_Color;\n" "in vec2 in_TexCoord;\n" +#endif + //"in vec3 in_Color;\n" //"out vec3 pass_Color;\n" "uniform mat4 proj_matrix;\n" "uniform mat4 view_matrix;\n" @@ -44,8 +50,12 @@ static char const *vertexshader = "{\n" " gl_Position = proj_matrix * view_matrix * model_matrix" " * vec4(in_Position, 1.0f);\n" - " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n" //" pass_Color = in_Color;\n" +#if defined HAVE_GLES_2X + " pass_TexCoord = in_TexCoord;\n" +#else + " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n" +#endif "}\n"; static char const *fragmentshader = @@ -54,13 +64,20 @@ static char const *fragmentshader = "uniform sampler2D in_Texture;\n" //"in vec3 pass_Color;\n" //"out vec4 out_Color;\n" +#if defined HAVE_GLES_2X + "varying vec2 pass_TexCoord;\n" +#endif "\n" "void main()\n" "{\n" //" gl_FragColor = 0.5 * (texture2D(in_Texture, vec2(gl_TexCoord[0]))\n" //" + vec4(pass_Color, 1.0));\n" +#if defined HAVE_GLES_2X + " gl_FragColor = vec4(0.5, 1.0, 0.0, 0.5);\n" +#else " gl_FragColor = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n" - //" gl_FragColor = vec4(0.5, 1.0, 0.0, 0.5);\n" +#endif + //" gl_FragColor = texture2D(in_Texture, pass_TexCoord);\n" "}\n"; #endif