feature: Add ability to draw to display directly from Python

This commit is contained in:
Tera << 8 2025-06-08 09:19:04 -04:00
parent 81b89a1a4f
commit d15a716476
Signed by: imterah
GPG key ID: 8FA7DD57BA6CEA37
8 changed files with 32 additions and 27 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "evdi"]
path = evdi
url = https://github.com/DisplayLink/evdi
[submodule "raylib-python-cffi"]
path = raylib-python-cffi
url = https://git.terah.dev/imterah/raylib-python-cffi

View file

@ -8,5 +8,13 @@ UnrealXR is a display multiplexer for the original Nreal Air (other devices may
2. Initialize the development shell: `nix-shell`
3. Create a virtual environment: `python3 -m venv .venv; source .venv/bin/activate`
4. Install Python dependencies: `pip install -r requirements.txt`
4. Build libevdi: `cd evdi/library; make -j$(nproc); cd ../..`
5. Build pyevdi: `cd evdi/pyevdi; make -j$(nproc); make install; cd ../..`
### Building `PyEvdi`
1. Build `libevdi`: `cd evdi/library; make -j$(nproc); cd ../..`
2. Build `PyEvdi`: `cd evdi/pyevdi; make -j$(nproc); make install; cd ../..`
### Building patched `PyRay`/`raylib`
1. Build the native version of raylib: `cd raylib-python-cffi/raylib-c; mkdir -p build/out; cd build; cmake -DCUSTOMIZE_BUILD=ON -DSUPPORT_FILEFORMAT_JPG=ON -DSUPPORT_FILEFORMAT_FLAC=ON -DWITH_PIC=ON -DCMAKE_BUILD_TYPE=Release -DPLATFORM=DRM -DENABLE_WAYLAND_DRM_LEASING=ON -DSUPPORT_CLIPBOARD_IMAGE=ON -DCMAKE_INSTALL_PREFIX:PATH=$PWD/out ..; make install -j$(nproc)`
2. Build the Python version of raylib: `cd ../..; PKG_CONFIG_PATH_FOR_TARGET="$PKG_CONFIG_PATH_FOR_TARGET:$PWD/raylib-c/build/out/lib64/pkgconfig/" PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PWD/raylib-c/build/out/lib64/pkgconfig/" ENABLE_WAYLAND_DRM_LEASING=YES RAYLIB_PLATFORM=DRM python3 setup.py bdist_wheel; pip install dist/*.whl`

10
main.py
View file

@ -8,6 +8,7 @@ from platformdirs import user_data_dir, user_config_dir
from loguru import logger
import PyEvdi
import pyedid
import pyray
import time
from render import render_loop
@ -160,6 +161,11 @@ def main():
atexit.register(unload_custom_fw)
input("Press the Enter key to continue loading after you unplug and plug in your XR device.")
# Raylib gets confused if there's multiple dri devices so we initialize the window before anything
logger.info("Initializing XR headset")
pyray.set_target_fps(edid.max_refresh_rate)
pyray.init_window(edid.max_width, edid.max_height, "UnrealXR")
logger.info("Initializing virtual displays")
cards = []
@ -173,9 +179,7 @@ def main():
atexit.register(lambda: card.close())
logger.info("Initialized displays")
logger.info("Beginning rendering")
logger.info("Initialized displays. Entering rendering loop")
render_loop(edid, cards)
if __name__ == "__main__":
print("Welcome to UnrealXR!\n")

1
raylib-python-cffi Submodule

@ -0,0 +1 @@
Subproject commit 1e195e4ac9b1dcd834fcf9c3d7bfc4e91bc10ecc

View file

@ -5,26 +5,10 @@ import pyray
from libunreal import EvdiDisplaySpec
def render_loop(display_metadata: EvdiDisplaySpec, cards: list[PyEvdi.Card]):
pyray.init_window(display_metadata.max_width, display_metadata.max_height, "UnrealXR")
while not pyray.window_should_close():
# Implement fullscreen toggle
if pyray.is_key_pressed(pyray.KeyboardKey.KEY_F11):
display = pyray.get_current_monitor()
if pyray.is_window_fullscreen():
pyray.set_window_size(display_metadata.max_width, display_metadata.max_height)
else:
pyray.set_window_size(pyray.get_monitor_width(display), pyray.get_monitor_height(display))
pyray.toggle_fullscreen()
# Ctrl-C to quit
elif pyray.is_key_down(pyray.KeyboardKey.KEY_LEFT_CONTROL) and pyray.is_key_down(pyray.KeyboardKey.KEY_C):
break
pyray.begin_drawing()
pyray.clear_background(pyray.BLACK)
pyray.draw_text("Hello world", 190, 200, 20, pyray.VIOLET)
pyray.draw_text("Hello world from Python!", 190, 200, 96, pyray.WHITE)
pyray.end_drawing()
logger.info("Goodbye!")

View file

@ -3,4 +3,5 @@ pybind11==2.13.6
pyedid==1.0.3
loguru==0.7.3
platformdirs==4.3.8
raylib==5.5.0.2
cffi=1.17.1
wheel=0.45.1

View file

@ -11,18 +11,22 @@
linuxHeaders
# raylib build dependencies
cmake
clang-tools
pkg-config
wayland
libGL
libgbm
libdrm
xorg.libXi
xorg.libXcursor
xorg.libXrandr
xorg.libXinerama
xorg.libX11
waylandpp
libxkbcommon
];
shellHook = ''
export LD_LIBRARY_PATH="$PWD/evdi/library:${pkgs.lib.makeLibraryPath [ pkgs.xorg.libX11 pkgs.libGL ]}:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="$PWD/evdi/library:${pkgs.lib.makeLibraryPath [ pkgs.libGL ]}:$LD_LIBRARY_PATH"
mkdir -p "$PWD/data/config" "$PWD/data/data"
export UNREALXR_CONFIG_PATH="$PWD/data/config"
export UNREALXR_DATA_PATH="$PWD/data/data"

View file

@ -1 +1 @@
sudo LD_LIBRARY_PATH="$LD_LIBRARY_PATH" UNREALXR_CONFIG_PATH="$UNREALXR_CONFIG_PATH" UNREALXR_DATA_PATH="$UNREALXR_DATA_PATH" python3 main.py
sudo LD_LIBRARY_PATH="$LD_LIBRARY_PATH" UNREALXR_CONFIG_PATH="$UNREALXR_CONFIG_PATH" UNREALXR_DATA_PATH="$UNREALXR_DATA_PATH" WAYLAND_DISPLAY="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" XDG_RUNTIME_DIR="/user/run/0" python3 main.py