cdev-tux / q3lite

Q3lite, an OpenGL ES port of Quake III Arena for embedded Linux systems.
GNU General Public License v3.0
93 stars 16 forks source link

2D objects invisible when VC4 driver used on Raspberry Pi #4

Open jeremyvisser opened 6 years ago

jeremyvisser commented 6 years ago

The VC4 driver for Raspberry Pi allows use of Mesa instead of Broadcom-specific GL APIs.

Firstly, Q3lite runs normally and as expected with the default Broadcom GL libraries. But I wanted to run Q3lite with the VC4 driver, so I did this by first configuring my system to use VC4, then modifying the Makefile like so:

diff --git a/Makefile.q3lite b/Makefile.q3lite
index bd7929a..4101d0c 100644
--- a/Makefile.q3lite
+++ b/Makefile.q3lite
@@ -140,15 +140,16 @@ endif
     PI_CFLAGS=-march=armv8-a+crc -mfpu=vfpv4 -mtune=cortex-a53
   endif
   CFLAGS += -DHAVE_GLES $(PI_CFLAGS) -mfloat-abi=hard -Ofast -I/opt/vc/include
-  ifneq ($(wildcard /opt/vc/lib/libbrcmEGL.so),)
-    ifneq ($(wildcard /opt/vc/lib/libbrcmGLESv2.so),)
-      LDFLAGS += -L/opt/vc/lib -lbrcmEGL -lbrcmGLESv2
-    else
-      LDFLAGS += -L/opt/vc/lib -lEGL -lGLESv2
-    endif
-  else
-    LDFLAGS += -L/opt/vc/lib -lEGL -lGLESv2
-  endif
+  LDFLAGS += -lEGL -lGLESv2 -lGL

 endif #ifneq ($(PLATFORM_TYPE),)

Exactly how correct this approach was I'm unsure (having no GL experience whatsoever) but it at least compiled.

I ran it within an X11 session with the following parameters:

./quake3.armv7l \
  +set com_hunkMegs 192 \
  +set com_zoneMegs 24 \
  +set com_soundMegs 16 \
  +set vm_ui 2 \
  +set vm_cgame 2 \
  +set com_introplayed 1 \
  +set com_protocol 68 \
  +map q3dm1 \
  +set r_mode -1 \
  +set r_customwidth 1024 \
  +set r_customheight 768 \
  +set r_fullscreen 0

The game started, and I could see the map and walk around, but all 2D things were missing from the display, like my crosshair, health status, and the pull-down console.

I ran the game through apitrace and noticed the following errors:

99138: message: major api error 1: GL_INVALID_OPERATION in unsupported function called (unsupported extension or deprecated function?)
99138 @0 glOrthof(left = 0, right = 1920, bottom = 1080, top = 0, zNear = 0, zFar = 1)
99138: warning: glGetError(glOrthof) = GL_INVALID_OPERATION

According to the documentation, it appears the glOrthof() function doesn't exist in OpenGL ES 2.0, and hence not Mesa, but for some reason is included in the Broadcom ES 2.0 library anyway:

grep --files-with-matches glOrthof /opt/vc/lib/libbrcmGLESv2.so /lib/libGLESv2.so
/opt/vc/lib/libbrcmGLESv2.so

grep --files-without-match glOrthof /opt/vc/lib/libbrcmGLESv2.so /lib/libGLESv2.so
/lib/libGLESv2.so

I've attached the apitrace file. I'm not sure how portable this file is, but it reproduces the graphical issue nicely on my laptop with Intel graphics:

quake3.invisible.trace.gz

As VC4 is the long-term future of graphics on the Raspberry Pi, using more standard components of the Linux graphics stack (Mesa, DRM, KMS), it will be good to get Q3lite working in this situation.

cdev-tux commented 6 years ago

Hello,

Thank you for your feedback. It’s very timely as I’m currently researching the steps necessary to add support for the OpenGL+KMS driver. If you haven’t seen it, I also have an open request for help in the Contributing Guide for implementing Mesa driver support. The renderer used in Q3lite was borrowed from another project, so I don’t have the expertise to make modifications to the renderer itself. However, I’m looking into adding the framework to allow switching renderers, which will make it more modular and easier for testing.

Another user mentioned that he compiled Q3lite for the Mesa driver (dtoverlay=vc4-kms-v3d), and that he had to replace -lGLESv2 with -lGLESv1_CM to fix linker errors (the Q3lite renderer uses OpenGL ES v1.1). He mentioned that the menus weren’t visible and the rendering was choppy at 1080P. You may also want to try without the -lGL and see if that makes a difference.

Any help and feedback that you can offer would be much appreciated. Thanks again.

kenneth-Q commented 6 years ago

Thank for your try. Can you code the game and run in the window? I think sdl is for console only and it is not frandly with desktop environment.

I hope it will be batter.😃

cdev-tux commented 6 years ago

I'll have to look at the code when I get to that point, but I should be able to get it running in a window.

cdev-tux commented 6 years ago

I’ve added the initial framework to support the VC4 OpenGL driver. More changes to follow.

jdonald commented 5 years ago

Given so much has changed from Mesa 13 to Mesa 19 I gave this a try on my Pi 3B+ with Buster. Apparently it's fixed now (menus, crosshair, health status, and ~ pull-down console all render). This could be due to fixes in Mesa or one of the recent merges from ioq3 upstream.

I validated under both windowed mode in X11 and KMSDRM.

As @cdev-tux pointed out this is OpenGL ES 1.1, not 2.0, so the proper patch is:

diff --git a/Makefile.q3lite b/Makefile.q3lite
index d8521dec..6e2f57b2 100644
--- a/Makefile.q3lite
+++ b/Makefile.q3lite
@@ -149,15 +149,7 @@ endif
     PI_CFLAGS=-march=armv8-a+crc -mfpu=vfpv4 -mtune=cortex-a53
   endif
   CFLAGS += -DHAVE_GLES $(PI_CFLAGS) -mfloat-abi=hard -Ofast -I/opt/vc/include
-  ifneq ($(wildcard /opt/vc/lib/libbrcmEGL.so),)
-    ifneq ($(wildcard /opt/vc/lib/libbrcmGLESv2.so),)
-      LDFLAGS += -L/opt/vc/lib -lbrcmEGL -lbrcmGLESv2
-    else
-      LDFLAGS += -L/opt/vc/lib -lEGL -lGLESv2
-    endif
-  else
-    LDFLAGS += -L/opt/vc/lib -lEGL -lGLESv2
-  endif
+  LDFLAGS += -lEGL -lGLESv1_CM

 endif #ifneq ($(PLATFORM_TYPE),)

Note that we retain -I/opt/vc/include in compiler flags intentionally. Using /opt/vc/include/GLES is a workaround for Buster's removal of the GLES1 headers despite linking with Mesa's libGLESv1_CM.so. See raspberrypi/firmware#1171.

cdev-tux commented 5 years ago

@jdonald Thank you for taking the time to look into this. I’ll be testing the code over the next few days on a fresh install of Buster, since my current install may have some added packages that are preventing things from working properly. I did find that SDL was attempting to use its RPI legacy driver on the Pi4, which won’t work so they have some updating to do as well. Thanks again for your time and effort.

cdev-tux commented 5 years ago

Given so much has changed from Mesa 13 to Mesa 19 I gave this a try on my Pi 3B+ with Buster. Apparently it's fixed now (menus, crosshair, health status, and ~ pull-down console all render). This could be due to fixes in Mesa or one of the recent merges from ioq3 upstream.

I validated under both windowed mode in X11 and KMSDRM.

As @cdev-tux pointed out this is OpenGL ES 1.1, not 2.0, so the proper patch is:

diff --git a/Makefile.q3lite b/Makefile.q3lite
index d8521dec..6e2f57b2 100644
--- a/Makefile.q3lite
+++ b/Makefile.q3lite
@@ -149,15 +149,7 @@ endif
     PI_CFLAGS=-march=armv8-a+crc -mfpu=vfpv4 -mtune=cortex-a53
   endif
   CFLAGS += -DHAVE_GLES $(PI_CFLAGS) -mfloat-abi=hard -Ofast -I/opt/vc/include
-  ifneq ($(wildcard /opt/vc/lib/libbrcmEGL.so),)
-    ifneq ($(wildcard /opt/vc/lib/libbrcmGLESv2.so),)
-      LDFLAGS += -L/opt/vc/lib -lbrcmEGL -lbrcmGLESv2
-    else
-      LDFLAGS += -L/opt/vc/lib -lEGL -lGLESv2
-    endif
-  else
-    LDFLAGS += -L/opt/vc/lib -lEGL -lGLESv2
-  endif
+  LDFLAGS += -lEGL -lGLESv1_CM

 endif #ifneq ($(PLATFORM_TYPE),)

Note that we retain -I/opt/vc/include in compiler flags intentionally. Using /opt/vc/include/GLES is a workaround for Buster's removal of the GLES1 headers despite linking with Mesa's libGLESv1_CM.so. See raspberrypi/firmware#1171.

I'm still having some issues getting this to run in X11. When you have time could you post a /condump from the game console so I can see the output of the game loading? Thanks.

jdonald commented 5 years ago

Sorry for the delayed response.

By default, Raspbian compiles SDL2 with both rpi and x11 video support, but not kmsdrm. I expect they're going to keep rpi for a while as Raspbian needs to support the Pi 1 and Pi Zero. When debugging though, it's unfortunate that it comes earlier in the alphabet.

As for what's causing your issues: q3lite's build process appears to default to give the binary a linker path to a locally built SDL2 (/usr/local/lib), so for testing I would often override that at runtime. For example:

cd /usr/local/games/quake3
LD_LIBRARY_PATH=/usr/lib/arm-linux-gnueabihf ./quake3.armv7l

Sometimes I pass SDL_VIDEODRIVER=x11 explicitly to ensure it doesn't try rpi, but that isn't necessary as SDL2 will figure out what to do when running from an X session.

To double-check that it's always calling the particular libSDL2.so (and other libraries) you're intending, I recommend often using the ldd command.

cd /usr/local/games/quake3
LD_LIBRARY_PATH=/usr/lib/arm-linux-gnueabihf ldd ./quake3.armv7l

Note that due to the excess use of sudo in the /usr/local/bin/q3lite script, environment variables (including DISPLAY) get unintentionally dropped. I rarely use the q3lite wrapper script due to such issues.

When running X11 in full screen the stdout text (not a condump, but gets the point across) has what you'd expect:

...
----- Client Initialization Complete -----
----- R_Init -----
SDL using driver "x11"

For testing kmsdrm, that isn't available in the default Raspbian install so I would build a local SDL2 with:

    sudo apt install libdrm-dev libgbm-dev
    ./configure --enable-video-kmsdrm --disable-video-x11 --disable-video-rpi

And of course occasionally check with ldd to make sure your quake3.armv7l is loading the right libSDL2.so.

cdev-tux commented 5 years ago

Thanks for your response. Setting LD_LIBRARY_PATH=/usr/lib/arm-linux-gnueabihf allows the game to run in X11. I didn’t realize that Buster has an SDL2 package installed by default. Apparently my issue was caused by not compiling SDL2 with the proper settings.

For testing I’ve been compiling the latest SDL2-2.0.10 and using that instead of the shared library installed by Q3lite. This can be done by setting the following in make-raspberrypi.sh.

USE_LOCAL_HEADERS=0 Q3LITE_INSTALL_SDL=0

In the past Q3lite hasn’t been able to use the SDL2 package in the Raspbian repo because that package is compiled to use X11 first, and the game hasn’t been using X11 for performance reasons. If SDL2 is compiled from source it places libs in /usr/local/lib by default. Q3lite places its own compatible SDL2 shared library in /usr/local/lib/q3lite and uses rpath to look there first for SDL2, then in /usr/local/lib second. This has been necessary due to a Raspberry Pi specific SDL2 bug that affected 2.0.4+ and wasn’t fixed until 2.0.9. Anyway, that’s some background as to why paths are set up the way they are. It’s unlikely that I’ll be able to use the SDL2 package from the repository as the game needs to support OpenGL, legacy GLES, X11, and KMSDRM on a Pi 0-4. That’s not going to be an easy task.

I came to the same conclusion as you about using sudo in the wrapper script. I plan to remove that code while I’m in there adding Pi 4 support.

Things are working in KMSDRM, although at a low framerate for now.

Thanks again for your help; that got me going in the right direction.