EGLOpenGLWindow.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // portions of this file are copied from GLFW egl_context.c/egl_context.h
  2. //========================================================================
  3. // GLFW 3.3 EGL - www.glfw.org
  4. //------------------------------------------------------------------------
  5. // Copyright (c) 2002-2006 Marcus Geelnard
  6. // Copyright (c) 2006-2016 Camilla Löwy <[email protected]>
  7. //
  8. // This software is provided 'as-is', without any express or implied
  9. // warranty. In no event will the authors be held liable for any damages
  10. // arising from the use of this software.
  11. //
  12. // Permission is granted to anyone to use this software for any purpose,
  13. // including commercial applications, and to alter it and redistribute it
  14. // freely, subject to the following restrictions:
  15. //
  16. // 1. The origin of this software must not be misrepresented; you must not
  17. // claim that you wrote the original software. If you use this software
  18. // in a product, an acknowledgment in the product documentation would
  19. // be appreciated but is not required.
  20. //
  21. // 2. Altered source versions must be plainly marked as such, and must not
  22. // be misrepresented as being the original software.
  23. //
  24. // 3. This notice may not be removed or altered from any source
  25. // distribution.
  26. //
  27. //========================================================================
  28. #ifdef BT_USE_EGL
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <cstdlib>
  33. #include "OpenGLInclude.h"
  34. #include "glad/egl.h"
  35. #include "glad/gl.h"
  36. #include "EGLOpenGLWindow.h"
  37. struct EGLInternalData2
  38. {
  39. bool m_isInitialized;
  40. int m_windowWidth;
  41. int m_windowHeight;
  42. int m_renderDevice;
  43. b3KeyboardCallback m_keyboardCallback;
  44. b3WheelCallback m_wheelCallback;
  45. b3ResizeCallback m_resizeCallback;
  46. b3MouseButtonCallback m_mouseButtonCallback;
  47. b3MouseMoveCallback m_mouseMoveCallback;
  48. EGLBoolean success;
  49. EGLint num_configs;
  50. EGLConfig egl_config;
  51. EGLSurface egl_surface;
  52. EGLContext egl_context;
  53. EGLDisplay egl_display;
  54. EGLInternalData2()
  55. : m_isInitialized(false),
  56. m_windowWidth(0),
  57. m_windowHeight(0),
  58. m_keyboardCallback(0),
  59. m_wheelCallback(0),
  60. m_resizeCallback(0),
  61. m_mouseButtonCallback(0),
  62. m_mouseMoveCallback(0) {}
  63. };
  64. EGLOpenGLWindow::EGLOpenGLWindow() { m_data = new EGLInternalData2(); }
  65. EGLOpenGLWindow::~EGLOpenGLWindow() { delete m_data; }
  66. void EGLOpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci)
  67. {
  68. m_data->m_windowWidth = ci.m_width;
  69. m_data->m_windowHeight = ci.m_height;
  70. m_data->m_renderDevice = ci.m_renderDevice;
  71. EGLint egl_config_attribs[] = {EGL_RED_SIZE,
  72. 8,
  73. EGL_GREEN_SIZE,
  74. 8,
  75. EGL_BLUE_SIZE,
  76. 8,
  77. EGL_DEPTH_SIZE,
  78. 8,
  79. EGL_SURFACE_TYPE,
  80. EGL_PBUFFER_BIT,
  81. EGL_RENDERABLE_TYPE,
  82. EGL_OPENGL_BIT,
  83. EGL_NONE};
  84. EGLint egl_pbuffer_attribs[] = {
  85. EGL_WIDTH,
  86. m_data->m_windowWidth,
  87. EGL_HEIGHT,
  88. m_data->m_windowHeight,
  89. EGL_NONE,
  90. };
  91. // Load EGL functions
  92. int egl_version = gladLoaderLoadEGL(NULL);
  93. if (!egl_version)
  94. {
  95. fprintf(stderr, "failed to EGL with glad.\n");
  96. exit(EXIT_FAILURE);
  97. };
  98. // Query EGL Devices
  99. const int max_devices = 32;
  100. EGLDeviceEXT egl_devices[max_devices];
  101. EGLint num_devices = 0;
  102. EGLint egl_error = eglGetError();
  103. if (!eglQueryDevicesEXT(max_devices, egl_devices, &num_devices) ||
  104. egl_error != EGL_SUCCESS)
  105. {
  106. printf("eglQueryDevicesEXT Failed.\n");
  107. m_data->egl_display = EGL_NO_DISPLAY;
  108. } else
  109. {
  110. // default case, should always happen (for future compatibility)
  111. if (m_data->m_renderDevice == -1)
  112. {
  113. // check env variable
  114. const char* env_p = std::getenv("EGL_VISIBLE_DEVICES");
  115. // variable is set
  116. if(env_p != NULL)
  117. {
  118. m_data->m_renderDevice = std::atoi(env_p);
  119. fprintf(stderr, "EGL device choice: %d of %d (from EGL_VISIBLE_DEVICES)\n", m_data->m_renderDevice, num_devices);
  120. } else {
  121. fprintf(stderr, "EGL device choice: %d of %d.\n", m_data->m_renderDevice, num_devices);
  122. } // else leave with -1
  123. } else
  124. {
  125. fprintf(stderr, "EGL device choice: %d of %d.\n", m_data->m_renderDevice, num_devices);
  126. }
  127. }
  128. // Query EGL Screens
  129. if (m_data->m_renderDevice == -1)
  130. {
  131. // Chose default screen, by trying all
  132. for (EGLint i = 0; i < num_devices; ++i)
  133. {
  134. // Set display
  135. EGLDisplay display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
  136. egl_devices[i], NULL);
  137. if (eglGetError() == EGL_SUCCESS && display != EGL_NO_DISPLAY)
  138. {
  139. int major, minor;
  140. EGLBoolean initialized = eglInitialize(display, &major, &minor);
  141. if (eglGetError() == EGL_SUCCESS && initialized == EGL_TRUE)
  142. {
  143. m_data->egl_display = display;
  144. break;
  145. }
  146. }
  147. else
  148. {
  149. fprintf(stderr, "GetDisplay %d failed with error: %x\n", i, eglGetError());
  150. }
  151. }
  152. }
  153. else
  154. {
  155. // Chose specific screen, by using m_renderDevice
  156. if (m_data->m_renderDevice < 0 || m_data->m_renderDevice >= num_devices)
  157. {
  158. fprintf(stderr, "Invalid render_device choice: %d < %d.\n", m_data->m_renderDevice, num_devices);
  159. exit(EXIT_FAILURE);
  160. }
  161. // Set display
  162. EGLDisplay display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
  163. egl_devices[m_data->m_renderDevice], NULL);
  164. if (eglGetError() == EGL_SUCCESS && display != EGL_NO_DISPLAY)
  165. {
  166. int major, minor;
  167. EGLBoolean initialized = eglInitialize(display, &major, &minor);
  168. if (eglGetError() == EGL_SUCCESS && initialized == EGL_TRUE)
  169. {
  170. m_data->egl_display = display;
  171. }
  172. }
  173. else
  174. {
  175. fprintf(stderr, "GetDisplay %d failed with error: %x\n", m_data->m_renderDevice, eglGetError());
  176. }
  177. }
  178. if (!eglInitialize(m_data->egl_display, NULL, NULL))
  179. {
  180. fprintf(stderr, "eglInitialize() failed with error: %x\n", eglGetError());
  181. exit(EXIT_FAILURE);
  182. }
  183. egl_version = gladLoaderLoadEGL(m_data->egl_display);
  184. if (!egl_version)
  185. {
  186. fprintf(stderr, "Unable to reload EGL.\n");
  187. exit(EXIT_FAILURE);
  188. }
  189. printf("Loaded EGL %d.%d after reload.\n", GLAD_VERSION_MAJOR(egl_version),
  190. GLAD_VERSION_MINOR(egl_version));
  191. m_data->success = eglBindAPI(EGL_OPENGL_API);
  192. if (!m_data->success)
  193. {
  194. // TODO: Properly handle this error (requires change to default window
  195. // API to change return on all window types to bool).
  196. fprintf(stderr, "Failed to bind OpenGL API.\n");
  197. exit(EXIT_FAILURE);
  198. }
  199. m_data->success =
  200. eglChooseConfig(m_data->egl_display, egl_config_attribs,
  201. &m_data->egl_config, 1, &m_data->num_configs);
  202. if (!m_data->success)
  203. {
  204. // TODO: Properly handle this error (requires change to default window
  205. // API to change return on all window types to bool).
  206. fprintf(stderr, "Failed to choose config (eglError: %d)\n", eglGetError());
  207. exit(EXIT_FAILURE);
  208. }
  209. if (m_data->num_configs != 1)
  210. {
  211. fprintf(stderr, "Didn't get exactly one config, but %d\n", m_data->num_configs);
  212. exit(EXIT_FAILURE);
  213. }
  214. m_data->egl_surface = eglCreatePbufferSurface(
  215. m_data->egl_display, m_data->egl_config, egl_pbuffer_attribs);
  216. if (m_data->egl_surface == EGL_NO_SURFACE)
  217. {
  218. fprintf(stderr, "Unable to create EGL surface (eglError: %d)\n", eglGetError());
  219. exit(EXIT_FAILURE);
  220. }
  221. m_data->egl_context = eglCreateContext(
  222. m_data->egl_display, m_data->egl_config, EGL_NO_CONTEXT, NULL);
  223. if (!m_data->egl_context)
  224. {
  225. fprintf(stderr, "Unable to create EGL context (eglError: %d)\n", eglGetError());
  226. exit(EXIT_FAILURE);
  227. }
  228. m_data->success =
  229. eglMakeCurrent(m_data->egl_display, m_data->egl_surface, m_data->egl_surface,
  230. m_data->egl_context);
  231. if (!m_data->success)
  232. {
  233. fprintf(stderr, "Failed to make context current (eglError: %d)\n", eglGetError());
  234. exit(EXIT_FAILURE);
  235. }
  236. if (!gladLoadGL((GLADloadfunc)eglGetProcAddress))
  237. {
  238. fprintf(stderr, "failed to load GL with glad.\n");
  239. exit(EXIT_FAILURE);
  240. }
  241. const GLubyte* ven = glGetString(GL_VENDOR);
  242. printf("GL_VENDOR=%s\n", ven);
  243. const GLubyte* ren = glGetString(GL_RENDERER);
  244. printf("GL_RENDERER=%s\n", ren);
  245. const GLubyte* ver = glGetString(GL_VERSION);
  246. printf("GL_VERSION=%s\n", ver);
  247. const GLubyte* sl = glGetString(GL_SHADING_LANGUAGE_VERSION);
  248. printf("GL_SHADING_LANGUAGE_VERSION=%s\n", sl);
  249. glViewport(0,0,m_data->m_windowWidth, m_data->m_windowHeight);
  250. //int i = pthread_getconcurrency();
  251. //printf("pthread_getconcurrency()=%d\n", i);
  252. }
  253. void EGLOpenGLWindow::closeWindow()
  254. {
  255. eglMakeCurrent(m_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
  256. EGL_NO_CONTEXT);
  257. eglDestroySurface(m_data->egl_display, m_data->egl_surface);
  258. eglDestroyContext(m_data->egl_display, m_data->egl_context);
  259. printf("Destroy EGL OpenGL window.\n");
  260. }
  261. void EGLOpenGLWindow::runMainLoop() {}
  262. float EGLOpenGLWindow::getTimeInSeconds() { return 0.; }
  263. bool EGLOpenGLWindow::requestedExit() const { return false; }
  264. void EGLOpenGLWindow::setRequestExit() {}
  265. void EGLOpenGLWindow::startRendering()
  266. {
  267. // printf("EGL window start rendering.\n");
  268. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  269. glEnable(GL_DEPTH_TEST);
  270. }
  271. void EGLOpenGLWindow::endRendering()
  272. {
  273. // printf("EGL window end rendering.\n");
  274. eglSwapBuffers(m_data->egl_display, m_data->egl_surface);
  275. }
  276. bool EGLOpenGLWindow::isModifierKeyPressed(int key) { return false; }
  277. void EGLOpenGLWindow::setMouseMoveCallback(b3MouseMoveCallback mouseCallback)
  278. {
  279. m_data->m_mouseMoveCallback = mouseCallback;
  280. }
  281. b3MouseMoveCallback EGLOpenGLWindow::getMouseMoveCallback()
  282. {
  283. return m_data->m_mouseMoveCallback;
  284. }
  285. void EGLOpenGLWindow::setMouseButtonCallback(
  286. b3MouseButtonCallback mouseCallback)
  287. {
  288. m_data->m_mouseButtonCallback = mouseCallback;
  289. }
  290. b3MouseButtonCallback EGLOpenGLWindow::getMouseButtonCallback()
  291. {
  292. return m_data->m_mouseButtonCallback;
  293. }
  294. void EGLOpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback)
  295. {
  296. m_data->m_resizeCallback = resizeCallback;
  297. }
  298. b3ResizeCallback EGLOpenGLWindow::getResizeCallback()
  299. {
  300. return m_data->m_resizeCallback;
  301. }
  302. void EGLOpenGLWindow::setWheelCallback(b3WheelCallback wheelCallback)
  303. {
  304. m_data->m_wheelCallback = wheelCallback;
  305. }
  306. b3WheelCallback EGLOpenGLWindow::getWheelCallback()
  307. {
  308. return m_data->m_wheelCallback;
  309. }
  310. void EGLOpenGLWindow::setKeyboardCallback(b3KeyboardCallback keyboardCallback)
  311. {
  312. m_data->m_keyboardCallback = keyboardCallback;
  313. }
  314. b3KeyboardCallback EGLOpenGLWindow::getKeyboardCallback()
  315. {
  316. return m_data->m_keyboardCallback;
  317. }
  318. void EGLOpenGLWindow::setRenderCallback(b3RenderCallback renderCallback) {}
  319. void EGLOpenGLWindow::setWindowTitle(const char* title) {}
  320. float EGLOpenGLWindow::getRetinaScale() const { return 1.f; }
  321. void EGLOpenGLWindow::setAllowRetina(bool allow) {}
  322. int EGLOpenGLWindow::getWidth() const { return m_data->m_windowWidth; }
  323. int EGLOpenGLWindow::getHeight() const { return m_data->m_windowHeight; }
  324. int EGLOpenGLWindow::fileOpenDialog(char* fileName, int maxFileNameLength)
  325. {
  326. return 0;
  327. }
  328. #endif // BT_USE_EGL