Missing GL version when using GLEW with EGL, OpenGL and ROS

I did encounter the following problem when using GLEW with EGL/OpenGL/ROS on the JTX2 and could not find any helpful solution so far. As I’m quite new to working with the JTX2, it may well be that the solution might be easy and apparent. Nonetheless, help would be appreciated.

The relevant code involved is listed in the following.

display.cpp

#include "rebope/display.hpp"

#include <iostream>

namespace rebope {

Display::Display(int pbufferWidth, int pbufferHeight, const std::string& title) {

  // Initialize EGL
  eglDpy_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  if(eglDpy_ == EGL_NO_DISPLAY) {
    std::cerr << "ERROR: EGL could not be initialized" << std::endl;
  }

  // Initialize an EGL display connection
  // EGLint major and minor could be added
  if (!eglInitialize(eglDpy_, 0, 0)) {
    std::cerr << "ERROR: Could not start EGL display connection" << std::endl;
  }

  // Bind the API to OpenGL
  eglBindAPI(EGL_OPENGL_API);

  // Specify the required configuration attributes
  EGLint configAttribs[] = {
    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
    EGL_CONFORMANT, EGL_OPENGL_BIT,
    EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
    EGL_LUMINANCE_SIZE, 0,
    EGL_RED_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_BLUE_SIZE, 8,
    EGL_ALPHA_SIZE, 8,
    EGL_DEPTH_SIZE, 8,
    EGL_LEVEL, 0,
    EGL_BUFFER_SIZE, 24,
    EGL_NONE
  };

  // Find a matching configuration
  EGLint numCfg;
  EGLConfig eglCfg;
  if(eglChooseConfig(eglDpy_, configAttribs, &eglCfg, 1, &numCfg) != EGL_TRUE) {
    std::cerr << "ERROR: Configuration selection failed" << std::endl;
  }

  // Specify buffer attributes
  EGLint pbufferAttribs[] = {
    EGL_WIDTH, pbufferWidth,
    EGL_HEIGHT, pbufferHeight,
    EGL_NONE
  };

  // Create a surface
  eglSurf_ = eglCreatePbufferSurface(eglDpy_, eglCfg, pbufferAttribs);
  if(eglSurf_ == EGL_NO_SURFACE) {
    std::cerr << "ERROR: Surface could not be created" << std::endl;
  }

  // Create context and make it current
  eglCtx_ = eglCreateContext(eglDpy_, eglCfg, EGL_NO_CONTEXT, NULL);
  if(eglMakeCurrent(eglDpy_, eglSurf_, eglSurf_, eglCtx_) != EGL_TRUE) {
    std::cerr << "ERROR: Display was not made current one" << std::endl;
  }

  // Initialize GLEW
  GLenum err = glewInit();
  if(err != GLEW_OK) {
    std::cerr << "ERROR: GLEW failed to initialize: " << err << std::endl;
  }

  // Initialize CUDA/OpenGL devices
  int deviceID = 0;
  cudaSetDevice(deviceID);
  cudaGLSetGLDevice(deviceID);

  // Remove triangles without visual artifacts (for performance reasons)
  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);
  glEnable(GL_DEPTH_TEST);

  // Bind buffer/Generate PBO
  glGenBuffers(1,&glb::pbo);
  glBindBuffer(GL_PIXEL_PACK_BUFFER,glb::pbo);
  glBufferData(GL_PIXEL_PACK_BUFFER, 4 * (pbufferWidth * pbufferHeight * sizeof(GLubyte)),NULL, GL_DYNAMIC_READ);

  // Register buffer to CUDA memory
  cudaGraphicsGLRegisterBuffer(&glb::pboRes, glb::pbo, cudaGraphicsRegisterFlagsReadOnly);

  // Map to CUDA
  cudaGraphicsMapResources(1, &glb::pboRes);

  // Unbind buffer
  glBindBuffer(GL_PIXEL_PACK_BUFFER,0);

  // Obtain pointer
  cudaGraphicsResourceGetMappedPointer(&glb::dptr, &glb::size, glb::pboRes);
}

void Display::clear(float r, float g, float b, float a) {
  glClearColor(r, g, b, a);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void Display::swapBuffer() {
  // Note: eglSwapBuffers() has no effect on a PbufferSurface
  if(eglSwapBuffers(eglDpy_,eglSurf_) != EGL_TRUE) {
    std::cerr << "ERROR: Buffer swap failed" << std::endl;
  }
}

Display::~Display() {

  // Unmap and unregister the graphics resource
  cudaGraphicsUnmapResources(1, &glb::pboRes);
  cudaGraphicsUnregisterResource(glb::pboRes);

  // Delete the PBO
  glDeleteBuffers(1, &glb::pbo);

  if(eglTerminate(eglDpy_) != EGL_TRUE) {
    std::cout << "ERROR: Improper EGL termination" << std::endl;
  }
}
}

display.hpp

#ifndef REBOPE_DISPLAY_H_
#define REBOPE_DISPLAY_H_

#include <EGL/egl.h>

#include <GL/glew.h>
#include <GL/glut.h>

#include <cuda_runtime.h>
#include <cuda_gl_interop.h>

#include <string>

#include "rebope/global.hpp"

namespace rebope {

class Display {
 public:
  Display(int pbufferWidth, int pbufferHeight, const std::string& title);

  void clear(float r, float g, float b, float a);

  void swapBuffer();

  virtual ~Display();

 protected:
 private:
  void operator=(const Display& display) {}

  Display(const Display& display) {}

  // Private variables for rendering
  EGLDisplay eglDpy_;
  EGLSurface eglSurf_;
  EGLContext eglCtx_;

};
}
#endif

Using this approach on a normal laptop with Ubuntu 16.04 works just fine. However, running the same part of the code on the JTX2 generates an error at…

// Initialize GLEW
  GLenum err = glewInit();
  if(err != GLEW_OK) {
    std::cerr << "ERROR: GLEW failed to initialize: " << err << std::endl;
  }

…with the error code “Missing GL version”. However, OpenGL should presumably already be available on the JTX2? Hence, I’m struggling to figure out the actual problem as well as an appropriate solution to fix it (even after an extended internet search). Suggestions would be very much appreciated!

Hi,

Jetson use Nvidia customized GL/GLES.

Please install Multimedia API package via JetPack and copy the EGL and GLES2, GLES3, KHR headers from “/home/nvidia/tegra_multimedia_api/include” to “/usr/include”.

We have several sample to demonstrate GL and GLES:
/home/nvidia/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGL
/home/nvidia/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGLES

Thanks.

Said and done. Just to be safe, the device has been flashed again and JetPack 3.1 was used/installed. However, the Multimedia API is located/installed at “/home/ubuntu/tegra_multimedia_api” instead of “/home/nvidia/tegra_multimedia_api” (which should not make a difference).

All headers located in “/usr/include/{EGL,GLES2,GLES3,KHR}” have been substituted with the headers from “/home/ubuntu/tegra_multimedia_api/include/{EGL,GLES2,GLES3,KHR}” with the same names. All other headers have been left unchanged.

Compiling everything with “catkin make” works flawlessly, but the error at runtime “missing GL version” persists so far.

ubuntu@tegra-ubuntu:/usr/lib$ roslaunch ~/catkin_ws/src/rebope/launch/jetson.launch 
... logging to /home/ubuntu/.ros/log/9e386922-a8f7-11e7-97ef-6c626d35ac1a/roslaunch-tegra-ubuntu-12550.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://10.42.0.201:46479/

SUMMARY
========

PARAMETERS
 * /rebope_jetson/rebope/alpha_init: 0.1
 * /rebope_jetson/rebope/beta_init: -0.3
 * /rebope_jetson/rebope/camera_image: /image_undistort/...
 * /rebope_jetson/rebope/gamma_init: 3.0
 * /rebope_jetson/rebope/object_file: /home/ubuntu/catk...
 * /rebope_jetson/rebope/shader_files: /home/ubuntu/catk...
 * /rebope_jetson/rebope/texture_file: /home/ubuntu/catk...
 * /rebope_jetson/rebope/x_init: 0
 * /rebope_jetson/rebope/y_init: 0.05
 * /rebope_jetson/rebope/z_init: 1.2
 * /rosdistro: kinetic
 * /rosversion: 1.12.7

NODES
  /rebope_jetson/
    rebope (rebope/rebope)

ROS_MASTER_URI=http://10.42.0.1:11311

core service [/rosout] found
process[rebope_jetson/rebope-1]: started with pid [12559]
ERROR: GLEW failed to initialize (error code: 1)
[rebope_jetson/rebope-1] process has died [pid 12559, exit code -11, cmd /home/ubuntu/catkin_ws/devel/lib/rebope/rebope camera:=/rebope_system/output/image camera_info:=/rebope_system/output/camera_info __name:=rebope __log:=/home/ubuntu/.ros/log/9e386922-a8f7-11e7-97ef-6c626d35ac1a/rebope_jetson-rebope-1.log].
log file: /home/ubuntu/.ros/log/9e386922-a8f7-11e7-97ef-6c626d35ac1a/rebope_jetson-rebope-1*.log
all processes on machine have died, roslaunch will exit
shutting down processing monitor...
... shutting down processing monitor complete
done

The error still originates from the previously presented code segment. Note: No display is connected to the JTX2 and everything is supposed to be rendered off-screen and without an X server (as in https://devblogs.nvidia.com/parallelforall/egl-eye-opengl-visualization-without-x-server/ ).

roslaunch-tegra-ubuntu-12550.log (12.9 KB)

I see a mention of a log. You might want to attach that.

Fair enough. The first log “/home/ubuntu/.ros/log/9e386922-a8f7-11e7-97ef-6c626d35ac1a/roslaunch-tegra-ubuntu-12550.log” has been attached. The second one “/home/ubuntu/.ros/log/9e386922-a8f7-11e7-97ef-6c626d35ac1a/rebope_jetson-rebope-1*.log” does not exist as ROS crashes immediately/within less than five seconds.

The only real information seems to be the error code 1 “missing GL version” from glewInit().

About all it says is the process died :( Does your system say the NVIDIA libraries are ok? Use:

sha1sum -c /etc/nv_tegra_release

Also, does “glxgears” work? This is in package mesa-utils.

Libraries seem to be OK (as expected).

ubuntu@tegra-ubuntu:~$ sha1sum -c /etc/nv_tegra_release 
/usr/lib/aarch64-linux-gnu/libv4l/plugins/libv4l2_nvvideocodec.so: OK
/usr/lib/aarch64-linux-gnu/libv4l/plugins/libv4l2_nvvidconv.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvomx.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnveglstreamproducer.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtx_helper.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvddk_vic.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libglx.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libargus_socketserver.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvddk_2d_v2.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvwinsys.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libargus.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvexif.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvdc.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvavp.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtestresults.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libargus_socketclient.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm_utils.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvfnet.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvll.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcameratools.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvapputil.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnveglstream_camconsumer.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvrm.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcam_imageencoder.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvparser.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtvmr.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvrm_gpu.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvtnr.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcamerautils.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvidia-egl-wayland.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvfnetstoredefog.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvodm_imager.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_utils.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcolorutil.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_video.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmmlite_image.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm_contentpipe.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvimp.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvos.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvrm_graphics.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmedia.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvfnetstorehdfx.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvomxilclient.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvcamlog.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvmm_parser.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libscf.so: OK
/usr/lib/aarch64-linux-gnu/tegra/libnvosd.so: OK
/usr/lib/xorg/modules/drivers/nvidia_drv.so: OK
/usr/lib/xorg/modules/extensions/libglx.so: OK

Only things done after flashing is applying the following patches/installs:

Mesa-utils have already been installed as can be seen in the following.

ubuntu@tegra-ubuntu:~$ sudo apt-get install mesa-utils
[sudo] password for ubuntu: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
mesa-utils is already the newest version (8.3.0-1).
The following packages were automatically installed and are no longer required:
  apt-clone archdetect-deb dmeventd dmraid dpkg-repack gir1.2-timezonemap-1.0
  gir1.2-xkl-1.0 grub-common kpartx kpartx-boot libappstream3
  libdebian-installer4 libdevmapper-event1.02.1 libdmraid1.0.0.rc16
  liblockfile-bin liblockfile1 liblvm2app2.2 liblvm2cmd2.02 libmircommon5
  libparted-fs-resize0 libreadline5 lockfile-progs lvm2 os-prober pmount
  python3-icu python3-pam rdate ubiquity-casper ubiquity-ubuntu-artwork
  ubuntu-core-launcher
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

However, “glxinfo” and “glxgears” showed the following from the very beginning. I was always unsure if this is supposed to be, but after all no display is connected (access via SSH).

ubuntu@tegra-ubuntu:~$ glxgears
Error: couldn't open display (null)
ubuntu@tegra-ubuntu:~$ glxinfo
Error: unable to open display

Normally anything using X11 (which is how the GPU driver works) requires a context (the DISPLAY) even if the context is a virtual desktop and not a real desktop. If you can get a monitor attached directly to the Jetson and get an X11 login, then testing glxgears should test the OpenGL on the Jetson. This does not mean you have to run your application with a monitor attached, but this might help debug. Since the sha1sum was ok it is likely that all of the OpenGL components are there (GLES might add to the problem), but without an actual local OpenGL app running it is hard to be certain.

I don’t know how your software uses the GPU, but it would also be useful to see if behavior changes when a real display is attached and running. Is there a possibility you can attach a real monitor for testing?

In many cases a virtual desktop would be required if the buffer on the Jetson itself is to act as a frame buffer (which in turn is what the GPU works with).

Hi,

Could you test our sample code to check if OpenGL run correctly?
/home/nvidia/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGL
/home/nvidia/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGLES

Thanks.

@AastaLLL: SimpleGL make works properly, but running it complains about no display being
found. SimpleGLES does not compile due to a redeclaration in “gl31.h” (original replaced by header in “/home/ubuntu/tegra_multimedia_api/include/GLES3/gl31.h”). I Did not have time yet to further look into this issue.

ubuntu@tegra-ubuntu:~/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGL$ sudo make
[sudo] password for ubuntu: 
/usr/local/cuda-8.0/bin/nvcc -ccbin g++ -I../../common/inc  -m64    -gencode arch=compute_53,code=sm_53 -gencode arch=compute_60,code=sm_60 -gencode arch=compute_62,code=sm_62 -gencode arch=compute_62,code=compute_62 -o simpleGL.o -c simpleGL.cu
/usr/local/cuda-8.0/bin/nvcc -ccbin g++   -m64      -gencode arch=compute_53,code=sm_53 -gencode arch=compute_60,code=sm_60 -gencode arch=compute_62,code=sm_62 -gencode arch=compute_62,code=compute_62 -o simpleGL simpleGL.o  -L/usr/lib/"nvidia-367" -lGL -lGLU -lX11 -lglut
mkdir -p ../../bin/aarch64/linux/release
cp simpleGL ../../bin/aarch64/linux/release
ubuntu@tegra-ubuntu:~/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGL$ ls
data  findgllib.mk  NsightEclipse.xml  simpleGL     simpleGL.o
doc   Makefile      readme.txt         simpleGL.cu
ubuntu@tegra-ubuntu:~/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGL$ ./simpleGL 
simpleGL (VBO) starting...

Invalid MIT-MAGIC-COOKIE-1 keyfreeglut (./simpleGL): failed to open display ':0'
ubuntu@tegra-ubuntu:~/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGL$ cd .. && cd simpleGLES
ubuntu@tegra-ubuntu:~/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGLES$ ls
data                  Makefile        NsightEclipse.xml  simpleGLES.o
findgleslib.mk        mesh.frag.glsl  readme.txt
graphics_interface.c  mesh.vert.glsl  simpleGLES.cu
ubuntu@tegra-ubuntu:~/NVIDIA_CUDA-8.0_Samples/2_Graphics/simpleGLES$ sudo make
/usr/local/cuda-8.0/bin/nvcc -ccbin g++ -I../../common/inc  -m64    -DUSE_CUDAINTEROP -DGRAPHICS_SETUP_EGL -DUSE_GLES -gencode arch=compute_53,code=sm_53 -gencode arch=compute_60,code=sm_60 -gencode arch=compute_62,code=sm_62 -gencode arch=compute_62,code=compute_62 -o simpleGLES.o -c simpleGLES.cu
../../common/inc/GL/glext.h(3821): error: invalid redeclaration of type name "PFNGLSHADERSOURCEPROC"
/usr/include/GLES3/gl31.h(483): here

1 error detected in the compilation of "/tmp/tmpxft_000009ee_00000000-11_simpleGLES.compute_62.cpp1.ii".
Makefile:283: recipe for target 'simpleGLES.o' failed
make: *** [simpleGLES.o] Error 2

@linuxdev: Yes, the possibility of connecting a display was possible as a bigger carrier board (e.g. developer board instead of J90-LC) is available. However, this might take some time to get hold of.

Hi,

Do you use JetPack3.1. If yes, please login with nvidia account.

Could you also try this command and run ./simpleGL again?

export DISPLAY=:0

To have a DISPLAY is mandatory for many applications, but realize that if you are in a hurry and don’t have a real hardware display you can install a virtual X server to pretend it is a real display. I suspect that in the end this will be mandatory anyway. One goal is to verify that your software can work with a real monitor attached, and only then add the complexity of making it work without a physical monitor. If the program won’t work with a real display you will have other debugging ahead…once things work with a monitor attached you can determine what kind of virtual environment is needed to replace the monitor.