Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

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