Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

258 строки
6.3 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://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #if defined USE_EGL
  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. #include "core.h"
  25. #include "lolgl.h"
  26. #include "eglapp.h"
  27. namespace lol
  28. {
  29. /*
  30. * EGL App implementation class
  31. */
  32. class EglAppData
  33. {
  34. friend class EglApp;
  35. private:
  36. #if defined USE_EGL
  37. EGLDisplay egl_dpy;
  38. EGLContext egl_ctx;
  39. EGLSurface egl_surf;
  40. uvec2 screen_size;
  41. # if defined HAVE_BCM_HOST_H
  42. EGL_DISPMANX_WINDOW_T nativewindow;
  43. # else
  44. Display *dpy;
  45. Window win;
  46. # endif
  47. #endif
  48. };
  49. /*
  50. * Public EglApp class
  51. */
  52. EglApp::EglApp(char const *title, ivec2 res, float fps) :
  53. data(new EglAppData())
  54. {
  55. #if defined USE_EGL
  56. # if defined HAVE_BCM_HOST_H
  57. bcm_host_init();
  58. data->egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  59. # else
  60. data->dpy = XOpenDisplay(NULL);
  61. if (data->dpy == NULL)
  62. {
  63. Log::Error("cannot connect to X server\n");
  64. exit(EXIT_FAILURE);
  65. }
  66. Window root = DefaultRootWindow(data->dpy);
  67. XSetWindowAttributes swa;
  68. swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
  69. data->win = XCreateWindow(data->dpy, root, 0, 0, res.x, res.y, 0,
  70. CopyFromParent, InputOutput,
  71. CopyFromParent, CWEventMask, &swa);
  72. XSetWindowAttributes xattr;
  73. xattr.override_redirect = False;
  74. XChangeWindowAttributes(data->dpy, data->win, CWOverrideRedirect, &xattr);
  75. XWMHints hints;
  76. hints.flags = InputHint;
  77. hints.input = True;
  78. XSetWMHints(data->dpy, data->win, &hints);
  79. XMapWindow(data->dpy, data->win);
  80. XStoreName(data->dpy, data->win, title);
  81. data->egl_dpy = eglGetDisplay((EGLNativeDisplayType)data->dpy);
  82. # endif
  83. if (data->egl_dpy == EGL_NO_DISPLAY)
  84. {
  85. Log::Error("cannot get EGL display\n");
  86. exit(EXIT_FAILURE);
  87. }
  88. if (!eglInitialize(data->egl_dpy, NULL, NULL))
  89. {
  90. Log::Error("cannot initialize EGL\n");
  91. exit(EXIT_FAILURE);
  92. }
  93. EGLint attr[] =
  94. {
  95. EGL_BUFFER_SIZE, 16,
  96. EGL_DEPTH_SIZE, 16,
  97. EGL_RED_SIZE, 4,
  98. EGL_GREEN_SIZE, 4,
  99. EGL_BLUE_SIZE, 4,
  100. EGL_ALPHA_SIZE, 4,
  101. #if defined HAVE_GLES_2X
  102. EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
  103. #endif
  104. EGL_NONE
  105. };
  106. EGLConfig ecfg;
  107. EGLint num_config;
  108. if (!eglChooseConfig(data->egl_dpy, attr, &ecfg, 1, &num_config))
  109. {
  110. Log::Error("cannot choose EGL config (%i)\n", eglGetError());
  111. exit(EXIT_FAILURE);
  112. }
  113. if (num_config != 1)
  114. {
  115. Log::Error("cannot choose between %i EGL configs\n", num_config);
  116. exit(EXIT_FAILURE);
  117. }
  118. if (!eglBindAPI(EGL_OPENGL_ES_API))
  119. {
  120. Log::Error("cannot bind OpenGL ES API (%i)\n", eglGetError());
  121. exit(EXIT_FAILURE);
  122. }
  123. # if defined HAVE_BCM_HOST_H
  124. DISPMANX_ELEMENT_HANDLE_T dispman_element;
  125. DISPMANX_DISPLAY_HANDLE_T dispman_display;
  126. DISPMANX_UPDATE_HANDLE_T dispman_update;
  127. VC_RECT_T dst_rect;
  128. VC_RECT_T src_rect;
  129. graphics_get_display_size(0 /* LCD */, &data->screen_size.x, &data->screen_size.y);
  130. dst_rect.x = 0;
  131. dst_rect.y = 0;
  132. dst_rect.width = data->screen_size.x;
  133. dst_rect.height = data->screen_size.y;
  134. src_rect.x = 0;
  135. src_rect.y = 0;
  136. src_rect.width = data->screen_size.x << 16;
  137. src_rect.height = data->screen_size.y << 16;
  138. dispman_display = vc_dispmanx_display_open(0 /* LCD */);
  139. dispman_update = vc_dispmanx_update_start(0);
  140. dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
  141. 0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE,
  142. 0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/);
  143. data->nativewindow.element = dispman_element;
  144. data->nativewindow.width = data->screen_size.x;
  145. data->nativewindow.height = data->screen_size.y;
  146. vc_dispmanx_update_submit_sync(dispman_update);
  147. data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
  148. &data->nativewindow, NULL);
  149. # else
  150. data->egl_surf = eglCreateWindowSurface(data->egl_dpy, ecfg,
  151. (EGLNativeWindowType)data->win,
  152. NULL);
  153. # endif
  154. if (data->egl_surf == EGL_NO_SURFACE)
  155. {
  156. Log::Error("cannot create EGL surface (%i)\n", eglGetError());
  157. exit(EXIT_FAILURE);
  158. }
  159. EGLint ctxattr[] =
  160. {
  161. #if defined HAVE_GLES_2X
  162. EGL_CONTEXT_CLIENT_VERSION, 2,
  163. #endif
  164. EGL_NONE
  165. };
  166. data->egl_ctx = eglCreateContext(data->egl_dpy, ecfg,
  167. EGL_NO_CONTEXT, ctxattr);
  168. if (data->egl_ctx == EGL_NO_CONTEXT)
  169. {
  170. Log::Error("cannot create EGL context (%i)\n", eglGetError());
  171. exit(EXIT_FAILURE);
  172. }
  173. eglMakeCurrent(data->egl_dpy, data->egl_surf,
  174. data->egl_surf, data->egl_ctx);
  175. # if !defined HAVE_BCM_HOST_H
  176. XWindowAttributes gwa;
  177. XGetWindowAttributes(data->dpy, data->win, &gwa);
  178. data->screen_size = ivec2(gwa.width, gwa.height);
  179. # endif
  180. /* Initialise everything */
  181. Ticker::Setup(fps);
  182. Video::Setup((ivec2)data->screen_size);
  183. Audio::Setup(2);
  184. #endif
  185. }
  186. void EglApp::ShowPointer(bool show)
  187. {
  188. ;
  189. }
  190. void EglApp::Run()
  191. {
  192. while (!Ticker::Finished())
  193. {
  194. /* Tick the renderer, show the frame and clamp to desired framerate. */
  195. Ticker::TickDraw();
  196. #if defined USE_EGL
  197. eglSwapBuffers(data->egl_dpy, data->egl_surf);
  198. #endif
  199. }
  200. }
  201. EglApp::~EglApp()
  202. {
  203. #if defined USE_EGL
  204. eglDestroyContext(data->egl_dpy, data->egl_ctx);
  205. eglDestroySurface(data->egl_dpy, data->egl_surf);
  206. eglTerminate(data->egl_dpy);
  207. # if defined HAVE_BCM_HOST_H
  208. /* FIXME */
  209. # else
  210. XDestroyWindow(data->dpy, data->win);
  211. XCloseDisplay(data->dpy);
  212. # endif
  213. #endif
  214. delete data;
  215. }
  216. } /* namespace lol */