You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

297 line
7.6 KiB

  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. #include <lol/engine-internal.h>
  11. #if defined USE_EGL && !defined __ANDROID__
  12. # if defined HAVE_BCM_HOST_H
  13. # include <bcm_host.h>
  14. # else
  15. # include <X11/Xlib.h>
  16. # include <X11/Xatom.h>
  17. # include <X11/Xutil.h>
  18. # endif
  19. # include <EGL/egl.h>
  20. # include <EGL/eglext.h>
  21. #endif
  22. #if USE_SDL || USE_OLD_SDL
  23. # if HAVE_SDL2_SDL_H
  24. # include <SDL2/SDL.h>
  25. # elif HAVE_SDL_SDL_H
  26. # include <SDL/SDL.h>
  27. # else
  28. # include <SDL.h>
  29. # endif
  30. #endif
  31. #include "lolgl.h"
  32. #include "eglapp.h"
  33. #if USE_SDL || USE_OLD_SDL
  34. # include "platform/sdl/sdlinput.h"
  35. #endif
  36. namespace lol
  37. {
  38. /*
  39. * EGL App implementation class
  40. */
  41. class EglAppData
  42. {
  43. friend class EglApp;
  44. private:
  45. #if defined USE_EGL && !defined __ANDROID__
  46. EGLDisplay egl_dpy;
  47. EGLContext egl_ctx;
  48. EGLSurface egl_surf;
  49. uvec2 screen_size;
  50. # if defined HAVE_BCM_HOST_H
  51. EGL_DISPMANX_WINDOW_T nativewindow;
  52. # else
  53. Display *dpy;
  54. Window win;
  55. # endif
  56. #endif
  57. };
  58. /*
  59. * Public EglApp class
  60. */
  61. EglApp::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. data->egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  68. # else
  69. data->dpy = XOpenDisplay(nullptr);
  70. if (data->dpy == nullptr)
  71. {
  72. Log::Error("cannot connect to X server\n");
  73. exit(EXIT_FAILURE);
  74. }
  75. Window root = DefaultRootWindow(data->dpy);
  76. XSetWindowAttributes swa;
  77. swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
  78. data->win = XCreateWindow(data->dpy, root, 0, 0, res.x, res.y, 0,
  79. CopyFromParent, InputOutput,
  80. CopyFromParent, CWEventMask, &swa);
  81. XSetWindowAttributes xattr;
  82. xattr.override_redirect = False;
  83. XChangeWindowAttributes(data->dpy, data->win, CWOverrideRedirect, &xattr);
  84. XWMHints hints;
  85. hints.flags = InputHint;
  86. hints.input = True;
  87. XSetWMHints(data->dpy, data->win, &hints);
  88. XMapWindow(data->dpy, data->win);
  89. XStoreName(data->dpy, data->win, title);
  90. data->egl_dpy = eglGetDisplay((EGLNativeDisplayType)data->dpy);
  91. # endif
  92. if (data->egl_dpy == EGL_NO_DISPLAY)
  93. {
  94. Log::Error("cannot get EGL display\n");
  95. exit(EXIT_FAILURE);
  96. }
  97. if (!eglInitialize(data->egl_dpy, nullptr, nullptr))
  98. {
  99. Log::Error("cannot initialize EGL\n");
  100. exit(EXIT_FAILURE);
  101. }
  102. EGLint attr[] =
  103. {
  104. EGL_BUFFER_SIZE, 16,
  105. EGL_DEPTH_SIZE, 16,
  106. EGL_RED_SIZE, 4,
  107. EGL_GREEN_SIZE, 4,
  108. EGL_BLUE_SIZE, 4,
  109. EGL_ALPHA_SIZE, 4,
  110. #if defined HAVE_GLES_2X
  111. EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
  112. #endif
  113. EGL_NONE
  114. };
  115. EGLConfig ecfg;
  116. EGLint num_config;
  117. if (!eglChooseConfig(data->egl_dpy, attr, &ecfg, 1, &num_config))
  118. {
  119. Log::Error("cannot choose EGL config (%i)\n", eglGetError());
  120. exit(EXIT_FAILURE);
  121. }
  122. if (num_config != 1)
  123. {
  124. Log::Error("cannot choose between %i EGL configs\n", num_config);
  125. exit(EXIT_FAILURE);
  126. }
  127. if (!eglBindAPI(EGL_OPENGL_ES_API))
  128. {
  129. Log::Error("cannot bind OpenGL ES API (%i)\n", eglGetError());
  130. exit(EXIT_FAILURE);
  131. }
  132. # if defined HAVE_BCM_HOST_H
  133. DISPMANX_ELEMENT_HANDLE_T dispman_element;
  134. DISPMANX_DISPLAY_HANDLE_T dispman_display;
  135. DISPMANX_UPDATE_HANDLE_T dispman_update;
  136. VC_RECT_T dst_rect;
  137. VC_RECT_T src_rect;
  138. graphics_get_display_size(0 /* LCD */, &data->screen_size.x, &data->screen_size.y);
  139. dst_rect.x = 0;
  140. dst_rect.y = 0;
  141. dst_rect.width = data->screen_size.x;
  142. dst_rect.height = data->screen_size.y;
  143. src_rect.x = 0;
  144. src_rect.y = 0;
  145. src_rect.width = data->screen_size.x << 16;
  146. src_rect.height = data->screen_size.y << 16;
  147. dispman_display = vc_dispmanx_display_open(0 /* LCD */);
  148. dispman_update = vc_dispmanx_update_start(0);
  149. dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
  150. 0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE,
  151. 0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/);
  152. data->nativewindow.element = dispman_element;
  153. data->nativewindow.width = data->screen_size.x;
  154. data->nativewindow.height = data->screen_size.y;
  155. vc_dispmanx_update_submit_sync(dispman_update);
  156. data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
  157. &data->nativewindow, nullptr);
  158. # else
  159. data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
  160. (EGLNativeWindowType)data->win,
  161. nullptr);
  162. # endif
  163. if (data->egl_surf == EGL_NO_SURFACE)
  164. {
  165. switch (eglGetError())
  166. {
  167. case EGL_BAD_DISPLAY:
  168. Log::Error("missing EGL display connection\n");
  169. break;
  170. case EGL_NOT_INITIALIZED:
  171. Log::Error("EGL display not initialized\n");
  172. break;
  173. case EGL_BAD_CONFIG:
  174. Log::Error("invalid EGL configuration\n");
  175. break;
  176. case EGL_BAD_NATIVE_WINDOW:
  177. Log::Error("invalid EGL native window\n");
  178. break;
  179. case EGL_BAD_ATTRIBUTE:
  180. Log::Error("invalid EGL window attribute\n");
  181. break;
  182. case EGL_BAD_ALLOC:
  183. Log::Error("cannot allocate EGL surface\n");
  184. break;
  185. case EGL_BAD_MATCH:
  186. Log::Error("unsupported EGL window\n");
  187. break;
  188. default:
  189. Log::Error("cannot create EGL surface (%i)\n", eglGetError());
  190. break;
  191. }
  192. exit(EXIT_FAILURE);
  193. }
  194. EGLint ctxattr[] =
  195. {
  196. #if defined HAVE_GLES_2X
  197. EGL_CONTEXT_CLIENT_VERSION, 2,
  198. #endif
  199. EGL_NONE
  200. };
  201. data->egl_ctx = eglCreateContext(data->egl_dpy, ecfg,
  202. EGL_NO_CONTEXT, ctxattr);
  203. if (data->egl_ctx == EGL_NO_CONTEXT)
  204. {
  205. Log::Error("cannot create EGL context (%i)\n", eglGetError());
  206. exit(EXIT_FAILURE);
  207. }
  208. eglMakeCurrent(data->egl_dpy, data->egl_surf,
  209. data->egl_surf, data->egl_ctx);
  210. # if !defined HAVE_BCM_HOST_H
  211. XWindowAttributes gwa;
  212. XGetWindowAttributes(data->dpy, data->win, &gwa);
  213. data->screen_size = uvec2(gwa.width, gwa.height);
  214. # endif
  215. # if USE_SDL || USE_OLD_SDL
  216. new SdlInput(res.x, res.y, data->screen_size.x, data->screen_size.y);
  217. # endif
  218. /* Initialise everything */
  219. Ticker::Setup(fps);
  220. Video::Setup((ivec2)data->screen_size);
  221. Audio::Setup(2);
  222. #endif
  223. }
  224. void EglApp::ShowPointer(bool show)
  225. {
  226. /* FIXME: unimplemented (do we have a mouse pointer anyway? */
  227. (void)show;
  228. }
  229. void EglApp::Tick()
  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. EglApp::~EglApp()
  238. {
  239. #if defined USE_EGL && !defined __ANDROID__
  240. eglDestroyContext(data->egl_dpy, data->egl_ctx);
  241. eglDestroySurface(data->egl_dpy, data->egl_surf);
  242. eglTerminate(data->egl_dpy);
  243. # if defined HAVE_BCM_HOST_H
  244. /* FIXME */
  245. # else
  246. XDestroyWindow(data->dpy, data->win);
  247. XCloseDisplay(data->dpy);
  248. # endif
  249. #endif
  250. delete data;
  251. }
  252. } /* namespace lol */