Loading [MathJax]/extensions/tex2jax.js
Radium Engine  1.5.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
EglOpenGLContext.cpp
1 #ifdef HEADLESS_HAS_EGL
2 # include <Headless/OpenGLContext/EglOpenGLContext.hpp>
3 
4 # include <glbinding-aux/ValidVersions.h>
5 # include <glbinding/glbinding.h>
6 # include <globjects/globjects.h>
7 
8 # include <iostream>
9 
10 // To prevent name collision on some systems between EGL and Eigen, those must be included last.
11 # include <EGL/egl.h>
12 # include <EGL/eglext.h>
13 
14 namespace Ra {
15 namespace Headless {
16 using namespace gl;
17 using namespace glbinding;
18 
19 static const EGLint configAttribs[] = { EGL_SURFACE_TYPE,
20  EGL_PBUFFER_BIT,
21  EGL_BLUE_SIZE,
22  8,
23  EGL_GREEN_SIZE,
24  8,
25  EGL_RED_SIZE,
26  8,
27  EGL_DEPTH_SIZE,
28  8,
29  EGL_RENDERABLE_TYPE,
30  EGL_OPENGL_BIT,
31  EGL_NONE };
32 
33 struct EglOpenGLContext::ContextEGL {
34  EGLDisplay m_eglDpy;
35  EGLSurface m_eglSurf;
36  EGLContext m_eglCtx;
37 };
38 
39 EglOpenGLContext::EglOpenGLContext( const glbinding::Version& glVersion,
40  const std::array<int, 2>& size ) :
41  OpenGLContext( glVersion, size ), m_eglContext { new ContextEGL } {
42  static const EGLint pbufferAttribs[] = {
43  EGL_WIDTH,
44  size[0], // not really needed, 1 should be OK
45  EGL_HEIGHT,
46  size[1], // not really needed, 1 should be OK
47  EGL_NONE,
48  };
49 
50  static const int MAX_DEVICES = 16;
51  EGLDeviceEXT eglDevs[MAX_DEVICES];
52  EGLint numDevices;
53 
54  // 1. Initialize EGL
55  PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =
56  (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress( "eglQueryDevicesEXT" );
57  eglQueryDevicesEXT( MAX_DEVICES, eglDevs, &numDevices );
58  if ( numDevices == 0 ) {
59  LOG( Core::Utils::logERROR ) << "EGL context creation : no devices available.";
60  std::abort();
61  }
62  PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
63  (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress( "eglGetPlatformDisplayEXT" );
64  m_eglContext->m_eglDpy = eglGetPlatformDisplayEXT( EGL_PLATFORM_DEVICE_EXT, eglDevs[0], 0 );
65 
66  EGLint major, minor;
67  if ( eglInitialize( m_eglContext->m_eglDpy, &major, &minor ) != EGL_TRUE ) {
68  LOG( Core::Utils::logERROR ) << "EGL context creation : Unable to initialize EGL ";
69  std::abort();
70  }
71 
72  // 2. Select an appropriate configuration
73  EGLint numConfigs;
74  EGLConfig eglCfg;
75  if ( eglChooseConfig( m_eglContext->m_eglDpy, configAttribs, &eglCfg, 1, &numConfigs ) !=
76  EGL_TRUE ) {
77  LOG( Core::Utils::logERROR ) << "EGL context creation : Unable to choose EGL config";
78  std::abort();
79  }
80 
81  // 3. Create a surface
82  // todo : do we really need a surface ???
83  // see https://developer.nvidia.com/blog/egl-eye-opengl-visualization-without-x-server/
84  m_eglContext->m_eglSurf =
85  eglCreatePbufferSurface( m_eglContext->m_eglDpy, eglCfg, pbufferAttribs );
86  if ( m_eglContext->m_eglSurf == EGL_NO_SURFACE ) {
87  LOG( Core::Utils::logERROR ) << "EGL context creation : Unable to create pbuffer";
88  std::abort();
89  }
90 
91  // 4. Bind the API
92  if ( eglBindAPI( EGL_OPENGL_API ) == EGL_FALSE ) {
93  LOG( Core::Utils::logERROR ) << "EGL context creation : Unable to bing OpenGL API";
94  std::abort();
95  }
96 
97  // 5. Create a context and make it current
98  EGLint contextAttribs[] = {
99  EGL_CONTEXT_MAJOR_VERSION,
100  glVersion.majorVersion(),
101  EGL_CONTEXT_MINOR_VERSION,
102  glVersion.minorVersion(),
103  EGL_CONTEXT_OPENGL_PROFILE_MASK,
104  EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
105  EGL_NONE,
106  };
107  m_eglContext->m_eglCtx =
108  eglCreateContext( m_eglContext->m_eglDpy, eglCfg, EGL_NO_CONTEXT, contextAttribs );
109  if ( m_eglContext->m_eglCtx == EGL_NO_CONTEXT ) {
110  LOG( Core::Utils::logERROR ) << "EGL context creation : Unable to get context";
111  std::abort();
112  }
113 
114  // Initialize globjects (internally initializes glbinding, and registers the current
115  // context)
116  eglMakeCurrent( m_eglContext->m_eglDpy,
117  m_eglContext->m_eglSurf,
118  m_eglContext->m_eglSurf,
119  m_eglContext->m_eglCtx );
120  globjects::init( []( const char* name ) { return eglGetProcAddress( name ); } );
121 }
122 EglOpenGLContext::~EglOpenGLContext() {
123  eglTerminate( m_eglContext->m_eglDpy );
124 }
125 void EglOpenGLContext::makeCurrent() const {
126  if ( m_eglContext->m_eglCtx ) {
127  eglMakeCurrent( m_eglContext->m_eglDpy,
128  m_eglContext->m_eglSurf,
129  m_eglContext->m_eglSurf,
130  m_eglContext->m_eglCtx );
131  }
132 }
133 
134 void EglOpenGLContext::doneCurrent() const {
135  if ( m_eglContext->m_eglCtx ) {
136  eglMakeCurrent( m_eglContext->m_eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
137  }
138 }
139 
140 bool EglOpenGLContext::isValid() const {
141  return m_eglContext->m_eglCtx != EGL_NO_CONTEXT;
142 }
143 
144 std::string EglOpenGLContext::getInfo() const {
145  auto generalInfo = OpenGLContext::getInfo();
146  std::stringstream infoText;
147  infoText << generalInfo << "Context provider : EGL\n";
148  return infoText.str();
149 }
150 
151 } // namespace Headless
152 } // namespace Ra
153 #endif
Definition: Cage.cpp:3