NativeWindowEglFbdev.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Core/NativeWindowEglFbdev.h>
  6. #include <AnKi/Util/Vector.h>
  7. #include <AnKi/Util/Array.h>
  8. #include <AnKi/Util/StdTypes.h>
  9. namespace anki
  10. {
  11. void NativeWindowImpl::create(NativeWindowInitInfo& init)
  12. {
  13. // Create window
  14. //
  15. fbwin = (fbdev_window*)malloc(sizeof(fbdev_window));
  16. if(fbwin == NULL)
  17. {
  18. throw ANKI_EXCEPTION("malloc() failed");
  19. }
  20. fbwin->width = init.width;
  21. fbwin->height = init.height;
  22. // EGL init
  23. //
  24. display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  25. if(display == EGL_NO_DISPLAY)
  26. {
  27. throw ANKI_EXCEPTION("Failed to create display");
  28. }
  29. int major, minor;
  30. if(eglInitialize(display, &major, &minor) == EGL_FALSE)
  31. {
  32. throw ANKI_EXCEPTION("Failed to initialize EGL");
  33. }
  34. int maxConfigs;
  35. if(eglGetConfigs(display, NULL, 0, &maxConfigs) == EGL_FALSE)
  36. {
  37. throw ANKI_EXCEPTION("Failed to query EGL configs");
  38. }
  39. if(maxConfigs < 1)
  40. {
  41. throw ANKI_EXCEPTION("Error in number of configs");
  42. }
  43. Vector<EGLConfig> configs(maxConfigs);
  44. Array<EGLint, 256> attribs;
  45. U attr = 0;
  46. attribs[attr++] = EGL_RENDERABLE_TYPE;
  47. attribs[attr++] = EGL_OPENGL_ES2_BIT;
  48. if(init.samplesCount > 1)
  49. {
  50. attribs[attr++] = EGL_SAMPLES;
  51. attribs[attr++] = init.samplesCount;
  52. }
  53. attribs[attr++] = EGL_RED_SIZE;
  54. attribs[attr++] = init.rgbaBits[0];
  55. attribs[attr++] = EGL_GREEN_SIZE;
  56. attribs[attr++] = init.rgbaBits[1];
  57. attribs[attr++] = EGL_BLUE_SIZE;
  58. attribs[attr++] = init.rgbaBits[2];
  59. attribs[attr++] = EGL_ALPHA_SIZE;
  60. attribs[attr++] = init.rgbaBits[3];
  61. attribs[attr++] = EGL_DEPTH_SIZE;
  62. attribs[attr++] = init.depthBits;
  63. attribs[attr++] = EGL_STENCIL_SIZE;
  64. attribs[attr++] = init.stencilBits;
  65. attribs[attr++] = EGL_NONE;
  66. EGLint configsCount;
  67. if(eglChooseConfig(display, &attribs[0], &configs[0], maxConfigs, &configsCount) == EGL_FALSE)
  68. {
  69. throw ANKI_EXCEPTION("Failed to query required EGL configs");
  70. }
  71. if(configsCount == 0)
  72. {
  73. throw ANKI_EXCEPTION("No matching EGL configs found");
  74. }
  75. EGLConfig config_ = nullptr;
  76. for(EGLint i = 0; i < configsCount; i++)
  77. {
  78. EGLint value;
  79. EGLConfig config = configs[i];
  80. // Use this to explicitly check that the EGL config has the
  81. // expected color depths
  82. eglGetConfigAttrib(display, config, EGL_RED_SIZE, &value);
  83. if(value != (EGLint)init.rgbaBits[0])
  84. {
  85. continue;
  86. }
  87. eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &value);
  88. if(value != (EGLint)init.rgbaBits[1])
  89. {
  90. continue;
  91. }
  92. eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &value);
  93. if(value != (EGLint)init.rgbaBits[2])
  94. {
  95. continue;
  96. }
  97. eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &value);
  98. if(value != (EGLint)init.rgbaBits[3])
  99. {
  100. continue;
  101. }
  102. eglGetConfigAttrib(display, config, EGL_SAMPLES, &value);
  103. if(value != (EGLint)init.samplesCount)
  104. {
  105. continue;
  106. }
  107. eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &value);
  108. if(value != (EGLint)init.depthBits)
  109. {
  110. continue;
  111. }
  112. eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &value);
  113. if(value != (EGLint)init.stencilBits)
  114. {
  115. continue;
  116. }
  117. // We found what we wanted
  118. config_ = config;
  119. break;
  120. }
  121. if(config_ == nullptr)
  122. {
  123. throw ANKI_EXCEPTION("Unable to find suitable EGL config");
  124. }
  125. // Surface
  126. //
  127. surface = eglCreateWindowSurface(display, config_, static_cast<EGLNativeWindowType>(fbwin), NULL);
  128. if(surface == EGL_NO_SURFACE)
  129. {
  130. throw ANKI_EXCEPTION("Cannot create surface");
  131. }
  132. // Context
  133. //
  134. EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
  135. context = eglCreateContext(display, config_, EGL_NO_CONTEXT, ctxAttribs);
  136. if(context == EGL_NO_CONTEXT)
  137. {
  138. throw ANKI_EXCEPTION("Cannot create context");
  139. }
  140. if(eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
  141. {
  142. throw ANKI_EXCEPTION("Cannot make the context current");
  143. }
  144. }
  145. void NativeWindowImpl::destroy()
  146. {
  147. // XXX
  148. }
  149. NativeWindow::~NativeWindow()
  150. {
  151. }
  152. void NativeWindow::init(NativeWindowInitInfo& initializer)
  153. {
  154. impl.reset(new NativeWindowImpl);
  155. impl->create(initializer);
  156. // Set the size after because the create may have changed it to something
  157. // more nice
  158. width = initializer.width;
  159. height = initializer.height;
  160. }
  161. void NativeWindow::destroy()
  162. {
  163. impl.reset();
  164. }
  165. void NativeWindow::swapBuffers()
  166. {
  167. ANKI_ASSERT(isCreated());
  168. if(eglSwapBuffers(impl->display, impl->surface) == EGL_FALSE)
  169. {
  170. throw ANKI_EXCEPTION("eglSwapBuffers() failed");
  171. }
  172. }
  173. } // end namespace anki