Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

291 linhas
7.5 KiB

  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 */