選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

299 行
7.7 KiB

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