Beagle Entertainment System (BES) on framebuffer

Andrew and all,

I’m looking to compile https://github.com/hendersa/bes for an Adafruit 1.8" SPI LCD and GPIO buttons.

I’m trying to integrate on top of Debian Jessie or Stretch. I plan to make the PRU updates to use remote-proc as that change looks pretty easy.

Do you compile BES without X11? I’m thinking that might be my issue, but I’m not sure how the various EGL headers get selected in Debian.

I’m getting the following error:

g++ -I. -Ines -Isqlite -c -O3 -fomit-frame-pointer -pedantic -Wall -W -Wno-unused-parameter -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -DFRAMESKIP -DNO_FFMPEG -DFINAL_VERSION -DSDL -DNO_LINK -DC_CORE -DNO_ASM -DZLIB -DHAVE_LIBPNG -DHAVE_MKSTEMP -DHAVE_STRINGS_H -DHAVE_SYS_IOCTL_H -DHAVE_STDINT_H eglSetup.cpp -o eglSetup.o
eglSetup.cpp: In function ‘int EGLInitialize()’:
eglSetup.cpp:123:64: error: invalid conversion from ‘EGLSurface {aka void*}’ to ‘EGLNativeWindowType {aka long unsigned int}’ [-fpermissive]
surface = eglCreateWindowSurface(display, config, window, 0);
^
Makefile:75: recipe for target ‘eglSetup.o’ failed
make: *** [eglSetup.o] Error 1

Here’s what I have in my include file:
/usr/include/EGL/egl.h:EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);

/usr/include/EGL/egl.h:typedef void *EGLSurface;

/usr/include/EGL/eglplatform.h:typedef EGLNativeWindowType NativeWindowType;

I’m thinking I can just adjust the BES source to use (NativeWindow)X, where X is my framebuffer, but https://e2e.ti.com/support/embedded/linux/f/354/t/116795 points to problems specifying any framebuffer other than 0. Is hacking on eglSetup.cpp what I should be doing or will it be fruitless?

Regards,

Jason

BES is built without X, as it uses SGX OpenGL ES on the framebuffer. SDL 1.2 initializes for ALSA audio, input via the framebuffer (i.e. keyboard
input) and Linux joystick devices, and video using full-screen 16 BPP with
the framebuffer target. I fill the framebuffer with all black pixels and
then ignore it (so no SDL_Flip() or SDL_UpdateRect() calls). The emulators render into SDL_Surfaces, and I take the pixel data of these surfaces, copy them into GLES textures, and then map those textures onto a pair of triangles covering the entire screen. This gives me scaling and bilinear filtering to any size display without requiring a software scaler.

Whenever I'm going to process the SDL event loop, I first check the BBB-specific inputs (PRU gamepads or GPIO inputs), generate the appropriate SDL_Events to represent input events, and then add those key events into the SDL event queue as key events. Then I do the SDL event loop and process key and joystick events as I normally would. This makes the hardware-specific inputs appear as keypresses to the emulators and
front-end GUI. The block of GPIOs I use for the 12 gamepad inputs (4 d-pad, 8 buttons, 1 pause button) are the pins on the P8 header that aren't blocked by the LCD3 cape. If you want to change the GPIOs that are used, the GPIO numbers are stored in BES's SQL database.

As for your EGL error, I suspect it is a change in datatype definitions.
I've had a few people mention similar things regarding EGL. Don't install
the Mesa headers. Or rather, the Mesa OpenGL headers should be OK, but the
EGL ones will not be. Instead, point to the reference implementation
headers from Khronos:

https://www.khronos.org/registry/EGL/api/EGL/

An apt-get of the Mesa EGL headers will get headers intended to run on an
X11-based system. Look at the Khronos API reference for eglCreateWindowSurface():

https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglCreateWindowSurface.xhtml

The third parameter is of type NativeWindowType, which is intended to be a
"placeholder" for the proper datatype. Now look at the Mesa and Khronos
reference headers:

https://github.com/mesa3d/mesa/blob/master/include/EGL/egl.h
https://www.khronos.org/registry/EGL/api/EGL/egl.h

These two list the third parameter as having the type EGLNativeWindowType.
As the API changes, it must remain binary compatible with older versions
of the GLES libraries. The actual datatype of EGLNativeWindowType varies a
lot depending upon the particular platform you are working on, and the
Mesa and Khronos reference implementations differ in that regard:

https://github.com/mesa3d/mesa/blob/master/include/EGL/eglplatform.h
https://www.khronos.org/registry/EGL/api/EGL/eglplatform.h

So, use the Khronos EGL headers, not the ones from Mesa, and you should
get a clean build. Alternatively, you can force a cast on that parameter and it will probably work for you OK.

I've been meaning to get around to putting some fixes into BES and clean up its code in the next month or two, so I'll pull in any patches that you want to throw my way.

Andrew

BES is built without X, as it uses SGX OpenGL ES on the framebuffer. SDL
1.2 initializes for ALSA audio, input via the framebuffer (i.e. keyboard
input) and Linux joystick devices, and video using full-screen 16 BPP with
the framebuffer target. I fill the framebuffer with all black pixels and
then ignore it (so no SDL_Flip() or SDL_UpdateRect() calls). The emulators
render into SDL_Surfaces, and I take the pixel data of these surfaces,
copy them into GLES textures, and then map those textures onto a pair of
triangles covering the entire screen. This gives me scaling and bilinear
filtering to any size display without requiring a software scaler.

Whenever I’m going to process the SDL event loop, I first check the
BBB-specific inputs (PRU gamepads or GPIO inputs), generate the
appropriate SDL_Events to represent input events, and then add those key
events into the SDL event queue as key events. Then I do the SDL event
loop and process key and joystick events as I normally would. This makes
the hardware-specific inputs appear as keypresses to the emulators and
front-end GUI. The block of GPIOs I use for the 12 gamepad inputs (4
d-pad, 8 buttons, 1 pause button) are the pins on the P8 header that
aren’t blocked by the LCD3 cape. If you want to change the GPIOs that are
used, the GPIO numbers are stored in BES’s SQL database.

As for your EGL error, I suspect it is a change in datatype definitions.
I’ve had a few people mention similar things regarding EGL. Don’t install
the Mesa headers. Or rather, the Mesa OpenGL headers should be OK, but the
EGL ones will not be. Instead, point to the reference implementation
headers from Khronos:

https://www.khronos.org/registry/EGL/api/EGL/

An apt-get of the Mesa EGL headers will get headers intended to run on an
X11-based system. Look at the Khronos API reference for
eglCreateWindowSurface():

https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglCreateWindowSurface.xhtml

The third parameter is of type NativeWindowType, which is intended to be a
“placeholder” for the proper datatype. Now look at the Mesa and Khronos
reference headers:

https://github.com/mesa3d/mesa/blob/master/include/EGL/egl.h
https://www.khronos.org/registry/EGL/api/EGL/egl.h

These two list the third parameter as having the type EGLNativeWindowType.
As the API changes, it must remain binary compatible with older versions
of the GLES libraries. The actual datatype of EGLNativeWindowType varies a
lot depending upon the particular platform you are working on, and the
Mesa and Khronos reference implementations differ in that regard:

https://github.com/mesa3d/mesa/blob/master/include/EGL/eglplatform.h
https://www.khronos.org/registry/EGL/api/EGL/eglplatform.h

So, use the Khronos EGL headers, not the ones from Mesa, and you should
get a clean build. Alternatively, you can force a cast on that parameter
and it will probably work for you OK.

I’ve been meaning to get around to putting some fixes into BES and clean
up its code in the next month or two, so I’ll pull in any patches that you
want to throw my way.

Awesome, thanks.

It seems you are still linking in libX11. Is that right?

X11 is linked in because I apt-get the SDL 1.2 library, which has X11 as a package dependency. I don't actually use X11 for anything. If you were to build a bare-bones SDL 1.2 from source, you could remove the need to link in X11.

FYI, I have spoken with Ryan Gordon (one of the SDL maintainers) about a BeagleBone target in SDL 2.x. Raspberry Pi already has its own target, and I thought that having a BB target providing similar functionality would make things simple for everyone trying to get GLES, audio, input, etc. working on the platform. But, that discussion was maybe two years ago, when SGX support was in one kernel version and not in the next, HDMI audio was squirrelly, etc. Ryan left the door open for us to provide a patch for SDL 2.0 whenever we'd like, though, so it might be a good time to revisit that if the kernel and Debian filesystem are where they need to be to support such things.

Andrew

v4.13.x-bone still has compatibly with that ancient SGX release, hdmi
audio is mainline now, so maybe it'll work.

Regards,

X11 is linked in because I apt-get the SDL 1.2 library, which has X11 as a
package dependency. I don’t actually use X11 for anything. If you were to
build a bare-bones SDL 1.2 from source, you could remove the need to link in
X11.

FYI, I have spoken with Ryan Gordon (one of the SDL maintainers) about a
BeagleBone target in SDL 2.x. Raspberry Pi already has its own target, and I
thought that having a BB target providing similar functionality would make
things simple for everyone trying to get GLES, audio, input, etc. working on
the platform. But, that discussion was maybe two years ago, when SGX support
was in one kernel version and not in the next, HDMI audio was squirrelly,
etc. Ryan left the door open for us to provide a patch for SDL 2.0 whenever
we’d like, though, so it might be a good time to revisit that if the kernel
and Debian filesystem are where they need to be to support such things.

v4.13.x-bone still has compatibly with that ancient SGX release, hdmi
audio is mainline now, so maybe it’ll work.

Why not just specify the SGX release and kernel you want?

Jason,

I think this is a bug in the code

https://github.com/hendersa/bes/blob/v0.1/src/eglSetup.cpp

At line 23 I see

static EGLSurface window = EGL_NO_SURFACE;

whereas 'window' should be of type EGLNativeWindowType.

It (window) should be initialised either to 0 for a 'default' window (which is probably why the code at some point compiled on a compiler that didn't worry so much about the type mismatch) or to some kind of platform/OS/window manager specific thing.

Given that the code only includes X11 headers when building for PC_PLATFORM it appears you might get away with setting this to 0 and expecting it to take over the whole screen? Does that sound plausible (sorry I'm not familiar with BES).

i.e.

static EGLNativeWindowType window = 0; // or possibly (void*)0; depending on the underlying type

Hope that helps
Robert