bell-sw / Liberica

Free and 100% open source Progressive Java Runtime for modern Java™ deployments supported by a leading OpenJDK contributor
https://bell-sw.com/pages/libericajdk/
GNU General Public License v2.0
318 stars 29 forks source link

Problem running JavaFX on touch display using linux-aarch64 on Raspberry Pi 4 #97

Closed maebli closed 2 years ago

maebli commented 2 years ago

NOTE: This question is related to Issue https://github.com/bell-sw/Liberica/issues/43

AIM

I want to run liberica on my RPI4 for an application using JAVAFX to display a GUI on a 7'' touch display. OS on RPI4 is Debian/GNU Linux 11 (bullseye)

ISSUE DESCRIPTION

bellsoft-jdk17.0.4.1+1-linux-aarch64-full.tar.gz downloaded from liberica and installed on a RPI4. With the command:

I ran "sudo java -Dprism.verbose=true -jar NameFile.jar"

and got the following error output

Prism pipeline init order: es2 sw
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
        succeeded.
GLFactory using com.sun.prism.es2.X11GLFactory
(X) Got class = class com.sun.prism.es2.ES2Pipeline
GraphicsPipeline.createPipeline: error initializing pipeline com.sun.prism.es2.ES2Pipeline
*** Fallback to Prism SW pipeline
Prism pipeline name = com.sun.prism.sw.SWPipeline
(X) Got class = class com.sun.prism.sw.SWPipeline
Initialized prism pipeline: com.sun.prism.sw.SWPipeline
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082)
Caused by: java.lang.UnsupportedOperationException: Unable to open DISPLAY
        at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$new$6(GtkApplication.java:181)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
        at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:179)
        at javafx.graphics/com.sun.glass.ui.gtk.GtkPlatformFactory.createApplication(GtkPlatformFactory.java:41)
        at javafx.graphics/com.sun.glass.ui.Application.run(Application.java:146)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:291)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:293)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:163)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:659)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:410)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
        ... 5 more

Also tried with jdk11 from liberica andopenjfx installed separately and not bundled. I had to create a new class which I only needed to call the main function of another class and after added some libs in the java path and downloaded libGL.so.1 and I got a similar exception. JDK11 und OPENJFX

Prism pipeline init order: es2 sw
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
        succeeded.
GLFactory using com.sun.prism.es2.X11GLFactory
GLFactory com.sun.prism.es2.X11GLFactory@f676333 could not be initialized. ES2Pipeline not available.
(X) Got class = class com.sun.prism.es2.ES2Pipeline
GraphicsPipeline.createPipeline: error initializing pipeline com.sun.prism.es2.ES2Pipeline
Reason: could not create an instance
*** Fallback to Prism SW pipeline
Prism pipeline name = com.sun.prism.sw.SWPipeline
(X) Got class = class com.sun.prism.sw.SWPipeline
Initialized prism pipeline: com.sun.prism.sw.SWPipeline
Exception in thread "main" java.lang.UnsupportedOperationException: Unable to open DISPLAY
        at com.sun.glass.ui.gtk.GtkApplication.lambda$new$6(GtkApplication.java:202)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
        at com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:200)
        at com.sun.glass.ui.gtk.GtkPlatformFactory.createApplication(GtkPlatformFactory.java:41)
        at com.sun.glass.ui.Application.run(Application.java:146)
        at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:290)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:293)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:163)
        at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:659)
        at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:679)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
        at java.base/java.lang.Thread.run(Thread.java:833)

I tested also $export DISPLAY=0 without success. Also tested adding-X and -Yin the ssh connection without success.

SIMILAR, BUT WORKING SETUP

Using Java 8 from Oracle (which has also JavaFX included) running on a RPI3 Modul B+ everything works fine.

Running the code on my local computer (not an ARM) which has the jdk full from liberica, everything works fine.

AlexanderScherbatiy commented 2 years ago

Do you use ssh to run a JavaFX app on Raspbery Pi 4?

Could you set the DISPLAY to :0.0 in ssh and run the JavaFX program without sudo:

ssh login@host
export DISPLAY=:0.0
java JavaFXExample

If this works then root needs to be granted to have access to Xorg:

ssh login@host
export DISPLAY=:0.0
xhost +SI:localuser:root
sudo -E java JavaFXExample
maebli commented 2 years ago

Hi @AlexanderScherbatiy

Thanks for your comment.

I executed: export DISPLAY=:0.0(and tested other versions which I have found online)

With echo $DISPLAY I checked. This is fine.

The output of my application is still the same. Yes I have an ssh connection.

I tried also to connect a keyboard on the RPI an execute the jar file.

Output is still the same.

After execute:xhost +SI:localuser:root I got the following error

xhost: unable to open display "0.0"(Same error with ssh and local on RPI)

AlexanderScherbatiy commented 2 years ago

Could you run w command? It should show which display x session uses:

> w
 12:08:57 up 2 min,  2 users,  load average: 1,04, 1,00, 0,43
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
user     :0       :0               Вт14   ?xdm?   1:31   0.02s /usr/libexec/gdm-x-session --run-script env 

Could you also run xclock to check if a native X11 app can find the display?

maebli commented 2 years ago

Thanks again for your comment.

I ran the following commands:

MicrosoftTeams-image (1)

To make sure, that is not an ssh problem, I used a keyboard and let run the commands on the RPI. The weird thing is, as you can see in the picture, the display works. Ironically, if I execute libcamera-hello (via ssh) I can also see the output of the camera on the display. Connection with the display is DSI.

Thanks for your help.

AlexanderScherbatiy commented 2 years ago

There are several platforms which JavaFX can use.

The default one on Linux system is gtk which uses GTK library and requires X11 server running on the system and DISPLAY environment variable setting. The X11 server is included in Debian Bullseye with Raspberry Pi Desktop.

The another one is using JavaFX monocle: https://wiki.openjdk.org/display/OpenJFX/Monocle

sudo java -Dglass.platform=Monocle -Dmonocle.platform=Linux JavaFXExample

It should be run with sudo to have access to system events.

Only software pipeline is supported by JavaFX on Raspberry Pi 4 just because Broadcom restricts its EGL support on that system: https://github.com/raspberrypi/firmware/blob/ab68242d6131d078b757a6962d7b22a3da79d3d9/opt/vc/src/hello_pi/hello_triangle/triangle.c#L533

maebli commented 2 years ago

sudo java -Dglass.platform=Monocle -Dmonocle.platform=Linux JavaFXExample got us a step further! Currently, there is an unrelated issue that is keeping the application from launching, but I will report back when I know more, so we can close this issue.

Thanks again for the prompt support!

maebli commented 2 years ago

It's working now thank you very much!

EDIT: Adding info related

The setup is the following:

installedliberica jdk17.0.4 (This version is not the full and does not contain JavaFX) on the RPI4 Downloaded openjfx on my computer (javafx-sdk-18.0.2 Monocle version for Linux aarch64)

MicrosoftTeams-image (2)

I used IntelliJ as IDE and gradle for the setup. I created a jar file and copied it on the RPI4 In gradle, in the plugin section I wrote:id 'org.openjfx.javafxplugin' version '0.0.13'

And then wrote the following lines to import the modules:

javafx{    

sdk= 'C:/javafx-sdk-18.0.2'    

modules = ['javafx.controls', 'javafx.fxml']

}

The modules can also be added in the VM with --add module path (or something like that. A lot of tutorials online) I'm not developing on the RPI, but on my local computer and let run the application on the RPI.

The goal at the end, is to have an executable jar file. So I choose this solution.

The modules here are just the jar files which are located in the sdk folder I downloaded.

As advice: The downloaded folder contained other elements. I eliminated them and let only the lib folder

After I executed the jar on the RPI, I got an error like: JavaFX Runtime components missing

My main class looked like : public class NameClass extends Application

It seems that " extends Application" causes an issue. Other users created a class which only calls the main function of the class with “extend Application“ and solved the problem. I did the same and it worked.

Then I imported the librarys for JavaFX (or at least I think I can call them this way), which were in the downloaded folder (.so files) and I copied them in the path from which java takes the librarys. For me as example: /usr/lib

(I'm not sure but I think the .so file which contained monocle in the name and others are missing in the JDK FX from Liberica)

The error I got then was Caused by: java.lang.UnsatisfiedLinkError: /usr/lib/libjavafx_font_pango.so which called a missing .so file

So I installed:libpangoft2-1.0-0 (This was missing)

at the end I executed:

sudo java -Dglass.platform=Monocle -Dmonocle.platform=Linux -jar NameOfJarFile.jar

and it worked