source: trunk/src/eglapp.cpp @ 1671

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

core: on the Raspberry Pi, use the proprietary graphics library instead of
X11 to create the EGL-capable display.

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