hjimbens
Posts: 48
Joined: Fri May 24, 2013 9:05 am

Full screen OpenGL ES on Pi 4

Wed Jun 26, 2019 12:22 pm

The Pi 4 seems to be very exciting new hardware. I can't wait to see the performance improvements.

My application uses the legacy OpenGL ES driver in combination with Dispmanx. I compiled my application on a fresh Buster image and everything works fine on a Pi 3 B+. Unfortunately the application does not return from the eglCreateContext call on a Pi 4. I checked the hello_pi demo applications. They explicitly terminate on a Pi 4. When I remove the code that terminates those apps on a Pi 4, they also hang in eglCreateContext.

I have the following questions:
1. Can we fix this ourselves or do we have to wait until libbrcmEGL is fixed to work with the new GPU?
2. Does the legacy driver support OpenGL ES 3 or do we have to use the fkms driver for OpenGL ES 3?
3. With the fkms driver, is it possible to render videos to textures via the OpenMax API?

edit: changed title

hjimbens
Posts: 48
Joined: Fri May 24, 2013 9:05 am

Re: Full screen OpenGL ES on Pi 4

Thu Jun 27, 2019 8:31 am

In another thread https://www.raspberrypi.org/forums/view ... 0#p1486236, 6by9 explained
There is no firmware driver for the 3D hardware on the Pi4, therefore there will be no "legacy" OpenGLES driver.
.

In the past I used gbm (drm) with the fkms driver to use full screen OpenGL ES. I tried that code again. It works fine on a Pi3 B+ (except for a problem with decoding and displaying videos via a texture). The same code on a Pi 4 (using /dev/dri/card1 instead of /dev/dri/card0) shows output, but it does not always display one frame per vblank and it shows all kind of flickering artefacts.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6876
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Full screen OpenGL ES on Pi 4

Thu Jun 27, 2019 9:57 am

hjimbens wrote:
Thu Jun 27, 2019 8:31 am
In the past I used gbm (drm) with the fkms driver to use full screen OpenGL ES. I tried that code again. It works fine on a Pi3 B+ (except for a problem with decoding and displaying videos via a texture). The same code on a Pi 4 (using /dev/dri/card1 instead of /dev/dri/card0) shows output, but it does not always display one frame per vblank and it shows all kind of flickering artefacts.
If you're syncing your submits to vsyncs, then we've just addressed an issue due to a bringup workaround. You can get the fix with rpi-update (normal warnings apply over using rpi-update).
https://github.com/raspberrypi/firmware ... -505023770
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Tue Jul 02, 2019 7:05 am

After reading all of this.....

- is is possible to make OpenGL ES render to a dispmanx layer as in older RPis using new drivers?
- is it possible to use OpenGL ES without X?

If yes, how to do this?

A full screen sized glxgears run at 40 fps. I recompiled Atari800 emulator for RPi4 using "general Linux" configuration: it works, but only at 77% real Atari speed. It is simply too slow to use... There is a configuration for RPi3 using its OpenGL ES and it had no performance problems, but it simply doesn't work on 4 displaying an empty screen.

Another question: when using X with new drivers, /dev/fb0 is not available... I think it is hidden under an overlay... Of course I can always use ctrl-alt-f1 and then run framebuffer related code, but is there any way to temporarily hide the X layer and unhide fb?

hjimbens
Posts: 48
Joined: Fri May 24, 2013 9:05 am

Re: Full screen OpenGL ES on Pi 4

Tue Jul 02, 2019 8:47 am

pik33 wrote:
Tue Jul 02, 2019 7:05 am
- is is possible to make OpenGL ES render to a dispmanx layer as in older RPis using new drivers?
No, as far as I can tell that is not possible.
pik33 wrote:
Tue Jul 02, 2019 7:05 am
- is it possible to use OpenGL ES without X?
Yes, by using GBM/DRM. My application (RPi3-) application used OpenGL ES on Dispmanx, OpenMax to render videos to a texture, and CEF3 to render html to a texture. On the Pi4 I managed to get the OpenGL ES part working with GBM/DRM. However OpenMax does no longer cooperate with OpenGL ES so it appears I will have to use mmal for the videos (but I have not found any sample yet that plays videos with sound as opposed to just dumping frames as fast as possible) and CEF3 uses X11 internally and that does not seem to mix well with OpenGL ES on GBM/DRM.

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Thu Jul 11, 2019 8:44 am

Can you tell where I can find any example of using gbm/drm? I tried this: https://github.com/eyelash/tutorials/bl ... /drm-gbm.c; it compiles but then it crashed on this line:

Code: Select all

	drmModeConnector *connector = find_connector (resources);


which causes memory protection fault

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6876
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Full screen OpenGL ES on Pi 4

Thu Jul 11, 2019 9:42 am

Code: Select all

static void find_display_configuration () {
	drmModeRes *resources = drmModeGetResources (device);
	// find a connector
	drmModeConnector *connector = find_connector (resources);
It doesn't check that resources is not NULL before calling find_connector.
In your case it is NULL as you've opened the /dev/dri/card0 which is the 3D only device, whilst /dev/dri/card1 is the DRM render capable device.

hjimbens has already posted that information in this very thread
The same code on a Pi 4 (using /dev/dri/card1 instead of /dev/dri/card0) shows output,

kmscube is generally the simplest example of using GL without X. Again you need to invoke it as "kmscube -D /dev/dri/card1" to make it choose the right node.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Fri Jul 12, 2019 8:49 am

"kmscube -D /dev/dri/card1" works

drm-gbm.c after changing the device to /dev/dri/card1 now crashes in swap_buffers () function, in line

struct gbm_bo *bo = gbm_surface_lock_front_buffer (gbm_surface);

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6876
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Full screen OpenGL ES on Pi 4

Fri Jul 12, 2019 9:58 am

pik33 wrote:
Fri Jul 12, 2019 8:49 am
"kmscube -D /dev/dri/card1" works

drm-gbm.c after changing the device to /dev/dri/card1 now crashes in swap_buffers () function, in line

struct gbm_bo *bo = gbm_surface_lock_front_buffer (gbm_surface);
Sorry, I'm not about to debug a random third party app that may never have worked. Take kmscube as an example, or raise an issue on https://github.com/eyelash/tutorials/issues

Oh look https://github.com/eyelash/tutorials/issues/4
tutorials/drm-gbm.c

Line 47 in 30aaec4
drmModeRes *resources = drmModeGetResources (device);

See http://manpages.ubuntu.com/manpages/xen ... ces.3.html - function may return NULL, at which point a segfault will happen a few lines later.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Fri Jul 12, 2019 1:40 pm

I am trying to debug this myself... to get this simple example run, having kmscube opened as a reference.

So far I found that what returns NULL is this:

Code: Select all

egl_surface = eglCreateWindowSurface (display, config, gbm_surface, NULL);
and the error is 3009:

EGL_BAD_MATCH 0x3009
Arguments are inconsistent; for example, an otherwise valid
context requires buffers (e.g. depth or stencil) not allocated by
an otherwise valid surface.

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Sat Jul 13, 2019 2:31 pm

A success: it works. After a cleaning I will publish the code as it is much simpler than the kmscube (as it doesn't choose from a lot of options and it doesn't draw any cube).

The problem was: the EGL on RPi4 gives 24 configuration. You have to find a correct one (which kmscube does), while the original program uses the first available configuration, which doesn't match with GBM and causes an error #3009

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Sat Jul 13, 2019 3:12 pm

Here it is:

Code: Select all

// gcc -o drm-gbm drm-gbm-mod.c -ldrm -lgbm -lEGL -lGL -I/usr/include/libdrm

//----------------------------------------------------------------------
//--------  Trying to get OpenGL ES screen on RPi4 without X
//--------  based on drm-gbm https://github.com/eyelash/tutorials/blob/master/drm-gbm.c
//--------  and kmscube https://github.com/robclark/kmscube
//--------  [email protected]
//----------------------------------------------------------------------

#include <xf86drm.h>
#include <xf86drmMode.h>
#include <gbm.h>
#include <EGL/egl.h>
#include <GL/gl.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

#define EXIT(msg) { fputs (msg, stderr); exit (EXIT_FAILURE); }

// global variables declarations

static int device;
static drmModeRes *resources;
static drmModeConnector *connector;
static uint32_t connector_id;
static drmModeEncoder *encoder;
static drmModeModeInfo mode_info;
static drmModeCrtc *crtc;
static struct gbm_device *gbm_device;
static EGLDisplay display;
static EGLContext context;
static struct gbm_surface *gbm_surface;
static EGLSurface egl_surface;
       EGLConfig config;
       EGLint num_config;
       EGLint count=0;
       EGLConfig *configs;
       int config_index;
       int i;
       
static struct gbm_bo *previous_bo = NULL;
static uint32_t previous_fb;       

static EGLint attributes[] = {
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_ALPHA_SIZE, 0,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_NONE
		};

static const EGLint context_attribs[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

struct gbm_bo *bo;	
uint32_t handle;
uint32_t pitch;
int32_t fb;
uint64_t modifier;


static drmModeConnector *find_connector (drmModeRes *resources) {

for (i=0; i<resources->count_connectors; i++) {
  drmModeConnector *connector = drmModeGetConnector (device, resources->connectors[i]);
  if (connector->connection == DRM_MODE_CONNECTED) {return connector;}
  drmModeFreeConnector (connector);
  }
return NULL; // if no connector found
}

static drmModeEncoder *find_encoder (drmModeRes *resources, drmModeConnector *connector) {

if (connector->encoder_id) {return drmModeGetEncoder (device, connector->encoder_id);}
return NULL; // if no encoder found
}

static void swap_buffers () {

eglSwapBuffers (display, egl_surface);
bo = gbm_surface_lock_front_buffer (gbm_surface);
handle = gbm_bo_get_handle (bo).u32;
pitch = gbm_bo_get_stride (bo);
drmModeAddFB (device, mode_info.hdisplay, mode_info.vdisplay, 24, 32, pitch, handle, &fb);
drmModeSetCrtc (device, crtc->crtc_id, fb, 0, 0, &connector_id, 1, &mode_info);
if (previous_bo) {
  drmModeRmFB (device, previous_fb);
  gbm_surface_release_buffer (gbm_surface, previous_bo);
  }
previous_bo = bo;
previous_fb = fb;
}

static void draw (float progress) {

glClearColor (1.0f-progress, progress, 0.0, 1.0);
glClear (GL_COLOR_BUFFER_BIT);
swap_buffers ();
}

static int match_config_to_visual(EGLDisplay egl_display, EGLint visual_id, EGLConfig *configs, int count) {

EGLint id;
for (i = 0; i < count; ++i) {
  if (!eglGetConfigAttrib(egl_display, configs[i], EGL_NATIVE_VISUAL_ID,&id)) continue;
  if (id == visual_id) return i;
  }
return -1;
}

int main () {

device = open ("/dev/dri/card1", O_RDWR);
resources = drmModeGetResources (device);
connector = find_connector (resources);
connector_id = connector->connector_id;
mode_info = connector->modes[0];
encoder = find_encoder (resources, connector);
crtc = drmModeGetCrtc (device, encoder->crtc_id);
drmModeFreeEncoder (encoder);
drmModeFreeConnector (connector);
drmModeFreeResources (resources);
gbm_device = gbm_create_device (device);
gbm_surface = gbm_surface_create (gbm_device, mode_info.hdisplay, mode_info.vdisplay, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT|GBM_BO_USE_RENDERING);
display = eglGetDisplay (gbm_device);
eglInitialize (display, NULL ,NULL);
eglBindAPI (EGL_OPENGL_API);
eglGetConfigs(display, NULL, 0, &count);
configs = malloc(count * sizeof *configs);
eglChooseConfig (display, attributes, configs, count, &num_config);
config_index = match_config_to_visual(display,GBM_FORMAT_XRGB8888,configs,num_config);
context = eglCreateContext (display, configs[config_index], EGL_NO_CONTEXT, context_attribs);
egl_surface = eglCreateWindowSurface (display, configs[config_index], gbm_surface, NULL);
free(configs);
eglMakeCurrent (display, egl_surface, egl_surface, context);

for (i = 0; i < 600; i++) draw (i / 600.0f);
	
drmModeSetCrtc (device, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &connector_id, 1, &crtc->mode);
drmModeFreeCrtc (crtc);
if (previous_bo) {
  drmModeRmFB (device, previous_fb);
  gbm_surface_release_buffer (gbm_surface, previous_bo);
  }
eglDestroySurface (display, egl_surface);
gbm_surface_destroy (gbm_surface);
eglDestroyContext (display, context);
eglTerminate (display);
gbm_device_destroy (gbm_device);

close (device);
return 0;
}

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Sat Jul 13, 2019 8:28 pm

Another remark.

If kmscube - or the code I put here - is used from the secondary shell (ctrl-alt-f2), trying to switch to X by pressing ctrl-alt-f1 (X started from a command line on RPi booted to the shell) while one of these programs still works make the system to not respond to any input.

Kmscube program doesn't stop itself: after ctrl-alt-F1 it still works but cannot be stopped by the keyboard.
The simple code I made here stops itself after 600 frames and then the Pi stops responding to any input other than the power switch.

The keyboard doesn't even switch on/off a numlock led after pressing a NumLock key.

There has to be a conflict between X and this kind of code.

cbratschi
Posts: 7
Joined: Mon Oct 17, 2016 3:19 pm

Re: Full screen OpenGL ES on Pi 4

Sun Jul 14, 2019 5:03 pm

I am using a similar code to access OpenGL ES without any window server and I am always getting:

failed to add service - already in use?

This happens in the eglGetDisplay(displayType) call where the gbm_create_device(device) result is used. Tried to re-arranged the code but no different. I can get the screen resolution but not EGL to work.

My current implementation:

https://github.com/cbratschi/aminogfx-g ... rc/rpi.cpp

I quickly tried to compile your code but the EGL libs were not found. Could you please share the complete command line?

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Mon Jul 15, 2019 5:07 am

Save the code as drm-gbm-mod.c
Then gcc -o drm-gbm drm-gbm-mod.c -ldrm -lgbm -lEGL -lGL -I/usr/include/libdrm (the comment at the first line of the code)

cbratschi
Posts: 7
Joined: Mon Oct 17, 2016 3:19 pm

Re: Full screen OpenGL ES on Pi 4

Mon Jul 15, 2019 12:19 pm

pik33 wrote:
Mon Jul 15, 2019 5:07 am
Save the code as drm-gbm-mod.c
Then gcc -o drm-gbm drm-gbm-mod.c -ldrm -lgbm -lEGL -lGL -I/usr/include/libdrm (the comment at the first line of the code)
Yes, already tried this:

drm-gbm-mod.c:13:10: fatal error: EGL/egl.h: Datei oder Verzeichnis nicht gefunden
#include <EGL/egl.h>

It compiles with these modifications on Buster:

//#include <GL/gl.h>
#include "GLES2/gl2.h"

gcc -o drm-gbm drm-gbm-mod.c -ldrm -lgbm -lbrcmEGL -lbrcmGLESv2 -I/usr/include/libdrm -I/opt/vc/include/ -L/opt/vc/lib

cbratschi
Posts: 7
Joined: Mon Oct 17, 2016 3:19 pm

Re: Full screen OpenGL ES on Pi 4

Mon Jul 15, 2019 12:19 pm

And getting the same error:

* failed to add service - already in use?

Any ideas what could cause this?

User avatar
PeterO
Posts: 4727
Joined: Sun Jul 22, 2012 4:14 pm

Re: Full screen OpenGL ES on Pi 4

Mon Jul 15, 2019 12:27 pm

cbratschi wrote:
Mon Jul 15, 2019 12:19 pm
And getting the same error:

* failed to add service - already in use?

Any ideas what could cause this?
You're trying to run old code that uses the nolonger available drivers.
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

pik33
Posts: 137
Joined: Thu Sep 10, 2015 4:26 pm

Re: Full screen OpenGL ES on Pi 4

Mon Jul 15, 2019 2:21 pm

//#include <GL/gl.h>
#include "GLES2/gl2.h"
Maybe you had to install these libraries/headers. I tried to compile the code using another SD card with older Buster (I replaced it with bigger/faster one) and the compiler didn't found gbm.h. It means I had to install it later and I don't remember when and how. The most probable way is I searched a repoository for lacked .h files and installed *-devel packages with these .h files needed to compile the example.

It works for me in Buster/RPi4 4 GB in exactly this form as it is published here.

Return to “OpenGLES”