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.

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