source: trunk/src/eglapp.cpp @ 1687

Last change on this file since 1687 was 1684, checked in by sam, 8 years ago

build: switch the Android native build rules to autoconf; still a bit rough
but we can now create shared objects for each project; only the testsuite
is not building properly because of issues with STLport, and EglApp is
deactivated because AndroidApp should have precedence.

  • Property svn:keywords set to Id
File size: 6.4 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://sam.zoy.org/projects/COPYING.WTFPL 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#include "core.h"
28#include "lolgl.h"
29#include "eglapp.h"
30
31namespace lol
32{
33
34/*
35 * EGL App implementation class
36 */
37
38class EglAppData
39{
40    friend class EglApp;
41
42private:
43#if defined USE_EGL && !defined __ANDROID__
44    EGLDisplay egl_dpy;
45    EGLContext egl_ctx;
46    EGLSurface egl_surf;
47    uvec2 screen_size;
48#   if defined HAVE_BCM_HOST_H
49    EGL_DISPMANX_WINDOW_T nativewindow;
50#   else
51    Display *dpy;
52    Window win;
53#   endif
54#endif
55};
56
57/*
58 * Public EglApp class
59 */
60
61EglApp::EglApp(char const *title, ivec2 res, float fps) :
62    data(new EglAppData())
63{
64#if defined USE_EGL && !defined __ANDROID__
65#   if defined HAVE_BCM_HOST_H
66    bcm_host_init();
67
68    data->egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
69#   else
70    data->dpy = XOpenDisplay(NULL);
71    if (data->dpy == NULL)
72    {
73        Log::Error("cannot connect to X server\n");
74        exit(EXIT_FAILURE);
75    }
76
77    Window root = DefaultRootWindow(data->dpy);
78
79    XSetWindowAttributes swa;
80    swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
81
82    data->win = XCreateWindow(data->dpy, root, 0, 0, res.x, res.y, 0,
83                              CopyFromParent, InputOutput,
84                              CopyFromParent, CWEventMask, &swa);
85
86    XSetWindowAttributes xattr;
87
88    xattr.override_redirect = False;
89    XChangeWindowAttributes(data->dpy, data->win, CWOverrideRedirect, &xattr);
90
91    XWMHints hints;
92    hints.flags = InputHint;
93    hints.input = True;
94    XSetWMHints(data->dpy, data->win, &hints);
95
96    XMapWindow(data->dpy, data->win);
97    XStoreName(data->dpy, data->win, title);
98
99    data->egl_dpy = eglGetDisplay((EGLNativeDisplayType)data->dpy);
100#   endif
101    if (data->egl_dpy == EGL_NO_DISPLAY)
102    {
103        Log::Error("cannot get EGL display\n");
104        exit(EXIT_FAILURE);
105    }
106
107    if (!eglInitialize(data->egl_dpy, NULL, NULL))
108    {
109        Log::Error("cannot initialize EGL\n");
110        exit(EXIT_FAILURE);
111    }
112
113    EGLint attr[] =
114    {
115        EGL_BUFFER_SIZE, 16,
116        EGL_DEPTH_SIZE, 16,
117        EGL_RED_SIZE, 4,
118        EGL_GREEN_SIZE, 4,
119        EGL_BLUE_SIZE, 4,
120        EGL_ALPHA_SIZE, 4,
121#if defined HAVE_GLES_2X
122        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
123#endif
124        EGL_NONE
125    };
126
127    EGLConfig ecfg;
128    EGLint num_config;
129    if (!eglChooseConfig(data->egl_dpy, attr, &ecfg, 1, &num_config))
130    {
131        Log::Error("cannot choose EGL config (%i)\n", eglGetError());
132        exit(EXIT_FAILURE);
133    }
134
135    if (num_config != 1)
136    {
137        Log::Error("cannot choose between %i EGL configs\n", num_config);
138        exit(EXIT_FAILURE);
139    }
140
141    if (!eglBindAPI(EGL_OPENGL_ES_API))
142    {
143        Log::Error("cannot bind OpenGL ES API (%i)\n", eglGetError());
144        exit(EXIT_FAILURE);
145    }
146
147#   if defined HAVE_BCM_HOST_H
148    DISPMANX_ELEMENT_HANDLE_T dispman_element;
149    DISPMANX_DISPLAY_HANDLE_T dispman_display;
150    DISPMANX_UPDATE_HANDLE_T dispman_update;
151    VC_RECT_T dst_rect;
152    VC_RECT_T src_rect;
153
154    graphics_get_display_size(0 /* LCD */, &data->screen_size.x, &data->screen_size.y);
155
156    dst_rect.x = 0;
157    dst_rect.y = 0;
158    dst_rect.width = data->screen_size.x;
159    dst_rect.height = data->screen_size.y;
160
161    src_rect.x = 0;
162    src_rect.y = 0;
163    src_rect.width = data->screen_size.x << 16;
164    src_rect.height = data->screen_size.y << 16;
165
166    dispman_display = vc_dispmanx_display_open(0 /* LCD */);
167    dispman_update = vc_dispmanx_update_start(0);
168
169    dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
170        0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE,
171        0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/);
172
173    data->nativewindow.element = dispman_element;
174    data->nativewindow.width = data->screen_size.x;
175    data->nativewindow.height = data->screen_size.y;
176    vc_dispmanx_update_submit_sync(dispman_update);
177
178    data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
179                                            &data->nativewindow, NULL);
180#   else
181    data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
182                                            (EGLNativeWindowType)data->win,
183                                            NULL);
184#   endif
185    if (data->egl_surf == EGL_NO_SURFACE)
186    {
187        Log::Error("cannot create EGL surface (%i)\n", eglGetError());
188        exit(EXIT_FAILURE);
189    }
190
191    EGLint ctxattr[] =
192    {
193#if defined HAVE_GLES_2X
194        EGL_CONTEXT_CLIENT_VERSION, 2,
195#endif
196        EGL_NONE
197    };
198    data->egl_ctx = eglCreateContext(data->egl_dpy, ecfg,
199                                     EGL_NO_CONTEXT, ctxattr);
200    if (data->egl_ctx == EGL_NO_CONTEXT)
201    {
202        Log::Error("cannot create EGL context (%i)\n", eglGetError());
203        exit(EXIT_FAILURE);
204    }
205
206    eglMakeCurrent(data->egl_dpy, data->egl_surf,
207                   data->egl_surf, data->egl_ctx);
208
209#   if !defined HAVE_BCM_HOST_H
210    XWindowAttributes gwa;
211    XGetWindowAttributes(data->dpy, data->win, &gwa);
212    data->screen_size = ivec2(gwa.width, gwa.height);
213#   endif
214
215    /* Initialise everything */
216    Ticker::Setup(fps);
217    Video::Setup((ivec2)data->screen_size);
218    Audio::Setup(2);
219#endif
220}
221
222void EglApp::ShowPointer(bool show)
223{
224    ;
225}
226
227void EglApp::Run()
228{
229    while (!Ticker::Finished())
230    {
231        /* Tick the renderer, show the frame and clamp to desired framerate. */
232        Ticker::TickDraw();
233#if defined USE_EGL && !defined __ANDROID__
234        eglSwapBuffers(data->egl_dpy, data->egl_surf);
235#endif
236    }
237}
238
239EglApp::~EglApp()
240{
241#if defined USE_EGL && !defined __ANDROID__
242    eglDestroyContext(data->egl_dpy, data->egl_ctx);
243    eglDestroySurface(data->egl_dpy, data->egl_surf);
244    eglTerminate(data->egl_dpy);
245#   if defined HAVE_BCM_HOST_H
246    /* FIXME */
247#   else
248    XDestroyWindow(data->dpy, data->win);
249    XCloseDisplay(data->dpy);
250#   endif
251#endif
252
253    delete data;
254}
255
256} /* namespace lol */
257
Note: See TracBrowser for help on using the repository browser.