Radium Engine  1.5.20
Loading...
Searching...
No Matches
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
14namespace Ra {
15namespace Headless {
16using namespace gl;
17using namespace glbinding;
18
19static 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
33struct EglOpenGLContext::ContextEGL {
34 EGLDisplay m_eglDpy;
35 EGLSurface m_eglSurf;
36 EGLContext m_eglCtx;
37};
38
39EglOpenGLContext::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}
122EglOpenGLContext::~EglOpenGLContext() {
123 eglTerminate( m_eglContext->m_eglDpy );
124}
125void 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
134void 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
140bool EglOpenGLContext::isValid() const {
141 return m_eglContext->m_eglCtx != EGL_NO_CONTEXT;
142}
143
144std::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
T abort(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
T str(T... args)