source: trunk/src/eglapp.cpp @ 2370

Last change on this file since 2370 was 2301, checked in by sam, 7 years ago

build: fix a few macro logic issues in SDL.h inclusion.

  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#if defined USE_EGL && !defined __ANDROID__
16#   if defined HAVE_BCM_HOST_H
17#       include <bcm_host.h>
18#   else
19#       include <X11/Xlib.h>
20#       include <X11/Xatom.h>
21#       include <X11/Xutil.h>
22#   endif
23#   include <EGL/egl.h>
24#   include <EGL/eglext.h>
25#endif
26
27#if defined USE_SDL
28#   if defined HAVE_SDL_SDL_H
29#      include <SDL/SDL.h>
30#   else
31#      include <SDL.h>
32#   endif
33#endif
34
35#include "core.h"
36#include "lolgl.h"
37#include "eglapp.h"
38#if defined USE_SDL
39#   include "platform/sdl/sdlinput.h"
40#endif
41
42namespace lol
43{
44
45/*
46 * EGL App implementation class
47 */
48
49class EglAppData
50{
51    friend class EglApp;
52
53private:
54#if defined USE_EGL && !defined __ANDROID__
55    EGLDisplay egl_dpy;
56    EGLContext egl_ctx;
57    EGLSurface egl_surf;
58    uvec2 screen_size;
59#   if defined HAVE_BCM_HOST_H
60    EGL_DISPMANX_WINDOW_T nativewindow;
61#   else
62    Display *dpy;
63    Window win;
64#   endif
65#endif
66};
67
68/*
69 * Public EglApp class
70 */
71
72EglApp::EglApp(char const *title, ivec2 res, float fps) :
73    data(new EglAppData())
74{
75#if defined USE_EGL && !defined __ANDROID__
76#   if defined HAVE_BCM_HOST_H
77    bcm_host_init();
78
79    data->egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
80#   else
81    data->dpy = XOpenDisplay(NULL);
82    if (data->dpy == NULL)
83    {
84        Log::Error("cannot connect to X server\n");
85        exit(EXIT_FAILURE);
86    }
87
88    Window root = DefaultRootWindow(data->dpy);
89
90    XSetWindowAttributes swa;
91    swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
92
93    data->win = XCreateWindow(data->dpy, root, 0, 0, res.x, res.y, 0,
94                              CopyFromParent, InputOutput,
95                              CopyFromParent, CWEventMask, &swa);
96
97    XSetWindowAttributes xattr;
98
99    xattr.override_redirect = False;
100    XChangeWindowAttributes(data->dpy, data->win, CWOverrideRedirect, &xattr);
101
102    XWMHints hints;
103    hints.flags = InputHint;
104    hints.input = True;
105    XSetWMHints(data->dpy, data->win, &hints);
106
107    XMapWindow(data->dpy, data->win);
108    XStoreName(data->dpy, data->win, title);
109
110    data->egl_dpy = eglGetDisplay((EGLNativeDisplayType)data->dpy);
111#   endif
112    if (data->egl_dpy == EGL_NO_DISPLAY)
113    {
114        Log::Error("cannot get EGL display\n");
115        exit(EXIT_FAILURE);
116    }
117
118    if (!eglInitialize(data->egl_dpy, NULL, NULL))
119    {
120        Log::Error("cannot initialize EGL\n");
121        exit(EXIT_FAILURE);
122    }
123
124    EGLint attr[] =
125    {
126        EGL_BUFFER_SIZE, 16,
127        EGL_DEPTH_SIZE, 16,
128        EGL_RED_SIZE, 4,
129        EGL_GREEN_SIZE, 4,
130        EGL_BLUE_SIZE, 4,
131        EGL_ALPHA_SIZE, 4,
132#if defined HAVE_GLES_2X
133        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
134#endif
135        EGL_NONE
136    };
137
138    EGLConfig ecfg;
139    EGLint num_config;
140    if (!eglChooseConfig(data->egl_dpy, attr, &ecfg, 1, &num_config))
141    {
142        Log::Error("cannot choose EGL config (%i)\n", eglGetError());
143        exit(EXIT_FAILURE);
144    }
145
146    if (num_config != 1)
147    {
148        Log::Error("cannot choose between %i EGL configs\n", num_config);
149        exit(EXIT_FAILURE);
150    }
151
152    if (!eglBindAPI(EGL_OPENGL_ES_API))
153    {
154        Log::Error("cannot bind OpenGL ES API (%i)\n", eglGetError());
155        exit(EXIT_FAILURE);
156    }
157
158#   if defined HAVE_BCM_HOST_H
159    DISPMANX_ELEMENT_HANDLE_T dispman_element;
160    DISPMANX_DISPLAY_HANDLE_T dispman_display;
161    DISPMANX_UPDATE_HANDLE_T dispman_update;
162    VC_RECT_T dst_rect;
163    VC_RECT_T src_rect;
164
165    graphics_get_display_size(0 /* LCD */, &data->screen_size.x, &data->screen_size.y);
166
167    dst_rect.x = 0;
168    dst_rect.y = 0;
169    dst_rect.width = data->screen_size.x;
170    dst_rect.height = data->screen_size.y;
171
172    src_rect.x = 0;
173    src_rect.y = 0;
174    src_rect.width = data->screen_size.x << 16;
175    src_rect.height = data->screen_size.y << 16;
176
177    dispman_display = vc_dispmanx_display_open(0 /* LCD */);
178    dispman_update = vc_dispmanx_update_start(0);
179
180    dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
181        0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE,
182        0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/);
183
184    data->nativewindow.element = dispman_element;
185    data->nativewindow.width = data->screen_size.x;
186    data->nativewindow.height = data->screen_size.y;
187    vc_dispmanx_update_submit_sync(dispman_update);
188
189    data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
190                                            &data->nativewindow, NULL);
191#   else
192    data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
193                                            (EGLNativeWindowType)data->win,
194                                            NULL);
195#   endif
196    if (data->egl_surf == EGL_NO_SURFACE)
197    {
198        switch (eglGetError())
199        {
200        case EGL_BAD_DISPLAY:
201            Log::Error("missing EGL display connection\n");
202            break;
203        case EGL_NOT_INITIALIZED:
204            Log::Error("EGL display not initialized\n");
205            break;
206        case EGL_BAD_CONFIG:
207            Log::Error("invalid EGL configuration\n");
208            break;
209        case EGL_BAD_NATIVE_WINDOW:
210            Log::Error("invalid EGL native window\n");
211            break;
212        case EGL_BAD_ATTRIBUTE:
213            Log::Error("invalid EGL window attribute\n");
214            break;
215        case EGL_BAD_ALLOC:
216            Log::Error("cannot allocate EGL surface\n");
217            break;
218        case EGL_BAD_MATCH:
219            Log::Error("unsupported EGL window\n");
220            break;
221        default:
222            Log::Error("cannot create EGL surface (%i)\n", eglGetError());
223            break;
224        }
225
226        exit(EXIT_FAILURE);
227    }
228
229    EGLint ctxattr[] =
230    {
231#if defined HAVE_GLES_2X
232        EGL_CONTEXT_CLIENT_VERSION, 2,
233#endif
234        EGL_NONE
235    };
236    data->egl_ctx = eglCreateContext(data->egl_dpy, ecfg,
237                                     EGL_NO_CONTEXT, ctxattr);
238    if (data->egl_ctx == EGL_NO_CONTEXT)
239    {
240        Log::Error("cannot create EGL context (%i)\n", eglGetError());
241        exit(EXIT_FAILURE);
242    }
243
244    eglMakeCurrent(data->egl_dpy, data->egl_surf,
245                   data->egl_surf, data->egl_ctx);
246
247#   if !defined HAVE_BCM_HOST_H
248    XWindowAttributes gwa;
249    XGetWindowAttributes(data->dpy, data->win, &gwa);
250    data->screen_size = ivec2(gwa.width, gwa.height);
251#   endif
252
253#   if defined USE_SDL
254    new SdlInput();
255#   endif
256
257    /* Initialise everything */
258    Ticker::Setup(fps);
259    Video::Setup((ivec2)data->screen_size);
260    Audio::Setup(2);
261#endif
262}
263
264void EglApp::ShowPointer(bool show)
265{
266    /* FIXME: unimplemented (do we have a mouse pointer anyway? */
267    (void)show;
268}
269
270void EglApp::Tick()
271{
272    /* Tick the renderer, show the frame and clamp to desired framerate. */
273    Ticker::TickDraw();
274#if defined USE_EGL && !defined __ANDROID__
275    eglSwapBuffers(data->egl_dpy, data->egl_surf);
276#endif
277}
278
279EglApp::~EglApp()
280{
281#if defined USE_EGL && !defined __ANDROID__
282    eglDestroyContext(data->egl_dpy, data->egl_ctx);
283    eglDestroySurface(data->egl_dpy, data->egl_surf);
284    eglTerminate(data->egl_dpy);
285#   if defined HAVE_BCM_HOST_H
286    /* FIXME */
287#   else
288    XDestroyWindow(data->dpy, data->win);
289    XCloseDisplay(data->dpy);
290#   endif
291#endif
292
293    delete data;
294}
295
296} /* namespace lol */
297
Note: See TracBrowser for help on using the repository browser.