[Bf-blender-cvs] [bb65f49005e] master: Linux: update EGL context code to fully work, including offscreen rendering

Christian Rauch noreply at git.blender.org
Tue Jan 28 11:00:10 CET 2020


Commit: bb65f49005ed17806bce2b048d37903cc1342d27
Author: Christian Rauch
Date:   Tue Jan 28 10:32:29 2020 +0100
Branches: master
https://developer.blender.org/rBbb65f49005ed17806bce2b048d37903cc1342d27

Linux: update EGL context code to fully work, including offscreen rendering

This is a step towards Wayland and headless rendering support, using EGL
instead of GLX. The EGL backend is not enabled by default, it can be tested
using WITH_GL_EGL=ON.

Differential Revision: https://developer.blender.org/D6585

===================================================================

M	CMakeLists.txt
M	intern/ghost/intern/GHOST_ContextEGL.cpp
M	intern/ghost/intern/GHOST_ContextEGL.h
M	intern/ghost/intern/GHOST_EventPrinter.cpp
M	intern/ghost/intern/GHOST_SystemX11.cpp
M	intern/ghost/intern/GHOST_WindowX11.cpp

===================================================================

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bbb528607c8..17e4ec23ed9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -978,7 +978,7 @@ if(WITH_GL_PROFILE_ES20)
       )
     endif()
 
-    list(APPEND BLENDER_GL_LIBRARIES OPENGLES_LIBRARY)
+    list(APPEND BLENDER_GL_LIBRARIES "${OPENGLES_LIBRARY}")
 
   else()
     set(OPENGLES_LIBRARY "" CACHE FILEPATH "OpenGL ES 2.0 library file")
@@ -1038,7 +1038,10 @@ else()
 endif()
 
 if(WITH_GL_EGL)
-  list(APPEND GL_DEFINITIONS -DWITH_GL_EGL)
+  find_package(OpenGL REQUIRED EGL)
+  list(APPEND BLENDER_GL_LIBRARIES OpenGL::EGL)
+
+  list(APPEND GL_DEFINITIONS -DWITH_GL_EGL -DGLEW_EGL -DGLEW_INC_EGL)
 
   if(WITH_SYSTEM_GLES)
     if(NOT OPENGLES_EGL_LIBRARY)
@@ -1048,7 +1051,7 @@ if(WITH_GL_EGL)
       )
     endif()
 
-    list(APPEND BLENDER_GL_LIBRARIES OPENGLES_EGL_LIBRARY)
+    list(APPEND BLENDER_GL_LIBRARIES ${OPENGLES_EGL_LIBRARY})
 
   else()
     set(OPENGLES_EGL_LIBRARY "" CACHE FILEPATH "EGL library file")
@@ -1088,10 +1091,6 @@ else()
   list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
 endif()
 
-if(WITH_GL_EGL)
-  list(APPEND GL_DEFINITIONS -DWITH_EGL)
-endif()
-
 #-----------------------------------------------------------------------------
 # Configure OpenMP.
 if(WITH_OPENMP)
@@ -1163,10 +1162,6 @@ else()
       list(APPEND GL_DEFINITIONS -DGL_ES_VERSION_1_0=0 -DGL_ES_VERSION_CL_1_1=0 -DGL_ES_VERSION_CM_1_1=0)
     endif()
 
-    if(WITH_GL_EGL)
-      list(APPEND GL_DEFINITIONS -DGLEW_INC_EGL)
-    endif()
-
     set(BLENDER_GLEW_LIBRARIES extern_glew_es bf_intern_glew_mx)
 
   else()
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
index d4eeda2a9ef..e072f0823f3 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -37,7 +37,7 @@
   case code: \
     return #code;
 
-static const char *get_egl_error_enum_string(EGLenum error)
+static const char *get_egl_error_enum_string(EGLint error)
 {
   switch (error) {
     CASE_CODE_RETURN_STR(EGL_SUCCESS)
@@ -60,7 +60,7 @@ static const char *get_egl_error_enum_string(EGLenum error)
   }
 }
 
-static const char *get_egl_error_message_string(EGLenum error)
+static const char *get_egl_error_message_string(EGLint error)
 {
   switch (error) {
     case EGL_SUCCESS:
@@ -129,7 +129,7 @@ static const char *get_egl_error_message_string(EGLenum error)
 static bool egl_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL)
 {
   if (!result) {
-    EGLenum error = eglGetError();
+    const EGLint error = eglGetError();
 
     const char *code = get_egl_error_enum_string(error);
     const char *msg = get_egl_error_message_string(error);
@@ -140,13 +140,13 @@ static bool egl_chk(bool result, const char *file = NULL, int line = 0, const ch
             file,
             line,
             text,
-            error,
+            static_cast<unsigned int>(error),
             code ? code : "<Unknown>",
             msg ? msg : "<Unknown>");
 #else
     fprintf(stderr,
             "EGL Error (0x%04X): %s: %s\n",
-            error,
+            static_cast<unsigned int>(error),
             code ? code : "<Unknown>",
             msg ? msg : "<Unknown>");
 #endif
@@ -225,8 +225,6 @@ GHOST_ContextEGL::GHOST_ContextEGL(bool stereoVisual,
           choose_api(api, s_gl_sharedContext, s_gles_sharedContext, s_vg_sharedContext)),
       m_sharedCount(choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount))
 {
-  assert(m_nativeWindow != 0);
-  assert(m_nativeDisplay != NULL);
 }
 
 GHOST_ContextEGL::~GHOST_ContextEGL()
@@ -253,8 +251,6 @@ GHOST_ContextEGL::~GHOST_ContextEGL()
 
     if (m_surface != EGL_NO_SURFACE)
       EGL_CHK(::eglDestroySurface(m_display, m_surface));
-
-    EGL_CHK(::eglTerminate(m_display));
   }
 }
 
@@ -307,18 +303,35 @@ GHOST_TSuccess GHOST_ContextEGL::releaseDrawingContext()
   if (m_display) {
     bindAPI(m_api);
 
-    return EGL_CHK(::eglMakeCurrent(m_display, None, None, NULL)) ? GHOST_kSuccess :
-                                                                    GHOST_kFailure;
+    return EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) ?
+               GHOST_kSuccess :
+               GHOST_kFailure;
   }
   else {
     return GHOST_kFailure;
   }
 }
 
-void GHOST_ContextEGL::initContextEGLEW()
+bool GHOST_ContextEGL::initContextEGLEW()
 {
-  if (GLEW_CHK(eglewInit(m_display)) != GLEW_OK)
+  /* We have to manually get this function before we can call eglewInit, since
+   * it requires a display argument. glewInit() does the same, but we only want
+   * to intialize EGLEW here. */
+  eglGetDisplay = (PFNEGLGETDISPLAYPROC)eglGetProcAddress("eglGetDisplay");
+  if (eglGetDisplay == NULL) {
+    return false;
+  }
+
+  if (!EGL_CHK((m_display = ::eglGetDisplay(m_nativeDisplay)) != EGL_NO_DISPLAY)) {
+    return false;
+  }
+
+  if (GLEW_CHK(eglewInit(m_display)) != GLEW_OK) {
     fprintf(stderr, "Warning! EGLEW failed to initialize properly.\n");
+    return false;
+  }
+
+  return true;
 }
 
 static const std::string &api_string(EGLenum api)
@@ -341,6 +354,10 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
 
   m_stereoVisual = false;  // It doesn't matter what the Window wants.
 
+  if (!initContextEGLEW()) {
+    return GHOST_kFailure;
+  }
+
 #ifdef WITH_GL_ANGLE
   // d3dcompiler_XX.dll needs to be loaded before ANGLE will work
   if (s_d3dcompiler == NULL) {
@@ -360,11 +377,6 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
   EGLSurface prev_read = eglGetCurrentSurface(EGL_READ);
   EGLContext prev_context = eglGetCurrentContext();
 
-  m_display = ::eglGetDisplay(m_nativeDisplay);
-
-  if (!EGL_CHK(m_display != EGL_NO_DISPLAY))
-    return GHOST_kFailure;
-
   EGLint egl_major, egl_minor;
 
   if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor)))
@@ -375,8 +387,6 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
   if (!EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)))
     goto error;
 
-  initContextEGLEW();
-
   if (!bindAPI(m_api))
     goto error;
 
@@ -419,6 +429,10 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
               egl_minor);
     }
   }
+  else {
+    attrib_list.push_back(EGL_RENDERABLE_TYPE);
+    attrib_list.push_back(EGL_OPENGL_BIT);
+  }
 
   attrib_list.push_back(EGL_RED_SIZE);
   attrib_list.push_back(8);
@@ -434,6 +448,12 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
   attrib_list.push_back(8);
 #endif
 
+  if (m_nativeWindow == 0) {
+    // off-screen surface
+    attrib_list.push_back(EGL_SURFACE_TYPE);
+    attrib_list.push_back(EGL_PBUFFER_BIT);
+  }
+
   attrib_list.push_back(EGL_NONE);
 
   EGLConfig config;
@@ -445,7 +465,19 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
   if (num_config != 1)  // num_config should be exactly 1
     goto error;
 
-  m_surface = ::eglCreateWindowSurface(m_display, config, m_nativeWindow, NULL);
+  if (m_nativeWindow != 0) {
+    m_surface = ::eglCreateWindowSurface(m_display, config, m_nativeWindow, NULL);
+  }
+  else {
+    static const EGLint pb_attrib_list[] = {
+        EGL_WIDTH,
+        1,
+        EGL_HEIGHT,
+        1,
+        EGL_NONE,
+    };
+    m_surface = ::eglCreatePbufferSurface(m_display, config, pb_attrib_list);
+  }
 
   if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
     goto error;
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
index cd6b0c959b7..da5ca7ef93f 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.h
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -102,7 +102,7 @@ class GHOST_ContextEGL : public GHOST_Context {
   GHOST_TSuccess getSwapInterval(int &intervalOut);
 
  private:
-  void initContextEGLEW();
+  bool initContextEGLEW();
 
   EGLNativeDisplayType m_nativeDisplay;
   EGLNativeWindowType m_nativeWindow;
diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp
index 119c9f28223..e459da39d14 100644
--- a/intern/ghost/intern/GHOST_EventPrinter.cpp
+++ b/intern/ghost/intern/GHOST_EventPrinter.cpp
@@ -39,7 +39,7 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event)
   if (event->getType() == GHOST_kEventWindowUpdate)
     return false;
 
-  std::cout << "\nGHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime()
+  std::cout << "GHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime()
             << ", type: ";
   switch (event->getType()) {
     case GHOST_kEventUnknown:
@@ -164,6 +164,8 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event)
       break;
   }
 
+  std::cout << std::endl;
+
   std::cout.flush();
 
   return handled;
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index f15641352e0..4c77dbd7abe 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -50,6 +50,7 @@
 
 #if defined(WITH_GL_EGL)
 #  include "GHOST_ContextEGL.h"
+#  include <EGL/eglext.h>
 #else
 #  include "GHOST_ContextGLX.h"
 #endif
@@ -243,6 +244,10 @@ GHOST_SystemX11::~GHOST_SystemX11()
   clearXInputDevices();
 #endif /* WITH_X11_XINPUT */
 
+#ifdef WITH_GL_EGL
+  ::eglTerminate(::eglGetDisplay(m_display));
+#endif
+
   if (m_xkb_descr) {
     XkbFreeKeyboard(m_xkb_descr, XkbAllComponentsMask, true);
   }
@@ -406,17 +411,39 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext()
 #endif
 
   const int profile_mask =
-#if defined(WITH_GL_PROFILE_CORE)
+#ifdef WITH_GL_EGL
+#  if defined(WITH_GL_PROFILE_CORE)
+      EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
+#  elif defined(WITH_GL_PROFILE_COMPAT)
+      EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
+#  else
+#    error  // must specify either core or compat at build time
+#  endif
+#else
+#  if defined(WITH_GL_PROFILE_CORE)
       GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
-#elif defined(WITH_GL_PROFILE_COMPAT)
+#  elif defined(WITH_GL_PROFILE_COMPAT)
       GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
-#else
-#  error  // must specify either core or compat at build time
+#  else
+#    error  // must specify either core or compat at build time


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list