EGL without X11

Hello,
I’m trying to use my TX2 to do some rendering, but with no display attached I can save some resources by not running X11. I’m trying to create an EGL context by following this example: https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/

I’ve modified the code in the blog post to add some error checking, my code follows:

#include <EGL/egl.h>
#include <stdio.h>

  static const EGLint configAttribs[] = {
          EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
          EGL_BLUE_SIZE, 8,
          EGL_GREEN_SIZE, 8,
          EGL_RED_SIZE, 8,
          EGL_DEPTH_SIZE, 8,
          EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
          EGL_NONE
  };    

#define pbufferWidth 9
#define pbufferHeight 9

static const EGLint pbufferAttribs[] = {
      EGL_WIDTH, pbufferWidth,
      EGL_HEIGHT, pbufferHeight,
      EGL_NONE,
};

int main(int argc, char *argv[])
{
  // 1. Initialize EGL
  EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);

  if (eglDpy == EGL_NO_DISPLAY) {
        fprintf(stderr, "Failed to get EGL display\n");
        return -1;
  }

  EGLint major, minor;

  if (eglInitialize(eglDpy, &major, &minor) == EGL_FALSE) {
        fprintf(stderr, "Failed to initialize EGL display: %x\n", eglGetError());
        return -1;
  }

  // 2. Select an appropriate configuration
  EGLint numConfigs;
  EGLConfig eglCfg;

  eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);
  if (numConfigs != 1) {
      fprintf(stderr, "Failed to choose exactly 1 config, chose %d\n", numConfigs);
      return -1;
  }

  // 3. Create a surface
  EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg, 
                                               pbufferAttribs);

  // 4. Bind the API
  eglBindAPI(EGL_OPENGL_API);

  // 5. Create a context and make it current
  EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, 
                                       NULL);

  eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx);

  // from now on use your OpenGL context

  // 6. Terminate EGL when finished
  eglTerminate(eglDpy);
  return 0;
}

When I run this code on my TX2 (without X11 running…), it fails at ‘eglInitialize’. Is there something else I need to do, or some other driver that must be loaded?

Thanks.

Ok, so it turns out i had to manually pick a display with eglQueryDevicesEXT and eglGetPlatformDisplayEXT.

So now my rendering engine can run without X11! hooray!

One more question: does argus require X11? when i try to run it without X11 running i get this:

(Argus) Error NotSupported: Failed to initialize EGLDisplay (in src/eglutils/EGLUtils.cpp, function getDefaultDisplay(), line 75)
(Argus) Error NotSupported: Failed to get default display (in src/api/OutputStreamImpl.cpp, function initialize(), line 80)
(Argus) Error NotSupported:  (propagating from src/api/CaptureSessionImpl.cpp, function createOutputStreamInternal(), line 565)

Alright, solved my own problem. I needed to set the display in my IOutputStreamSettings object using the setEGLDisplay member. When i set it to the same display I was rendering with, everything works fine!

Leaving here for posterity.

1 Like

Hi wdouglass,

Could you share your final sample code? It could benefit other users who would like to use non-X11 window system.

Sure! The modified version of the above sample (again, derived from the blog post linked above) is this:

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdio.h>

  static const EGLint configAttribs[] = {
          EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
          EGL_BLUE_SIZE, 8,
          EGL_GREEN_SIZE, 8,
          EGL_RED_SIZE, 8,
          EGL_DEPTH_SIZE, 8,
          EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
          EGL_NONE
  };    

#define pbufferWidth 9
#define pbufferHeight 9

static const EGLint pbufferAttribs[] = {
      EGL_WIDTH, pbufferWidth,
      EGL_HEIGHT, pbufferHeight,
      EGL_NONE,
};

int main(int argc, char *argv[])
{


  static const int MAX_DEVICES = 4;
  EGLDeviceEXT eglDevs[MAX_DEVICES];
  EGLint numDevices;
  
  PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =
      (PFNEGLQUERYDEVICESEXTPROC)
      eglGetProcAddress("eglQueryDevicesEXT");
  
  eglQueryDevicesEXT(MAX_DEVICES, eglDevs, &numDevices);

  printf("Detected %d devices\n", numDevices);

  
  PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
    (PFNEGLGETPLATFORMDISPLAYEXTPROC)
    eglGetProcAddress("eglGetPlatformDisplayEXT");

  EGLDisplay eglDpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, 
                                    eglDevs[0], 0);
  
  // 1. Initialize EGL

  if (eglDpy == EGL_NO_DISPLAY) {
        fprintf(stderr, "Failed to get EGL display\n");
        return -1;
  }

  EGLint major, minor;

  if (eglInitialize(eglDpy, &major, &minor) == EGL_FALSE) {
        fprintf(stderr, "Failed to initialize EGL display: %x\n", eglGetError());
        return -1;
  }

  // 2. Select an appropriate configuration
  EGLint numConfigs;
  EGLConfig eglCfg;

  eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);
  if (numConfigs != 1) {
      fprintf(stderr, "Failed to choose exactly 1 config, chose %d\n", numConfigs);
      return -1;
  }

  // 3. Create a surface
  EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg, 
                                               pbufferAttribs);

  // 4. Bind the API
  eglBindAPI(EGL_OPENGL_API);

  // 5. Create a context and make it current
  EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, 
                                       NULL);

  eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx);

  // from now on use your OpenGL context

  // 6. Terminate EGL when finished
  eglTerminate(eglDpy);
  return 0;
}

and the initialization of the IOutputStreamSettings object looks like this (where display is an EGLDisplay object created using the same method above…)

ioss->setPixelFormat(PIXEL_FMT_YCbCr_420_888);
ioss->setResolution(Size2D<uint32_t>(width, height));
ioss->setEGLDisplay(display);
1 Like

Hello everywhere.

By following the above example, I created an EGL Display object in a non X11 windows system which I set to Argus::OuputStream object. The problem is that when I query the EGL stream for new frames I am getting segmentation fault

EGLint streamState = 0;
if (!eglQueryStreamKHR(iStream->getEGLDisplay(), iStream->getEGLStream(), EGL_STREAM_STATE_KHR, &streamState))
    std::cout << "eglQueryStreamKHR EGL_STREAM_STATE_KHR failed" << std::endl;

Is there anything else I must do in order to query the EGL stream ?

Hi dimitris_akridas,
Please share a test code so that we can build, run and reproduce the issue. It should be efficient to make a patch based on either tegra_multimedia_api sample instead of making a whole new test code.

Hello DaneLLL.

Just patch the main.cpp of the cudaHistogram sample with the following. For simplicity I didn’t create the EGL display but let Argus to use the default. Maybe this is more suitable to a standalone post.

32a33
> #include "EGLGlobal.h"
125a127,138
>         EGLint streamState = 0;
>         while (streamState != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR && streamState != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR)
>         {
>             if (!eglQueryStreamKHR(iStream->getEGLDisplay(), iStream->getEGLStream(), EGL_STREAM_STATE_KHR, &streamState))
>                 printf("eglQueryStreamKHR EGL_STREAM_STATE_KHR failed\n");
>         }
> 
>         if (streamState == EGL_STREAM_STATE_DISCONNECTED_KHR)
>         {
>             printf("EGL Stream state: DISCONNECTED\n");
>             break;
>         }

Hi,

Yes. Please make a new post and share steps. It seems the patch cannot be applied by ‘patch -p1 < xxx.patch’. Please give more detail. Do you run r32.1? Also how you disable Ubuntu desktop and X11. Thanks.

Hello.

I made a new post that isolates the problem from this thread. I though that the problem with the segmentation fault was due to the disabled X11 but then I realized that it happens even with the default EGLDisplay of Argus and the X11 enabled. Sorry for this.

Hi wdouglass,

I just wanted to thank you for sharing this, it has allowed me to do OpenGL based calculations on a HPC system that is not running an X server. In case anyone might find it useful, I’ve made a small ctypes based python module from this:

Thanks!
Jori

2 Likes

Also , Sometime’s it gives compilation errors and includes Xlib.h in egl_plaform.h , Defining the definition EGL_NO_X11 helps resolving it.

for cmake : TARGET_COMPILE_DEFINITIONS(${TARGET_NAME} PUBLIC -DEGL_NO_X11)